1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//! Options for item-level point reads, writes, and patch operations.
use ;
use OperationOptions;
/// Options for item point-read operations.
///
/// Used by [`ContainerClient::read_item()`](crate::clients::ContainerClient::read_item).
///
/// General-purpose settings such as custom headers and excluded regions are configured
/// via the [`with_operation_options`](Self::with_operation_options) setter. See [`OperationOptions`] for details.
/// Options for item write operations.
///
/// Used by [`ContainerClient::create_item()`](crate::clients::ContainerClient::create_item),
/// [`ContainerClient::replace_item()`](crate::clients::ContainerClient::replace_item),
/// [`ContainerClient::upsert_item()`](crate::clients::ContainerClient::upsert_item), and
/// [`ContainerClient::delete_item()`](crate::clients::ContainerClient::delete_item).
///
/// General-purpose settings such as custom headers, excluded regions, and content
/// response behavior are configured via the [`with_operation_options`](Self::with_operation_options) setter.
/// See [`OperationOptions`] for details.
/// Options for [`ContainerClient::patch_item()`](crate::clients::ContainerClient::patch_item()).
///
/// PATCH is implemented driver-side as a Read-Modify-Write (RMW) loop:
/// the driver reads the current item, applies your [`PatchInstructions`](crate::models::PatchInstructions)
/// locally, and issues an ETag-guarded Replace. If the Replace returns
/// 412 PreconditionFailed (another writer raced), the loop restarts.
///
/// The optional [`max_attempts`](Self::max_attempts) field bounds how many
/// times that loop may retry; `None` falls back to the driver default (5).
///
/// # Conditions are not exposed
///
/// PATCH intentionally does **not** expose either flavor of "condition" that
/// peer SDKs surface on their PATCH options:
///
/// * **`Precondition` (`If-Match` / `If-None-Match`).** The handler owns the
/// `If-Match` precondition on the internal Replace and captures the ETag
/// off the matching Read; honoring a caller-set value would either shadow
/// that ETag (silently breaking the RMW guarantee) or require resolving
/// it against the handler's own ETag (no sensible merge). The driver-side
/// PATCH handler rejects any caller-set precondition with an error before
/// issuing any sub-operation.
/// * **SQL filter predicate** (peer SDKs' `FilterPredicate`). Predicate
/// evaluation requires either native wire-level PATCH (so the server
/// evaluates the predicate inside the same transaction) or a client-side
/// SQL subset evaluator; neither is in scope for this preview. The
/// driver's [`PatchInstructions`](crate::models::PatchInstructions) has no `condition` field, so
/// there is no way to attach a predicate to a PATCH request.
///
/// The session token lives on the dedicated
/// [`session_token`](Self::session_token) field (mirroring
/// [`ItemReadOptions`] / [`ItemWriteOptions`]). All other general-purpose
/// settings (custom headers, content response behavior, excluded regions,
/// etc.) are configured via [`with_operation_options`](Self::with_operation_options) — see
/// [`OperationOptions`] for details.
///
/// # Latency
///
/// Because every PATCH is at minimum a Read followed by a Replace, the
/// best-case round-trip floor for ``patch_item`` is **2× the single-RTT
/// cost** of a comparable Read or Replace against the same partition.
/// Each retry triggered by a 412 PreconditionFailed adds another full
/// Read+Replace pair to the wall-clock cost.
///
/// When configuring an end-to-end latency budget via
/// [`OperationOptions`]'s end-to-end request settings, size the budget
/// accordingly — a useful rule of thumb is **≥ 2× the p99 single-RTT
/// budget you would set for a plain Replace**, plus headroom for any
/// 412 retries you want to tolerate. Setting the budget too low can
/// cancel the RMW between the Read and the Replace, producing a
/// timeout error even when the service is healthy.