As a user, I want to create an update
. The update
take a manifest
as input. I do not get a chance to give my update a name - the name is generated by the service. Creating the update
can take a long time, and the process can fail in ways that cannot be validated on the initial request since the validation is too costly. If the create fails at any point in time, no update
resource will be created.
It is tempting to, as an implementor of a service, use globally unique identifiers as keys. However, if there is any possibilty to use a natural key, that is preferred. Humans are bad a remembering GUIDs. A hybrid apprach is to allow the user to optionally specify a key, and generate a key if one is not provided. The hybrid apprach makes it possible to make the operation idempotent.
There is no need for me (as a user) to list all updates that are being created at any given time. Only the user who is creating a user (or someone they hand off the process to) need to monitor the progress.
This requirement - or lack thereof - generally maps to if there is a resource that the user creates the lifetime of when the create runs. In this case, the
job
resource is automatically expired/deleted after 72hrs. There are also no easily identifiable properties on thejob
resource that a user might want to see.
Since the service supports generation of resource ids for updates, the corresponding HTTP method is POST.
The canonical target URL is the collection resource for updates.
If the service allowed the client to set the name, the http method would be PUT, and the target URL would be the update item - e.g.
/updates/mypreferredname
.
Request:
HTTP/1.1 POST /updates
Content-Type: application/json
{
...
}
Response:
HTTP/1.1 202 OK
Operation-Location: /operations/1234
Request:
HTTP/1.1 GET /operations/1234
Response:
HTTP/1.1 200 OK
Retry-After: 37
{
"status": "creating"
}
...
Request:
HTTP/1.1 GET /operations/1234
Response:
HTTP/1.1 200 OK
{
"status": "succeeded",
"resourceLocation": "/updates/7891"
}
...or (in case of failure)...
HTTP/1.1 200 OK
{
"status": "failed",
"error": {
}
}
Create the update resource immediately and track the creation progress on the update resource itself. If possible, this (resource based long running operation/RELO) is the preferred API pattern since it is simpler for the client to understand (no custom redirects needed). The main differences between this and the current approach are:
- The resource will be created and remain even in the case of failure. It is possible, but uncommon, to automatically clean up failed resources.
- Clients can see all
update
resources that are being created. This is generally a good thing, but it does mean that the client has to check the status before they try to apply the update. - Signalling custom progress/status of the operation becomes slightly less elegant since you end up with fields on the
update
resource that only applies while the resource is being created. - It is not possible to track multiple parallel operations. For create operations, this is a non issue (you can only create a given resource once).