Skip to content

Commit 372bcd6

Browse files
committed
Restore all prior named guidelines with some edits where needed
1 parent 97b50d1 commit 372bcd6

File tree

2 files changed

+230
-106
lines changed

2 files changed

+230
-106
lines changed

azure/ConsiderationsForServiceDesign.md

+146-69
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
| Date | Notes |
88
| ----------- | -------------------------------------------------------------- |
9+
| 2024-Mar-17 | Updated LRO guidelines |
910
| 2024-Jan-17 | Added guidelines on returning string offsets & lengths |
1011
| 2022-Jul-15 | Update guidance on long-running operations |
1112
| 2022-Feb-01 | Updated error guidance |
@@ -216,7 +217,7 @@ cannot collide with a resource path that contains user-specified resource ids.
216217

217218
## Long-Running Operations
218219

219-
Long-running operations are an API design pattern that should be used when the processing of
220+
Long-running operations (LROs) are an API design pattern that should be used when the processing of
220221
an operation may take a significant amount of time -- longer than a client will want to block
221222
waiting for the result.
222223

@@ -225,33 +226,106 @@ a _status monitor_, which is an ephemeral resource that will track the status an
225226
The status monitor resource is distinct from the target resource (if any) and specific to the individual
226227
operation request.
227228

228-
A POST or DELETE operation returns a `202 Accepted` response with the status monitor in the response body.
229-
A long-running POST should not be used for resource create -- use PUT as described below.
230-
PATCH must never be used for long-running operations -- it should be reserved for simple resource updates.
231-
If a long-running update is required it should be implemented with POST.
229+
There are four types of LROs allowed in Azure REST APIs:
230+
231+
1. An LRO to create or replace a resource that involves additional long-running processing.
232+
2. An LRO to delete a resource.
233+
3. An LRO to perform an action on or with an existing resource (or resource collection).
234+
4. An LRO to perform an action not related to an existing resource (or resource collection).
235+
236+
The following sections describe these patterns in detail.
237+
238+
### Create or replace a resource requiring additional long-running processing
239+
<a href="#put-with-additional-long-running-processing"></a> <!-- Preserve anchor of previous heading -->
240+
241+
A special case of long-running operation that occurs often is a PUT operation to create or replace a resource
242+
that involves some additional long-running processing.
243+
One example is a resource that requires physical resources (e.g. servers) to be "provisioned" to make the resource functional.
244+
245+
In this case:
246+
- The operation must use the PUT method (NOTE: PATCH is never allowed here)
247+
- The URL identifies resource being created or replaced.
248+
- The request and response body have identical schemas & represent the resource.
249+
- The request may contain an `Operation-Id` header that the service will use as
250+
the ID of the status monitor created for the operation.
251+
252+
```text
253+
PUT /items/FooBar&api-version=2022-05-01
254+
Operation-Id: 22
255+
256+
{
257+
"prop1": 555,
258+
"prop2": "something"
259+
}
260+
```
261+
262+
In this case the response to the initial request is a `201 Created` to indicate that
263+
the resource has been created or `200 OK` when the resource was replaced.
264+
A status monitor is created to track the additional processing and the ID of the status monitor
265+
is returned in the `Operation-Id` header of the response.
266+
The response may also include an `Operation-Location` header for backward compatibility.
267+
If the resource supports ETags, the response may contain an `etag` header and possibly an `etag` property in the resource.
268+
269+
```text
270+
HTTP/1.1 201 Created
271+
Operation-Id: 22
272+
Operation-Location: https://items/operations/22
273+
etag: "123abc"
274+
275+
{
276+
"id": "FooBar",
277+
"etag": "123abc",
278+
"prop1": 555,
279+
"prop2": "something"
280+
}
281+
```
282+
283+
The client will issue a GET to the status monitor to obtain the status of the operation performing the additional processing.
284+
285+
```text
286+
GET https://items/operations/22?api-version=2022-05-01
287+
```
232288

233-
There is a special form of long-running operation initiated with PUT that is described
234-
in [Create (PUT) with additional long-running processing](./Guidelines.md#put-operation-with-additional-long-running-processing).
235-
The remainder of this section describes the pattern for long-running POST and DELETE operations.
289+
When the additional processing completes, the status monitor will indicate if it succeeded or failed.
236290

237-
This diagram illustrates how a long-running operation with a status monitor is initiated and then how the client
291+
```text
292+
HTTP/1.1 200 OK
293+
294+
{
295+
"id": "22",
296+
"status": "Succeeded"
297+
}
298+
```
299+
300+
If the additional processing failed, the service may delete the original resource if it is not usable in this state,
301+
but should clearly document this behavior.
302+
303+
### Long-running delete operation
304+
305+
A long-running delete operation follows the general pattern of a long-running operation --
306+
it returns a `202 Accepted` with a status monitor which the client uses to determine the outcome of the delete.
307+
308+
The resource being deleted should remain visible (returned from a GET) until the delete operation completes successfully.
309+
310+
When the delete operation completes successfully, a client must be able to create a new resource with same name without conflicts.
311+
312+
This diagram illustrates how a long-running DELETE operation is initiated and then how the client
238313
determines it has completed and obtains its results:
239314

240315
```mermaid
241316
sequenceDiagram
242317
participant Client
243318
participant API Endpoint
244319
participant Status Monitor
245-
Client->>API Endpoint: POST/DELETE
320+
Client->>API Endpoint: DELETE
246321
API Endpoint->>Client: HTTP/1.1 202 Accepted<br/>{ "id": "22", "status": "NotStarted" }
247322
Client->>Status Monitor: GET
248323
Status Monitor->>Client: HTTP/1.1 200 OK<br/>Retry-After: 5<br/>{ "id": "22", "status": "Running" }
249324
Client->>Status Monitor: GET
250325
Status Monitor->>Client: HTTP/1.1 200 OK<br/>{ "id": "22", "status": "Succeeded" }
251326
```
252327

253-
1. The client sends the request to initiate the long-running operation.
254-
The initial request could be a POST or DELETE method.
328+
1. The client sends the request to initiate the long-running DELETE operation.
255329
The request may contain an `Operation-Id` header that the service uses as the ID of the status monitor created for the operation.
256330

257331
2. The service validates the request and initiates the operation processing.
@@ -274,11 +348,8 @@ If the operation is still being processed, the status field will contain a "non-
274348

275349
5. After the operation processing completes, a GET request to the status monitor returns the status monitor with a status field set to a terminal value -- `Succeeded`, `Failed`, or `Canceled` -- that indicates the result of the operation.
276350
If the status is `Failed`, the status monitor resource contains an `error` field with a `code` and `message` that describes the failure.
277-
If the status is `Succeeded` and the LRO is an Action operation, the operation results will be returned in the `result` field of the status monitor.
278-
If the status is `Succeeded` and the LRO is an operation on a resource, the client can perform a GET on the resource
279-
to observe the result of the operation if desired.
280351

281-
6. There may be some cases where a long-running operation can be completed before the response to the initial request.
352+
6. There may be some cases where a long-running DELETE operation can be completed before the response to the initial request.
282353
In these cases, the operation should still return a `202 Accepted` with the `status` property set to the appropriate terminal state.
283354

284355
7. The service is responsible for purging the status-monitor resource.
@@ -291,6 +362,9 @@ An action operation that is also long-running combines the [Action Operations](#
291362
with the [Long Running Operations](#long-running-operations) pattern.
292363

293364
The operation is initiated with a POST operation and the operation path ends in `:<action>`.
365+
A long-running POST should not be used for resource create -- use PUT as described above.
366+
PATCH must never be used for long-running operations -- it should be reserved for simple resource updates.
367+
If a long-running update is required it should be implemented with POST.
294368

295369
```text
296370
POST /<service-or-resource-url>:<action>?api-version=2022-05-01
@@ -302,7 +376,7 @@ Operation-Id: 22
302376
}
303377
```
304378

305-
The response is a `202 Accepted` as described above.
379+
A long-running action operation returns a `202 Accepted` response with the status monitor in the response body.
306380

307381
```text
308382
HTTP/1.1 202 Accepted
@@ -332,74 +406,77 @@ HTTP/1.1 200 OK
332406
}
333407
```
334408

335-
### PUT with additional long-running processing
409+
This diagram illustrates how a long-running action operation is initiated and then how the client
410+
determines it has completed and obtains its results:
336411

337-
A special case of long-running operation that occurs often is a PUT operation to create or replace a resource
338-
that involves some additional long-running processing.
339-
One example is a resource requires physical resources (e.g. servers) to be "provisioned" to make the resource functional.
340-
In this case, the request may contain an `Operation-Id` header that the service will use as
341-
the ID of the status monitor created for the operation.
412+
```mermaid
413+
sequenceDiagram
414+
participant Client
415+
participant API Endpoint
416+
participant Status Monitor
417+
Client->>API Endpoint: POST
418+
API Endpoint->>Client: HTTP/1.1 202 Accepted<br/>{ "id": "22", "status": "NotStarted" }
419+
Client->>Status Monitor: GET
420+
Status Monitor->>Client: HTTP/1.1 200 OK<br/>Retry-After: 5<br/>{ "id": "22", "status": "Running" }
421+
Client->>Status Monitor: GET
422+
Status Monitor->>Client: HTTP/1.1 200 OK<br/>{ "id": "22", "status": "Succeeded", "result": { ... } }
423+
```
342424

343-
```text
344-
PUT /items/FooBar&api-version=2022-05-01
345-
Operation-Id: 22
425+
1. The client sends the request to initiate the long-running action operation.
426+
The request may contain an `Operation-Id` header that the service uses as the ID of the status monitor created for the operation.
346427

347-
{
348-
"prop1": 555,
349-
"prop2": "something"
350-
}
351-
```
428+
2. The service validates the request and initiates the operation processing.
429+
If there are any problems with the request, the service responds with a `4xx` status code and error response body.
430+
Otherwise the service responds with a `202-Accepted` HTTP status code.
431+
The response body is the status monitor for the operation including the ID, either from the request header or generated by the service.
432+
When returning a status monitor whose status is not in a terminal state, the response must also include a `retry-after` header indicating the minimum number of seconds the client should wait
433+
before polling (GETing) the status monitor URL again for an update.
434+
For backward compatibility, the response may also include an `Operation-Location` header containing the absolute URL
435+
of the status monitor resource (without an api-version query parameter).
352436

353-
In this case the response to the initial request is a `201 Created` to indicate that the resource has been created
354-
or `200 OK` when the resource was replaced.
355-
The response body contains a representation of the created resource, which is the standard pattern for a create operation.
356-
A status monitor is created to track the additional processing and the ID of the status monitor
357-
is returned in the `Operation-Id` header of the response.
358-
The response may also include an `Operation-Location` header for backward compatibility.
359-
If the resource supports ETags, the response may contain an `etag` header and possibly an `etag` property in the resource.
437+
3. After waiting at least the amount of time specified by the previous response's `Retry-after` header,
438+
the client issues a GET request to the status monitor using the ID in the body of the initial response.
439+
The GET operation for the status monitor is documented in the REST API definition and the ID
440+
is the last URL path segment.
360441

361-
```text
362-
HTTP/1.1 201 Created
363-
Operation-Id: 22
364-
Operation-Location: https://items/operations/22
365-
etag: "123abc"
442+
4. The status monitor responds with information about the operation including its current status,
443+
which should be represented as one of a fixed set of string values in a field named `status`.
444+
If the operation is still being processed, the status field will contain a "non-terminal" value, like `NotStarted` or `Running`.
366445

367-
{
368-
"id": "FooBar",
369-
"etag": "123abc",
370-
"prop1": 555,
371-
"prop2": "something"
372-
}
373-
```
446+
5. After the operation processing completes, a GET request to the status monitor returns the status monitor with a status field set to a terminal value -- `Succeeded`, `Failed`, or `Canceled` -- that indicates the result of the operation.
447+
If the status is `Failed`, the status monitor resource contains an `error` field with a `code` and `message` that describes the failure.
448+
If the status is `Succeeded`, the operation results will be returned in the `result` field of the status monitor.
374449

375-
The client will issue a GET to the status monitor to obtain the status of the operation performing the additional processing.
450+
6. There may be some cases where a long-running action operation can be completed before the response to the initial request.
451+
In these cases, the operation should still return a `202 Accepted` with the `status` property set to the appropriate terminal state.
376452

377-
```text
378-
GET https://items/operations/22?api-version=2022-05-01
379-
```
453+
7. The service is responsible for purging the status-monitor resource.
454+
It should auto-purge the status monitor resource after completion (at least 24 hours).
455+
The service may offer DELETE of the status monitor resource due to GDPR/privacy.
380456

381-
When the additional processing completes, the status monitor will indicate if it succeeded or failed.
457+
### Long-running action operation not related to a resource
382458

383-
```text
384-
HTTP/1.1 200 OK
459+
When an long-running action operation is not related to a specific resource (a batch operation is one example),
460+
another approach is needed.
385461

386-
{
387-
"id": "22",
388-
"status": "Succeeded"
389-
}
390-
```
462+
A long-running action operation not related to a resource should use a PUT operation for a resource that combines a status monitor with the request and results of the operation. In this pattern, clients obtain the status of the operation by issuing a GET on the same URL as the PUT operation.
391463

392-
If the additional processing failed, the service may delete the original resource if it is not usable in this state,
393-
but would have to clearly document this behavior.
464+
The following examples illustrate this pattern.
394465

395-
### Long-running delete operation
466+
```text
467+
PUT /translate-operations/<operation-id>
396468
397-
A long-running delete operation follows the general pattern of a long-running operation --
398-
it returns a `202 Accepted` with a status monitor which the client uses to determine the outcome of the delete.
469+
<Request body is combination of status monitor and operation properties>
470+
```
399471

400-
The resource being deleted should remain visible (returned from a GET) until the delete operation completes successfully.
472+
Note that the client specifies the operation id in the URL path.
401473

402-
When the delete operation completes successfully, a client must be able to create new resource with same name without conflicts.
474+
A successful response to the PUT operation should have a `201 Created` status and response body
475+
of the same structure as the request body, possibly with some additional output-only fields.
476+
477+
The service is responsible for purging the combined status-monitor/request/response resource.
478+
It should auto-purge this resource after completion (at least 24 hours).
479+
The service may offer DELETE of the status monitor resource due to GDPR/privacy.
403480

404481
### Controlling a long-running operation
405482

0 commit comments

Comments
 (0)