PatchAPI: Add JSON patch support
See original GitHub issueScenario’s:
- Limited to single document always
- Composable for Transactional batch
- Order performed as requested (with-in single document)
- Structure updates (Add, delete, replace, etc…), conditional aspect
- Special operations (increment, numeric types)
Will follow later
Non goals
- Chain results in TransactionalBatch scenario (ex: update a doc, use result to update another doc)
- Support custom JS lambda
Open clarifications
- What’s status code when the patched document is larger than 2MB?
413 - Payload Too Large
- What’s status code when the inflight patched document is larger than 2MB but eventual size is valid?
We will only track the final size of item generated and any intermediate size during the application of PatchSpec will not be considered. Any artifacts (ConfirmedPatchHistory) generated during creation of PatchSpec will not be accounted for in 2MB size.
- Service structure validation: What validations are performed on final result?
None
- How many mutations per document (or batch) are supported?
Maximum 100 operations per Patch request.
- What’s the REST API version?
- Any guards to cover for client encryption? (accidental encryption override/corruption)
With our current non-deterministic encryption model where server does not know which properties are encrypted, we would not support Patch on documents which has encrypted data. However, with upcoming deterministic encryption model – patch will be supported.
- Can the patch be used to rename document id (not PK)?
Yes
- Client encryption and patch consistency
Repeat point.
- What will it be ChangeFeed ChangeType?
Replace
Finalized OM
public abstract class Container
{
// Single document
ItemResponse<T> PatchItemAsync(
string,
PartitionKey,
IReadOnlyList<PatchOperation>,
ItemRequestOptions,
CancellationToken);
// Single PK, Transactional-batch
TransactionalBatchBuilder CreateTransactionalBatch(PartitionKey pk);
}
public abstract class TransactionalBatchBuilder
{
// Results in nested builder pattern
TransactionalBatchBuilder PatchItem(
string id,
IReadOnlyList<PatchOperation> patchOperations,
ItemRequestOptions);
TransactionalBatchResponse Execute(CancellationToken token);
}
public abstract class PatchOperation
{
public PatchOperationType Operation;
public string path;
static PatchOperation CreateAddOperation<T>(string path, T payload);
static PatchOperation CreateRemoveOperation(string path);
static PatchOperation CreateReplaceOperation<T>(string path, T payload);
static PatchOperation CreateSetOperation<T>(string path, T payload);
}
// { op = "add", Path="", value="" }
public class PatchOperationType
{
Add,
Remove,
Replace,
Set
}
Alternative OM considered
public abstract class Container
{
// Single document
ItemResponse<T> PatchItemAsync(
PartitionKey,
string,
ItemPatchSpecfication,
ItemRequestOptions,
CancellationToken);
// Single PK, Trasnactional-batch
TransactionalBatchBuilder CreateTransactionalBath(PartitionKey pk);
}
public abstract class TransactionalBatchBuilder
{
// Results in nested builder pattern
TransactionalBatchBuilder PatchItem(
string id,
PatchSpecfication spec,
ItemReqeustOptions);
TransactionalBatchResponse Execute(CancellationToken token);
}
public class ItemPatchSpecfication
{
private List<PatchOperation> ops;
ItemPatchSpecfication Add<T>(string path, T payload);
ItemPatchSpecfication Delete(string path);
ItemPatchSpecfication Replace<T>(string path, T payload);
ItemPatchSpecfication Move(string path, string path);
ItemPatchSpecfication Get(string path);
ItemPatchSpecfication increment(string path);
}
// { op = Add, Path="", value="" }
internal class ItemPatchOperation // Union type
{
Operation;
from;
Path;
Value;
...
}
- Single document mutations(or patches)
- Composable through builder
- Support multiple types (representing nested types)
- Same list of PatchOperation can be leveraged for both SingleItem and TransactionalBatch scenarios
- Actual operation contract is not public. Will explore it when its a goal
Operation contract is made public (based on feedback for Batch).
- Patch values has to go-through custom serializer
- Response semantics still TBD
Consistent with other APIs.
Notes:
- Path as string literal: Error prone typing, serialization inference. One option is to have overload can infer path through full payload (ex: Add<T>(T item) with assumption that only one root-nested path present. Its a convenience overload and based on user feedback we can explore.
ref: https://tools.ietf.org/html/rfc6902 https://www.nuget.org/packages/Microsoft.AspNetCore.JsonPatch/
/cc: @j82w, @ealsur , @FabianMeiswinkel , @kushagraThapar , @moderakh , @milismsft
Issue Analytics
- State:
- Created 3 years ago
- Comments:14 (9 by maintainers)
Top GitHub Comments
Any ETA on GA?
@loraderon Patch API is currently in preview, you can test it with nuget 3.20.1-preview. That issue you linked is to add it on V4 (the next SDK version)