AIP-162
Resource Revisions
Some APIs need to have resources with a revision history, where users can reason about the state of the resource over time. There are several reasons for this:
- Users may want to be able to roll back to a previous revision, or diff against a previous revision.
- An API may create data which is derived in some way from a resource at a given point in time. In these cases, it may be desirable to snapshot the resource for reference later.
Note: We use the word revision to refer to a historical reference for a particular resource, and intentionally avoid the term version, which refers to the version of an API as a whole.
Guidance
APIs may store a revision history for a resource. Examples of when it is useful include:
- When it is valuable to expose older versions of a resource via an API. This can avoid the overhead of the customers having to write their own API to store and enable retrieval of revisions.
- Other resources depend on different revisions of a resource.
- There is a need to represent the change of a resource over time.
APIs implementing resources with a revision history should abstract resource revisions as nested collection of the resource. Sometimes, the revisions collection can be a top level collection, exceptions include:
- If resource revisions are meant to have longer lifespan than the parent resource. In other words, resource revisions exist after resource deletion.
message BookRevision {
// The name of the book revision.
string name = 1;
// The snapshot of the book
Book snapshot = 2
[(google.api.field_behavior) = OUTPUT_ONLY];
// The timestamp that the revision was created.
google.protobuf.Timestamp create_time = 3
[(google.api.field_behavior) = OUTPUT_ONLY];
// Other revision IDs that share the same snapshot.
repeated string alternate_ids = 4
[(google.api.field_behavior) = OUTPUT_ONLY];
}
- The
messagemust be annotated as a resource (AIP-123). - The
messagename must be named{ResourceType}Revision. - The resource revision must contain a field with a message type of the
parent resource, with a field name of
snapshot.- The value of
snapshotmust be the configuration of the parent at the point in time the revision was created.
- The value of
- The resource revision must contain a
create_timefield (see AIP-142). - The resource revision may contain a repeated field
alternate_ids, which would contain a list of resource IDs that the revision is also known by (e.g.latest)
Creating Revisions
Depending on the resource, different APIs may have different strategies for
- Create a new revision any time that there is a change to the parent resource
- Create a new revision when important system state changes
- Create a new revision when specifically requested
APIs may use any of these strategies. APIs must document their revision creation strategy.
Resource names for revisions
When referring to specific revision of a resource, the subcollection name
must be named revisions. Resource revisions have names with the format
{resource_name}/revisions/{revision_id}. For example:
publishers/123/books/les-miserables/revisions/c7cfa2a8
Server-specified Aliases
Services may reserve specific IDs to be aliases (e.g.
latest). These are read-only and managed by the service.
GET /v1/publishers/{publisher}/books/{book}/revisions/{revision_id}
- If a
latestID exists, it must represent the most recently created revision. The content ofpublishers/{publisher}/books/{book}/revisions/latestandpublishers/{publisher}/books/{book}can differ, as the latest revision may be different from the current state of the resource.
User-Specified Aliases
APIs may provide a mechanism for users to assign an alias ID to an existing revision with a custom method "alias":
rpc AliasBookRevision(AliasBookRevisionRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{name=publishers/*/books/*/revisions/*}:alias"
body: "*"
};
}
message AliasBookRevisionRequest {
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
type: "library.googleapis.com/BookRevision"
}];
// The ID of the revision to alias to, e.g. `CURRENT` or a semantic
// version.
string alias_id = 2 [(google.api.field_behavior) = REQUIRED];
}
- The request message must have a
namefield:- The field must be annotated as required.
- The field must identify the resource type that it references.
- The request message must have a
alias_idfield:
View on GitHub