Skip to content

Commit 228225f

Browse files
author
Dan Kershaw [MSFT]
committed
Addressed comments from Mike Pizzo
1 parent 8c215e3 commit 228225f

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

graph/patterns/upsert.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@ Additionally, IaC code scripts or templates usually employ client-provided names
2121

2222
The solution is to use an `Upsert` pattern, to solve for the non-idempotent creation and client-provided naming problems.
2323

24-
* For IaC scenarios, resources must use `Upsert` semantics with an [alternate key](./alternate-key.md):
25-
* Use `PATCH` with a client-provided alternate key.
26-
* For a non-existent resource (specified by the alternate key) the service must handle this as a "create". As part of creation, the service must still generate the primary key value.
27-
* For an existing resource (specified by the alternate key) the service must handle this as an "update.
28-
* Any new alternate key, used for IaC scenarios, should be called `uniqueName`, if there isn't already an existing property that could be used as an alternate key.
24+
* For IaC scenarios, resources must use `Upsert` semantics with a client-provided key:
25+
* Use `PATCH` with a client-provided key:
26+
* If there is a natural client-provided key that can serve as the primary key, then the service should support `Upsert` with that key.
27+
* If the primary key is service-generated, the client-provided key should use an [alternate key](./alternate-key.md) to support idempotent creation.
28+
* For a non-existent resource (specified by the client-provided key) the service must handle this as a "create". As part of creation, the service must still generate the primary key value, if appropriate.
29+
* For an existing resource (specified by the client-provided key) the service must handle this as an "update".
30+
* Any new alternate key, used for IaC scenarios, should be called `uniqueName`, if there isn't already a more natural existing property that could be used as an alternate key.
2931
* NOTE: the service must also support `GET` using the alternate key pattern.
30-
* For consistent CRUD Microsoft Graph behaviors, all resources, **including** resources used in IaC scenarios, should use `POST` and a service-generated primary key, per existing guidelines, and support `GET`, `PATCH` and `DELETE` using the primary key.
32+
* Services should always support `POST` to the collection URL.
33+
* For service-generated keys, this should return the server generated key.
34+
* For client-provided keys, the client should provide the key as part of the request payload.
3135
* If a service does not support `Upsert`, then a `PATCH` call against a non-existent resource must result in an HTTP "409 conflict" error.
3236

3337
This solution allows for existing resources that follow Microsoft Graph conventions for CRUD operations to add `Upsert` without impacting existing apps or functionality.
@@ -40,12 +44,11 @@ This pattern should be adopted for resources that are managed through infrastruc
4044

4145
## Issues and considerations
4246

43-
* The addition of this new pattern (with alternate key) does not represent a breaking change.
47+
* The addition of this new pattern (with an alternate key) to an existing API does not represent a breaking change.
4448
However, some API producers may have concerns about accidental usages of this new pattern unwittingly creating many new resources when the intent was an update.
4549
As a result, API producers can use the `Prefer: idempotent` to require clients to opt-in to the Upsert behavior.
4650
* The client-provided alternate key must be immutable after being set. If its value is null then it should be settable as a way to backfill existing resources for use in IaC scenarios.
4751
* API producers could use `PUT` operations to create or update, but generally this approach is not recommended due to the destructive nature of `PUT`'s replace semantics.
48-
* API producers could use `Upsert` with a primary (client-provided) key and this may be appropriate for some scenarios. However, the recommendation is for resources to support creation using `POST` and a service-generated primary key, for consistency reasons.
4952
* API producers may annotate entity sets, singletons and collections to indicate that entities can be "upserted". The example below shows this annotation for the `groups` entity set.
5053

5154
```xml
@@ -58,6 +61,8 @@ As a result, API producers can use the `Prefer: idempotent` to require clients t
5861
</EntitySet>
5962
```
6063

64+
* `Upsert` can also be supported against singletons, using a `PATCH` to the singleton's URL.
65+
6166
## Examples
6267

6368
For these examples we'll use the `group` entity type, which defines both a primary (service-generated) key (`id`) and an alternate (client-provided) key (`uniqueName`).
@@ -71,12 +76,12 @@ For these examples we'll use the `group` entity type, which defines both a prima
7176
<Property Name="uniqueName" Type="Edm.String"/>
7277
<Property Name="displayName" Type="Edm.String"/>
7378
<Property Name="description" Type="Edm.String"/>
74-
<Annotation Term="OData.Community.Keys.V1.AlternateKeys">
79+
<Annotation Term="Org.OData.Core.V1.AlternateKeys">
7580
<Collection>
76-
<Record Type="OData.Community.Keys.V1.AlternateKey">
81+
<Record Type="Org.OData.Core.V1.AlternateKey">
7782
<PropertyValue Property="Key">
7883
<Collection>
79-
<Record Type="OData.Community.Keys.V1.PropertyRef">
84+
<Record Type="Org.OData.Core.V1.PropertyRef">
8085
<PropertyValue Property="Name" PropertyPath="uniqueName" />
8186
</Record>
8287
</Collection>

0 commit comments

Comments
 (0)