diff --git a/container/service.proto b/container/service.proto
index 976c04ed..6fa72b02 100644
--- a/container/service.proto
+++ b/container/service.proto
@@ -78,6 +78,9 @@ service ContainerService {
// - Common failures (SECTION_FAILURE_COMMON);
// - **CONTAINER_AWAIT_TIMEOUT** (3075, SECTION_CONTAINER): \
// transaction was sent but not executed within the deadline.
+ // - **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ // if requester attached container revision he knows and it does not match
+ // the server's one.
rpc SetExtendedACL(SetExtendedACLRequest) returns (SetExtendedACLResponse);
// Returns Extended ACL table and signature from `Container` smart contract
@@ -115,6 +118,9 @@ service ContainerService {
// - Common failures (SECTION_FAILURE_COMMON);
// - **CONTAINER_AWAIT_TIMEOUT** (3075, SECTION_CONTAINER): \
// transaction was sent but not executed within the deadline.
+ // - **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ // if requester attached container revision he knows and it does not match
+ // the server's one.
rpc SetAttribute(SetAttributeRequest) returns (SetAttributeResponse);
// Sends transaction calling contract method to remove container attribute,
@@ -128,6 +134,9 @@ service ContainerService {
// - Common failures (SECTION_FAILURE_COMMON);
// - **CONTAINER_AWAIT_TIMEOUT** (3075, SECTION_CONTAINER): \
// transaction was sent but not executed within the deadline.
+ // - **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ // if requester attached container revision he knows and it does not match
+ // the server's one.
rpc RemoveAttribute(RemoveAttributeRequest) returns (RemoveAttributeResponse);
}
@@ -336,7 +345,8 @@ message ListResponse {
neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
}
-// Set Extended ACL
+// Set Extended ACL.
+// Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
message SetExtendedACLRequest {
// Set Extended ACL request body does not have separate `ContainerID`
// reference. It will be taken from `EACLTable.container_id` field.
@@ -495,7 +505,8 @@ message AnnounceUsedSpaceResponse {
neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
}
-// Attribute setting request
+// Attribute setting request.
+// Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
message SetAttributeRequest {
// Request payload message.
message Body {
@@ -568,7 +579,8 @@ message SetAttributeResponse {
neo.fs.v2.status.Status status = 1;
}
-// Attribute removal request
+// Attribute removal request.
+// Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
message RemoveAttributeRequest {
// Request payload message.
message Body {
diff --git a/container/types.proto b/container/types.proto
index 86e3b0ab..dcf95944 100644
--- a/container/types.proto
+++ b/container/types.proto
@@ -116,4 +116,17 @@ message Container {
// Placement policy for the object inside the container
neo.fs.v2.netmap.PlacementPolicy placement_policy = 6 [json_name = "placementPolicy"];
+
+ // Container revision. It increments every time container's properties are
+ // changed by the owner (or the owner itself is changed).
+ //
+ // Do not confuse it with API version: this field describes how many times
+ // container has been changed since its creation, while API version describes
+ // proto message format.
+ //
+ // It must only be set by storage nodes and must not be filled on the client
+ // side. The initial revision after a successful container creation call is 0.
+ //
+ // Versioned containers are available starting from API v2.27.0.
+ uint64 revision = 7 [json_name = "revision"];
}
diff --git a/object/service.proto b/object/service.proto
index b275fbfc..82e4e963 100644
--- a/object/service.proto
+++ b/object/service.proto
@@ -80,6 +80,9 @@ service ObjectService {
// size quota set by user was exceeded;
// - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
// object storage container not found;
+ // - **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ // if requester attached container revision he knows and it does not match
+ // the server's one.
// - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \
// (for trusted object preparation) session private key does not exist or has
// been deleted;
@@ -112,6 +115,9 @@ service ObjectService {
// deleting a locked object is prohibited;
// - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
// object container not found;
+ // - **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ // if requester attached container revision he knows and it does not match
+ // the server's one.
// - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
// provided session token has expired.
rpc Delete(DeleteRequest) returns (DeleteResponse);
@@ -167,6 +173,9 @@ service ObjectService {
// access to operation SEARCH of the object is denied;
// - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
// search container not found;
+ // - **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ // if requester attached container revision he knows and it does not match
+ // the server's one.
// - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
// provided session token has expired.
rpc Search(SearchRequest) returns (stream SearchResponse);
@@ -393,7 +402,8 @@ message GetResponse {
neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
}
-// PUT object request
+// PUT object request.
+// Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
message PutRequest {
// PUT request body
message Body {
@@ -459,7 +469,8 @@ message PutResponse {
neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
}
-// Object DELETE request
+// Object DELETE request.
+// Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
message DeleteRequest {
// Object DELETE request body
message Body {
@@ -639,7 +650,8 @@ message SearchResponse {
neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
}
-// Object SearchV2 request
+// Object SearchV2 request.
+// Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
message SearchV2Request {
// Object Search request body
message Body {
diff --git a/proto-docs/container.md b/proto-docs/container.md
index e9aee69a..9cf58c9c 100644
--- a/proto-docs/container.md
+++ b/proto-docs/container.md
@@ -167,6 +167,9 @@ Statuses:
- Common failures (SECTION_FAILURE_COMMON);
- **CONTAINER_AWAIT_TIMEOUT** (3075, SECTION_CONTAINER): \
transaction was sent but not executed within the deadline.
+- **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ if requester attached container revision he knows and it does not match
+ the server's one.
| Name | Input | Output |
| ---- | ----- | ------ |
@@ -216,6 +219,9 @@ Statuses:
- Common failures (SECTION_FAILURE_COMMON);
- **CONTAINER_AWAIT_TIMEOUT** (3075, SECTION_CONTAINER): \
transaction was sent but not executed within the deadline.
+- **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ if requester attached container revision he knows and it does not match
+ the server's one.
| Name | Input | Output |
| ---- | ----- | ------ |
@@ -233,6 +239,9 @@ Statuses:
- Common failures (SECTION_FAILURE_COMMON);
- **CONTAINER_AWAIT_TIMEOUT** (3075, SECTION_CONTAINER): \
transaction was sent but not executed within the deadline.
+- **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ if requester attached container revision he knows and it does not match
+ the server's one.
| Name | Input | Output |
| ---- | ----- | ------ |
@@ -571,7 +580,8 @@ returned here to make sure everything has been done as expected.
### Message RemoveAttributeRequest
-Attribute removal request
+Attribute removal request.
+Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
| Field | Type | Label | Description |
@@ -637,7 +647,8 @@ Attribute removal response
### Message SetAttributeRequest
-Attribute setting request
+Attribute setting request.
+Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
| Field | Type | Label | Description |
@@ -708,7 +719,8 @@ Attribute setting response
### Message SetExtendedACLRequest
-Set Extended ACL
+Set Extended ACL.
+Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
| Field | Type | Label | Description |
@@ -784,6 +796,13 @@ of stable-marshalled container message.
| basic_acl | [uint32](#uint32) | | `BasicACL` contains access control rules for the owner, system and others groups, as well as permission bits for `BearerToken` and `Extended ACL` |
| attributes | [Container.Attribute](#neo.fs.v2.container.Container.Attribute) | repeated | Attributes represent immutable container's meta data |
| placement_policy | [neo.fs.v2.netmap.PlacementPolicy](#neo.fs.v2.netmap.PlacementPolicy) | | Placement policy for the object inside the container |
+| revision | [uint64](#uint64) | | Container revision. It increments every time container's properties are changed by the owner (or the owner itself is changed).
+
+Do not confuse it with API version: this field describes how many times container has been changed since its creation, while API version describes proto message format.
+
+It must only be set by storage nodes and must not be filled on the client side. The initial revision after a successful container creation call is 0.
+
+Versioned containers are available starting from API v2.27.0. |
diff --git a/proto-docs/object.md b/proto-docs/object.md
index d6e53769..9229cc25 100644
--- a/proto-docs/object.md
+++ b/proto-docs/object.md
@@ -170,6 +170,9 @@ Statuses:
size quota set by user was exceeded;
- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
object storage container not found;
+- **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ if requester attached container revision he knows and it does not match
+ the server's one.
- **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \
(for trusted object preparation) session private key does not exist or has
been deleted;
@@ -206,6 +209,9 @@ Statuses:
deleting a locked object is prohibited;
- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
object container not found;
+- **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ if requester attached container revision he knows and it does not match
+ the server's one.
- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
provided session token has expired.
@@ -269,6 +275,9 @@ Statuses:
access to operation SEARCH of the object is denied;
- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
search container not found;
+- **CONTAINER_REVISION_MISMATCH** (3076, SECTION_CONTAINER): \
+ if requester attached container revision he knows and it does not match
+ the server's one.
- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
provided session token has expired.
@@ -420,7 +429,8 @@ Statuses:
### Message DeleteRequest
-Object DELETE request
+Object DELETE request.
+Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
| Field | Type | Label | Description |
@@ -771,7 +781,8 @@ following steps:
### Message PutRequest
-PUT object request
+PUT object request.
+Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
| Field | Type | Label | Description |
@@ -961,7 +972,8 @@ Object Search response body
### Message SearchV2Request
-Object SearchV2 request
+Object SearchV2 request.
+Behaviour can be augmented with __NEOFS__CONTAINER_REVISION x-header.
| Field | Type | Label | Description |
diff --git a/proto-docs/session.md b/proto-docs/session.md
index 7ce058f4..3a1f72d8 100644
--- a/proto-docs/session.md
+++ b/proto-docs/session.md
@@ -396,6 +396,14 @@ affect system behaviour:
how many past epochs the node can look up through. The `value` is string
encoded `uint64` in decimal presentation. If set to '0' or not set, only the
current epoch will be used. DEPRECATED: header ignored by servers.
+* __NEOFS__CONTAINER_REVISION \
+ Starting from API v2.27.0 and for a limited set of requests only, requester
+ can attach container revision to extended headers to ensure container state
+ is up to date. If server's known revision does not match the requested one,
+ it must return **CONTAINER_REVISION_MISMATCH** (3076) response status with
+ no payload.
+ Value format: a positive base-10 integer counter with no leading zeros.
+ Check request's description to see if this header is supported.
| Field | Type | Label | Description |
diff --git a/proto-docs/status.md b/proto-docs/status.md
index 3dcc13c1..9a49dd11 100644
--- a/proto-docs/status.md
+++ b/proto-docs/status.md
@@ -106,6 +106,7 @@ Section of statuses for container-related operations.
| EACL_NOT_FOUND | 1 | [**3073**] eACL table not found. |
| CONTAINER_LOCKED | 2 | [**3074**] Operation rejected by the container lock. |
| CONTAINER_AWAIT_TIMEOUT | 3 | [**3075**] Async container operation timed out. |
+| CONTAINER_VERSION_MISMATCH | 4 | [**3076**] Requested operation with container is not in sync: container revision does not meet the server's one. Can be returned only if requester provides container version he has, see requests documentation for more info. |
diff --git a/session/types.proto b/session/types.proto
index 81b9cc2b..452cd4ab 100644
--- a/session/types.proto
+++ b/session/types.proto
@@ -203,6 +203,14 @@ message SessionToken {
// how many past epochs the node can look up through. The `value` is string
// encoded `uint64` in decimal presentation. If set to '0' or not set, only the
// current epoch will be used. DEPRECATED: header ignored by servers.
+// * __NEOFS__CONTAINER_REVISION \
+// Starting from API v2.27.0 and for a limited set of requests only, requester
+// can attach container revision to extended headers to ensure container state
+// is up to date. If server's known revision does not match the requested one,
+// it must return **CONTAINER_REVISION_MISMATCH** (3076) response status with
+// no payload.
+// Value format: a positive base-10 integer counter with no leading zeros.
+// Check request's description to see if this header is supported.
message XHeader {
// Key of the X-Header
string key = 1 [json_name = "key"];
diff --git a/status/types.proto b/status/types.proto
index d993f045..74dbaeb9 100644
--- a/status/types.proto
+++ b/status/types.proto
@@ -158,6 +158,12 @@ enum Container {
// [**3075**] Async container operation timed out.
CONTAINER_AWAIT_TIMEOUT = 3;
+
+ // [**3076**] Requested operation with container is not in sync: container
+ // revision does not meet the server's one. Can be returned only if requester
+ // provides container version he has, see requests documentation for more
+ // info.
+ CONTAINER_VERSION_MISMATCH = 4;
}
// Section of statuses for session-related operations.