|
| 1 | +# Long-running requests |
| 2 | + |
| 3 | +Occasionally, a service may need to expose an operation that takes a |
| 4 | +significant amount of time to complete. In these situations, it is often a poor |
| 5 | +user experience to simply block while the task runs; rather, it is better to |
| 6 | +return some kind of promise to the user, and allow the user to check back in |
| 7 | +later. |
| 8 | + |
| 9 | +The long-running request pattern is roughly analogous to a [Future][] in Python |
| 10 | +or Java, or a [Node.js Promise][]. Essentially, the user is given a token that |
| 11 | +can be used to track progress and retrieve the result. |
| 12 | + |
| 13 | +## Guidance |
| 14 | + |
| 15 | +Operations that might take a significant amount of time to complete **should** |
| 16 | +return a `202 Accepted` response along with an identifier that can be used to |
| 17 | +track the status of the request and ultimately retrieve the result. |
| 18 | + |
| 19 | +Any single operation defined in an API surface **must** either _always_ return |
| 20 | +`202 Accepted` along with a request identifier, or _never_ do so. A service |
| 21 | +**must not** return a `200 OK` response with the result if it is "fast enough", |
| 22 | +and `202 Accepted` if it is not fast enough, because such behavior adds |
| 23 | +significant burdens for clients. |
| 24 | + |
| 25 | +**Note:** User expectations can vary on what is considered "a significant |
| 26 | +amount of time" depending on what work is being done. A good rule of thumb is |
| 27 | +10 seconds. |
| 28 | + |
| 29 | +### Status monitor representation |
| 30 | + |
| 31 | +The response to a long-running request **should** be a "status monitor" having |
| 32 | +the following common format: |
| 33 | + |
| 34 | +```typescript |
| 35 | +interface StatusMonitor { |
| 36 | + // The identifier for this status monitor. |
| 37 | + id: string; |
| 38 | + |
| 39 | + // Whether the request is done. |
| 40 | + done: boolean; |
| 41 | + |
| 42 | + // The result of the request. |
| 43 | + // Only populated if the request is done and was successful. |
| 44 | + response: any; |
| 45 | + |
| 46 | + // The error that arose from the request. |
| 47 | + // Only populated if the request is done and was unsuccessful. |
| 48 | + error: Error; |
| 49 | + |
| 50 | + // Metadata associated with the request. |
| 51 | + // Populated throughout the life of the request, including after |
| 52 | + // it completes. |
| 53 | + metadata: any; |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +- If the `done` field is `true`, then one and exactly one of the `response` and |
| 58 | + `error` fields **must** be populated. |
| 59 | + - If the `done` field is `false`, then the `response` and `error` fields |
| 60 | + **must not** be populated. |
| 61 | +- The `response` and `metadata` fields **may** be any type that the service |
| 62 | + determines to be appropriate, but **must** always be the same type for any |
| 63 | + particular operation. |
| 64 | + - The `response` and `metadata` types **should** be defined in the same API |
| 65 | + surface as the operation itself. |
| 66 | + - The `response` and `metadata` types that need no data **should** use a |
| 67 | + custom-defined empty struct rather than a common void or empty type, to |
| 68 | + permit future extensibility. |
| 69 | + |
| 70 | +### Querying a status monitor |
| 71 | + |
| 72 | +The service **must** provide an endpoint to query the status of the operation, |
| 73 | +which **must** accept the operation identifier and **should not** include other |
| 74 | +parameters: |
| 75 | + |
| 76 | +```http |
| 77 | +GET /v1/statusMonitors/{status_monitor} HTTP/2 |
| 78 | +Host: library.googleapis.com |
| 79 | +Accept: application/json |
| 80 | +``` |
| 81 | + |
| 82 | +The endpoint **must** return a `StatusMonitor` as described above. |
| 83 | + |
| 84 | +### Standard methods |
| 85 | + |
| 86 | +APIs **may** return an `StatusMonitor` from the [`Create`][aip-133], |
| 87 | +[`Update`][aip-134], or [`Delete`][aip-135] standard methods if appropriate. In |
| 88 | +this case, the `response` field **must** be the standard and expected response |
| 89 | +type for that standard method. |
| 90 | + |
| 91 | +When creating or deleting a resource with a long-running request, the resource |
| 92 | +**should** be included in [`List`][aip-132] and [`Get`][aip-131] calls; |
| 93 | +however, the resource **should** indicate that it is not usable, generally with |
| 94 | +a [state enum][aip-216]. |
| 95 | + |
| 96 | +### Parallel requests |
| 97 | + |
| 98 | +A resource **may** accept multiple requests that will work on it in parallel, |
| 99 | +but is not obligated to do so: |
| 100 | + |
| 101 | +- Resources that accept multiple parallel requests **may** place them in a |
| 102 | + queue rather than work on the requests simultaneously. |
| 103 | +- Resource that does not permit multiple requests in parallel (denying any new |
| 104 | + request until the one that is in progress finishes) **must** return |
| 105 | + `409 Conflict` if a user attempts a parallel request, and include an error |
| 106 | + message explaining the situation. |
| 107 | + |
| 108 | +### Expiration |
| 109 | + |
| 110 | +APIs **may** allow their status monitor resources to expire after sufficient |
| 111 | +time has elapsed after the request completed. |
| 112 | + |
| 113 | +**Note:** A good rule of thumb for status monitor expiry is 30 days. |
| 114 | + |
| 115 | +### Errors |
| 116 | + |
| 117 | +Errors that prevent a long-running request from _starting_ **must** return an |
| 118 | +error response (AIP-193), similar to any other method. |
| 119 | + |
| 120 | +Errors that occur over the course of a request **may** be placed in the |
| 121 | +metadata message. The errors themselves **must** still be represented with a |
| 122 | +canonical error object. |
| 123 | + |
| 124 | +## Interface Definitions |
| 125 | + |
| 126 | +{% tab proto %} |
| 127 | + |
| 128 | +When using protocol buffers, the well-known type `google.longrunning.Operation` |
| 129 | +is used. |
| 130 | + |
| 131 | +**Note:** For historical reasons, Google uses the term `Operation` to represent |
| 132 | +what this document describes as a `StatusMonitor`. |
| 133 | + |
| 134 | +{% sample 'lro.proto', 'rpc WriteBook' %} |
| 135 | + |
| 136 | +- The response type **must** be `google.longrunning.Operation`. The `Operation` |
| 137 | + proto definition **must not** be copied into individual APIs. |
| 138 | + - The response **must not** be a streaming response. |
| 139 | +- The method **must** include a `google.longrunning.operation_info` annotation, |
| 140 | + which **must** define both response and metadata types. |
| 141 | + - The response and metadata types **must** be defined in the file where the |
| 142 | + RPC appears, or a file imported by that file. |
| 143 | + - If the response and metadata types are defined in another package, the |
| 144 | + fully-qualified message name **must** be used. |
| 145 | + - The response type **should not** be `google.protobuf.Empty` (except for |
| 146 | + [`Delete`][aip-135] methods), unless it is certain that response data will |
| 147 | + _never_ be needed. If response data might be added in the future, define an |
| 148 | + empty message for the RPC response and use that. |
| 149 | + - The metadata type is used to provide information such as progress, partial |
| 150 | + failures, and similar information on each `GetOperation` call. The metadata |
| 151 | + type **should not** be `google.protobuf.Empty`, unless it is certain that |
| 152 | + metadata will _never_ be needed. If metadata might be added in the future, |
| 153 | + define an empty message for the RPC metadata and use that. |
| 154 | +- APIs with messages that return `Operation` **must** implement the |
| 155 | + [`Operations`][lro] service. Individual APIs **must not** define their own |
| 156 | + interfaces for long-running operations to avoid inconsistency. |
| 157 | + |
| 158 | +{% tab oas %} |
| 159 | + |
| 160 | +{% sample 'lro.oas.yaml', 'paths' %} |
| 161 | + |
| 162 | +- `202` **must** be the only success status code defined. |
| 163 | +- The `202` response **must** define an `application/json` response body and no other |
| 164 | + response content types. |
| 165 | +- The response body schema **must** be an object with `name`, `done`, and `result` |
| 166 | + properties as described above for a StatusMonitor |
| 167 | +- The response body schema **may** contain an object property named `metadata` to |
| 168 | + hold service-specific metadata associated with the operation, for example progress |
| 169 | + information and common metadata such as create time. The service **should** define |
| 170 | + the contents of the `metadata` object in a separate schema, which **should** specify |
| 171 | + `additionalProperties: true` to allow for future extensibility. |
| 172 | +- The `response` property **must** be a schema that defines the success |
| 173 | + response for the operation. For an operation that typically gives a `204 No Content` |
| 174 | + response, such as a `Delete`, `response` should be defined as an empty object schema. |
| 175 | + For a standard `Get/Create/Update` operation, `response` should be a representation |
| 176 | + of the resource. |
| 177 | +- If a service has any long running operations, the service **must** define an |
| 178 | + `StatusMonitor` resource with a `list` operation to retrieve a potentially filtered |
| 179 | + list of status monitors and a `get` operation to retrieve a specific status monitor |
| 180 | + by its `name`. |
| 181 | + |
| 182 | +{% endtabs %} |
| 183 | + |
| 184 | +<!-- prettier-ignore-start --> |
| 185 | +[google.rpc.Status]: https://github.com/googleapis/api-common-protos/blob/master/google/rpc/S.proto |
| 186 | +[lro]: https://github.com/googleapis/api-common-protos/blob/master/google/longrunning/operations.proto |
| 187 | +[node.js promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises |
| 188 | +[future]: https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Future |
| 189 | +<!-- prettier-ignore-end --> |
0 commit comments