Singleton resources
APIs sometimes need to represent a resource where exactly one instance of the resource always exists within any given parent. A common use case for this is for a config object.
Guidance
An API may define singleton resources. A singleton resource must always exist by virtue of the existence of its parent, with one and exactly one per parent.
For example:
message Config { option (google.api.resource) = { type: "api.example.com/Config" pattern: "users/{user}/config" };
// additional fields including name}
The Config
singleton would have the following RPCs:
rpc GetConfig(GetConfigRequest) returns (Config) { option (google.api.http) = { get: "/v1/{name=users/*/config}" };}
rpc UpdateConfig(UpdateConfigRequest) returns (Config) { option (google.api.http) = { patch: "/v1/{config.name=users/*/config}" body: "config" };}
components: schemas: Config: type: object properties: name: type: string # additional properties... required: - name parameters: user: in: path name: user required: true schema: type: string
The Config
singleton would have the following methods:
paths: users/{user}/config: get: operationId: getUserConfig parameters: - $ref: '#/components/parameters/user' responses: '200': content: application/json: schema: $ref: '#/components/schemas/Config' patch: operationId: updateUserConfig parameters: - $ref: '#/components/parameters/user' requestBody: content: application/json: schema: $ref: '#/components/schemas/Config' responses: '200': content: application/json: schema: $ref: '#/components/schemas/Config'
- Singleton resources must not have a user-provided or system-generated ID;
their resource name includes the name of their parent followed by
one static-segment.
- Example:
users/1234/config
- Example:
- Singleton resources are always singular.
- Example:
users/1234/thing
- Example:
- Singleton resources may parent other resources.
- Singleton resources must not define the
Create
orDelete
standard methods. The singleton is implicitly created or deleted when its parent is created or deleted. - Singleton resources should define the
Get
andUpdate
methods, and may define custom methods as appropriate.- However, singleton resources must not define the
Update
method if all fields on the resource are output only.
- However, singleton resources must not define the
- Singleton resources may define the
List
method, but must implement it according to AEP-159. See the example below.- The trailing segment in the path pattern that typically represents the
collection should be the
plural
form of the Singleton resource e.g./v1/{parent=users/*}/configs
. - If a parent resource ID is provided instead of the hyphen
-
as per AEP-159, then the service should return a collection of one Singleton resource corresponding to the specified parent resource.
- The trailing segment in the path pattern that typically represents the
collection should be the
rpc ListConfigs(ListConfigsRequest) returns (ListConfigsResponse) { option (google.api.http) = { get: "/v1/{parent=users/*}/configs" };}
message ListConfigsRequest { // To list all configs, use `-` as the user id. // Formats: // * `users/-` // * `users/{user}` // // Note: Specifying an actual user id will return a collection of one config. // Use GetConfig instead. string parent = 1 [ (google.api.resource_reference).child_type = "api.example.com/Config"];
// other standard pagination fields...}
components: schemas: UserConfigCollection: type: object properties: configs: type: array items: '$ref': '#/components/schemas/Config'
paths: users/-/configs: get: operationId: listUserConfigs # standard pagination parameters... responses: '200': content: application/json: schema: $ref: '#/components/schemas/UserConfigCollection'
Rationale
Support for Standard List
While Singleton resources are not directly part of a collection themselves, they can be viewed as part of their parent’s collection. The one-to-one relationship of parent-to-singleton means that for every one parent there is one singleton instance, naturally enabling some collection-based methods when combined with the pattern of Reading Across Collections. The Singleton can present as a collection to the API consumer as it is indirectly one based on its parent. Furthermore, presenting the Singleton resource as a pseudo-collection in such methods enables future expansion to a real collection, should a Singleton be found lacking.