Skip to content

Commit 3445e5c

Browse files
authored
Merge pull request #353 from mikekistler/new-lro-guidelines
Update Azure API Guidelines for new LRO pattern. A huge "THANKS!" to everyone that contributed to this!
2 parents 27aa5a2 + e4cc4b3 commit 3445e5c

File tree

7 files changed

+262
-109
lines changed

7 files changed

+262
-109
lines changed

azure/ConsiderationsForServiceDesign.md

Lines changed: 188 additions & 72 deletions
Large diffs are not rendered by default.

azure/Guidelines.md

Lines changed: 73 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
# Microsoft Azure REST API Guidelines
2+
3+
<!-- cspell:ignore autorest, BYOS, etag, idempotency, maxpagesize, innererror -->
4+
25
## History
36

47
| Date | Notes |
58
| ----------- | -------------------------------------------------------------- |
9+
| 2022-Jul-15 | Update guidance on long-running operations |
610
| 2022-May-11 | Drop guidance on version discovery |
711
| 2022-Mar-29 | Add guidelines about using durations |
812
| 2022-Mar-25 | Update guideline for date values in headers to follow RFC 7231 |
@@ -135,7 +139,7 @@ GET | Read (i.e. list) a resource collection | `200-OK`
135139
GET | Read the resource | `200-OK`
136140
DELETE | Remove the resource | `204-No Content`\; avoid `404-Not Found`
137141

138-
:white_check_mark: **DO** return status code `202-Accepted` and follow the guidance in [Long-Running Operations & Jobs](#long-running-operations--jobs) when a PUT, PATCH, POST, or DELETE method completes asynchronously.
142+
:white_check_mark: **DO** return status code `202-Accepted` and follow the guidance in [Long-Running Operations & Jobs](#long-running-operations--jobs) when a PUT, POST, or DELETE method completes asynchronously.
139143

140144
:white_check_mark: **DO** treat method names as case sensitive and should always be in uppercase
141145

@@ -694,7 +698,11 @@ Azure services need to change over time. However, when changing a service, there
694698

695699
:white_check_mark: **DO** review any API changes with the Azure API Stewardship Board
696700

697-
:white_check_mark: **DO** use an `api-version` query parameter with a `YYYY-MM-DD` date value, with a `-preview` suffix for a preview service.
701+
Clients specify the version of the API to be used in every request to the service, even requests to an `Operation-Location` or `nextLink` URL returned by the service.
702+
703+
:white_check_mark: **DO** use a required query parameter named `api-version` on every operation for the client to specify the API version.
704+
705+
:white_check_mark: **DO** use `YYYY-MM-DD` date values, with a `-preview` suffix for preview versions, as the valid values for `api-version`.
698706

699707
```text
700708
PUT https://service.azure.com/users/Jeff?api-version=2021-06-04
@@ -757,68 +765,99 @@ implemented as a _long-running operation (LRO)_. This allows clients to continue
757765
operation is being processed. The client obtains the outcome of the operation at some later time
758766
through another API call.
759767
See the [Long Running Operations section](./ConsiderationsForServiceDesign.md#long-running-operations) in
760-
Considerations for Service Design for an introduction to the design of long running operations.
768+
Considerations for Service Design for an introduction to the design of long-running operations.
761769

762770
:white_check_mark: **DO** implement an operation as an LRO if the 99th percentile response time is greater than 1s.
763771

772+
:no_entry: **DO NOT** implement PATCH as an LRO. If LRO update is required it must be implemented with POST.
773+
764774
In rare instances where an operation may take a _very long_ time to complete, e.g. longer than 15 minutes,
765775
it may be better to expose this as a first class resource of the API rather than as an operation on another resource.
766776

767-
There are two basic patterns that can be used for long-running operations:
768-
1. Resource-based long-running operations (RELO)
769-
2. Long-running operations with status monitor
777+
There are two basic patterns for long-running operations in Azure. The first pattern is used for a POST and DELETE
778+
operations that initiate the LRO. These return a `202 Accepted` response with a JSON status monitor in the response body.
779+
The second pattern applies only in the case of a PUT operation to create a resource that also involves additional long-running processing.
780+
For guidance on when to use a specific pattern, please refer to [Considerations for Service Design, Long Running Operations](./ConsiderationsForServiceDesign.md#long-running-operations).
781+
These are described in the following two sections.
782+
783+
#### POST or DELETE LRO pattern
784+
785+
A POST or DELETE long-running operation accepts a request from the client to initiate the operation processing and returns
786+
a [status monitor](https://datatracker.ietf.org/doc/html/rfc7231#section-6.3.3) that reports the operation's progress.
787+
788+
:no_entry: **DO NOT** use a long-running POST to create a resource -- use PUT as described below.
789+
790+
:white_check_mark: **DO** allow the client to pass an `Operation-Id` header with an ID for the operation's status monitor.
791+
792+
:white_check_mark: **DO** generate an ID (typically a GUID) for the status monitor if the `Operation-Id` header was not passed by the client.
793+
794+
:white_check_mark: **DO** fail a request with a `400-BadRequest` if the `Operation-Id` header matches an existing operation unless the request is identical to the prior request (a retry scenario).
795+
796+
:white_check_mark: **DO** perform as much validation as practical when initiating the operation to alert clients of errors early.
797+
798+
:white_check_mark: **DO** return a `202-Accepted` status code from the request that initiates an LRO if the processing of the operation was successfully initiated (except for "PUT with additional processing" type LRO).
799+
800+
:warning: **YOU SHOULD NOT** return any other `2xx` status code from the initial request of an LRO -- return `202-Accepted` and a status monitor even if processing was completed before the initiating request returns.
801+
802+
:white_check_mark: **DO** return a status monitor in the response body as described in [Obtaining status and results of long-running operations](#obtaining-status-and-results-of-long-running-operations).
803+
804+
:ballot_box_with_check: **YOU SHOULD** include an `Operation-Location` header in the response with the absolute URL of the status monitor for the operation.
770805

771-
:white_check_mark: **DO** use the RELO pattern when the operation is on a resource that contains a "status" property that can be used to obtain the outcome of the operation.
806+
:ballot_box_with_check: **YOU SHOULD** include the `api-version` query parameter in the `Operation-Location` header with the same version passed on the initial request if it is required by the get operation on the status monitor.
772807

773-
:ballot_box_with_check: **YOU SHOULD** only use the status monitor LRO pattern when the RELO pattern is not applicable.
808+
:ballot_box_with_check: **YOU SHOULD** allow any valid value of the `api-version` query parameter to be used in the get operation on the status monitor.
774809

775-
#### Resource-based long-running operations
810+
#### PUT operation with additional long-running processing
776811

777-
Some common situations where the RELO pattern should be used:
778-
1. A "create" operation (PUT, PATCH, or POST) for a resource where the basic structure of the resource is created immediately and includes a status field that indicates when the create has completed, e.g. "provisioning" -> "active".
779-
2. An action operation for a resource where both the initiation of the action and the completion of the action cause a change to the "status" property of the resource.
812+
For a PUT (create or replace) with additional long-running processing:
780813

781-
:white_check_mark: **DO** return a `200-OK` response, `201-Created` for create operations, from the request that initiates the operation. The response body should contain a representation of the resource that clearly indicates that the operation has been accepted or started.
814+
:white_check_mark: **DO** allow the client to pass an `Operation-Id` header with a ID for the status monitor for the operation.
782815

783-
:white_check_mark: **DO** support a get method on the resource that returns a representation of the resource including the status field that indicates when the operation has completed.
816+
:white_check_mark: **DO** generate an ID (typically a GUID) for the status monitor if the `Operation-Id` header was not passed by the client.
784817

785-
:white_check_mark: **DO** define the "status" field of the resource as an enum with all the values it may contain including the "terminal" values "Succeeded", "Failed", and "Canceled". See [Enums & SDKs](#enums--sdks-client-libraries).
818+
:white_check_mark: **DO** fail a request with a `400-BadRequest` if the `Operation-Id` header that matches an existing operation unless the request is identical to the prior request (a retry scenario).
786819

787-
:ballot_box_with_check: **YOU SHOULD** use the name `status` for the "status" field of the resource.
820+
:white_check_mark: **DO** perform as much validation as practical when initiating the operation to alert clients of errors early.
788821

789-
#### Long-running operations with status monitor
822+
:white_check_mark: **DO** return a `201-Created` status code for create or `200-OK` for replace from the initial request with a representation of the resource if the resource was created successfully.
790823

791-
In a long-running operation with status monitor, the client makes a request to initiate the operation processing and receives a URL in the response where it can obtain the operation results. The [HTTP specification](https://datatracker.ietf.org/doc/html/rfc7231#section-6.3.3) calls the target of this URL a "status monitor".
824+
:white_check_mark: **DO** include an `Operation-Id` header in the response with the ID of the status monitor for the operation.
792825

793-
:white_check_mark: **DO** return a `202-Accepted` status code from the request that initiates an LRO with status monitor if the processing of the operation was successfully initiated.
826+
:white_check_mark: **DO** include response headers with any additional values needed for a GET request to the status monitor (e.g. location).
794827

795-
:white_check_mark: **DO** perform as much validation of the initial request as practical and return an error response immediately when appropriate (without starting the operation).
828+
:ballot_box_with_check: **YOU SHOULD** include an `Operation-Location` header in the response with the absolute URL of the status monitor for the operation.
796829

797-
:white_check_mark: **DO** return the status monitor URL in the `Operation-Location` response header.
830+
:ballot_box_with_check: **YOU SHOULD** include the `api-version` query parameter in the `Operation-Location` header with the same version passed on the initial request if it is required by the get operation on the status monitor.
798831

799-
:white_check_mark: **DO** support the `get` method on the status monitor endpoint that returns a `200-OK` response with a response body that contains the completion status of the operation with sufficient information to diagnose any potential failures.
832+
:ballot_box_with_check: **YOU SHOULD** allow any valid value of the `api-version` query parameter to be used in the get operation on the status monitor.
800833

801-
:white_check_mark: **DO** include a field in the status monitor resource named `status` indicating the operation's status. This field should be a string with well-defined values. Indicate the terminal state using "Succeeded", "Failed", or "Canceled".
834+
#### Obtaining status and results of long-running operations
802835

803-
:white_check_mark: **DO** include a field in the status monitor named `error` to contain error information -- minimally `code` and `message` fields -- when an operation fails.
836+
For all long-running operations, the client will issue a GET on a status monitor resource to obtain the current status of the operation.
804837

805-
:white_check_mark: **DO** retain the status monitor resource for some documented period of time (at least 24 hours) after the operation completes.
838+
:white_check_mark: **DO** support the GET method on the status monitor endpoint that returns a `200-OK` response with the current state of the status monitor.
806839

807-
:white_check_mark: **DO** include a `Retry-After` header in the response to the initiating request and requests to the operation-location URL. The value of this header should be an integer number of seconds to wait before making the next request to the operation-location URL.
840+
:white_check_mark: **DO** return a status monitor in the response body that conforms with the following structure:
808841

809-
:heavy_check_mark: **YOU MAY** support a `get` method on the status monitor collection URL that returns a list of status monitors for all recently initiated operations.
842+
**OperationStatus** : Object
810843

811-
:warning: **YOU SHOULD NOT** return any other `2xx` status code from the initial request of a status-monitor LRO -- return `202-Accepted` and a status monitor URL even if processing was completed before the initiating request returns.
844+
Property | Type | Required | Description
845+
-------- | ----------- | :------: | -----------
846+
`id` | string | true | The unique id of the operation
847+
`status` | string | true | enum that includes terminal values "Succeeded", "Failed", "Canceled"
848+
`error` | ErrorDetail | | Error object that describes the error when status is "Failed"
849+
`result` | object | | Only for POST action-type LRO, the results of the operation when completed successfully
850+
additional<br/>properties | | | Additional named or dynamic properties of the operation
812851

813-
:no_entry: **DO NOT** return any data in the response body of a `202-Accepted` response.
852+
:white_check_mark: **DO** include the `id` of the operation and any other values needed for the client to form a GET request to the status monitor (e.g. a `location` path parameter).
814853

815-
Previous Azure guidelines specified "Azure-AsyncOperation" as the name of the response header containing the status monitor URL.
854+
:white_check_mark: **DO** include a `Retry-After` header in the response to GET requests to the status monitor if the operation is not complete. The value of this header should be an integer number of seconds to wait before making the next request to the status monitor.
816855

817-
:white_check_mark: **DO** return **both** `Azure-AsyncOperation` and `Operation-Location` headers if your service previously returned `Azure-AsyncOperation`, even though they are redundant, so that existing clients will continue to operate.
856+
:white_check_mark: **DO** include the `result` property (if any) in the status monitor for a POST action-type long-running operation when the operation completes successfully.
818857

819-
:white_check_mark: **DO** return the same value for **both** headers.
858+
:no_entry: **DO NOT** include a `result` property in the status monitor for a long-running operation that is not a POST action-type long-running operation.
820859

821-
:white_check_mark: **DO** look for **both** headers in client code, preferring the `Operation-Location` header.
860+
:white_check_mark: **DO** retain the status monitor resource for some publicly documented period of time (at least 24 hours) after the operation completes.
822861

823862
### Bring your own Storage
824863
When implementing your service, it is very common to store and retrieve data and files. When you encounter this scenario, avoid implementing your own storage strategy and instead use Azure Bring Your Own Storage (BYOS). BYOS provides significant benefits to service implementors, e.g. security, an aggressively optimized frontend, uptime, etc.
@@ -847,7 +886,7 @@ It is not uncommon to rely on other services, e.g. storage, when implementing yo
847886
Generally speaking, there are two patterns that you will encounter when working with files; single file access, and file collections.
848887

849888
##### Single file access
850-
Desiging an API for accessing a single file, depending on your scenario, is relatively straight forward.
889+
Designing an API for accessing a single file, depending on your scenario, is relatively straight forward.
851890

852891
:heavy_check_mark: **YOU MAY** use a Shared Access Signature [SAS](https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview) to provide access to a single file. SAS is considered the minimum security for files and can be used in lieu of, or in addition to, RBAC.
853892

azure/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ Designing powerful APIs with strong defaults, consistent behavior across related
77
* [OpenAPI Style Guidelines](https://github.com/Azure/azure-api-style-guide/blob/main/README.md)
88
* [Breaking Changes](http://aka.ms/AzBreakingChangesPolicy/) <sub>Note: Internal Microsoft link</sub>
99

10-
You can reach out to use via [email](mailto://[email protected]) or in our [Teams](https://teams.microsoft.com/l/team/19%3a3ebb18fded0e47938f998e196a52952f%40thread.tacv2/conversations?groupId=1a10b50c-e870-4fe0-8483-bf5542a8d2d8&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47) channel.
10+
You can reach out to us via [email](mailto://[email protected]) or in our [Teams](https://teams.microsoft.com/l/team/19%3a3ebb18fded0e47938f998e196a52952f%40thread.tacv2/conversations?groupId=1a10b50c-e870-4fe0-8483-bf5542a8d2d8&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47) channel.
1111

1212
<sub>Note: The Teams channel is internal MS.</sup>

azure/relo.drawio

Lines changed: 0 additions & 1 deletion
This file was deleted.

azure/relo.jpg

-19.9 KB
Binary file not shown.

azure/statmon.drawio

Lines changed: 0 additions & 1 deletion
This file was deleted.

azure/statmon.jpg

-25.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)