Skip to content

Commit ddb58d1

Browse files
committed
update methods use match with optimistic locking; update javadoc and docs
1 parent 10a4382 commit ddb58d1

2 files changed

Lines changed: 46 additions & 18 deletions

File tree

docs/content/en/docs/documentation/reconciler.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,18 @@ third-party write. This requires **either**:
207207

208208
- `Options.matchAndFilter(matcher)` / `Options.matchAndFilterWithDefaultMatcher(updateType)` — compare
209209
the desired state to the actual (cached) state; if they already match, skip the write entirely,
210-
otherwise write and filter the own event. This is the **default** for the `ResourceOperations`
211-
update/patch methods, and generally the most efficient option: it filters the own event *and*
212-
avoids a request to the API server when nothing changed. Default matchers are provided for every
213-
operation type, but they are heuristics — a workflow relying on them should be tested against the
214-
concrete resources it manages, or a custom matcher supplied.
210+
otherwise write and filter the own event. This is the **default** for the server-side apply and
211+
patch (JSON Patch / JSON Merge Patch) methods, and generally the most efficient option: it filters
212+
the own event *and* avoids a request to the API server when nothing changed. Default matchers are
213+
provided for every operation type, but they are heuristics — a workflow relying on them should be
214+
tested against the concrete resources it manages, or a custom matcher supplied.
215215
- `Options.filterWithOptimisticLocking()` — filter the own event; the write must use optimistic
216216
locking (a resource version set on the written resource), otherwise an `IllegalArgumentException`
217217
is thrown. Requiring optimistic locking guarantees a concurrent third-party change is rejected by
218-
the API server rather than being silently filtered out.
218+
the API server rather than being silently filtered out. The overloads taking a matcher /
219+
`updateType` additionally skip the write when the desired state already matches. This match +
220+
optimistic locking combination is the **default** for the PUT `update` / `updatePrimary` /
221+
`updatePrimaryStatus` methods (a full PUT should not clobber a concurrent change).
219222
- `Options.cacheOnly()` — only cache the response (read-cache-after-write consistency), no own-event
220223
filtering.
221224
- `Options.forceFilterEvents()` — always filter, regardless of optimistic locking. Only safe when

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceOperations.java

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -325,15 +325,17 @@ public P serverSideApplyPrimaryStatus(P desired, Options options) {
325325
* it (read-cache-after-write consistency).
326326
*
327327
* <p>Uses the {@link UpdateType#UPDATE} default {@link Matcher}: the update is skipped when the
328-
* actual (cached) state already matches the desired one, otherwise it is performed and the
329-
* resulting own event is filtered. Use {@link #update(HasMetadata, Options)} to change this.
328+
* actual (cached) state already matches the desired one, otherwise it is performed using
329+
* optimistic locking (the resource version must be set, otherwise an {@link
330+
* IllegalArgumentException} is thrown) and the resulting own event is filtered. Use {@link
331+
* #update(HasMetadata, Options)} to change this.
330332
*
331333
* @param resource the desired resource to update
332334
* @param <R> the resource type
333335
* @return the updated resource as returned by the API server
334336
*/
335337
public <R extends HasMetadata> R update(R resource) {
336-
return update(resource, Options.matchAndFilterWithDefaultMatcher(UpdateType.UPDATE));
338+
return update(resource, Options.filterWithOptimisticLocking(UpdateType.UPDATE));
337339
}
338340

339341
/**
@@ -351,7 +353,9 @@ public <R extends HasMetadata> R update(R desired, Options options) {
351353

352354
/**
353355
* Updates (HTTP PUT) the resource, caching and filtering the own event through the given {@link
354-
* InformerEventSource}. Uses the {@link UpdateType#UPDATE} default {@link Matcher}.
356+
* InformerEventSource}. Uses the {@link UpdateType#UPDATE} default {@link Matcher} and optimistic
357+
* locking: the update is skipped when the actual state already matches, otherwise it is performed
358+
* with optimistic locking (the resource version must be set) and the own event is filtered.
355359
*
356360
* @param resource the desired resource to update
357361
* @param informerEventSource the event source used for caching and own-event filtering
@@ -361,7 +365,7 @@ public <R extends HasMetadata> R update(R desired, Options options) {
361365
public <R extends HasMetadata> R update(
362366
R resource, InformerEventSource<R, P> informerEventSource) {
363367
return update(
364-
resource, informerEventSource, Options.matchAndFilterWithDefaultMatcher(UpdateType.UPDATE));
368+
resource, informerEventSource, Options.filterWithOptimisticLocking(UpdateType.UPDATE));
365369
}
366370

367371
/**
@@ -439,15 +443,17 @@ public <R extends HasMetadata> R create(
439443

440444
/**
441445
* Updates (HTTP PUT) the resource {@code status} subresource, caching the response and filtering
442-
* the own event. Uses the {@link UpdateType#UPDATE_STATUS} default {@link Matcher}.
446+
* the own event. Uses the {@link UpdateType#UPDATE_STATUS} default {@link Matcher} and optimistic
447+
* locking: the update is skipped when the actual status already matches, otherwise it is
448+
* performed with optimistic locking (the resource version must be set, otherwise an {@link
449+
* IllegalArgumentException} is thrown) and the own event is filtered.
443450
*
444451
* @param resource the desired resource (with the status to update)
445452
* @param <R> the resource type
446453
* @return the updated resource as returned by the API server
447454
*/
448455
public <R extends HasMetadata> R updateStatus(R resource) {
449-
return updateStatus(
450-
resource, Options.matchAndFilterWithDefaultMatcher(UpdateType.UPDATE_STATUS));
456+
return updateStatus(resource, Options.filterWithOptimisticLocking(UpdateType.UPDATE_STATUS));
451457
}
452458

453459
/**
@@ -465,13 +471,16 @@ public <R extends HasMetadata> R updateStatus(R resource, Options options) {
465471

466472
/**
467473
* Updates (HTTP PUT) the primary resource, caching and filtering the own event through the
468-
* controller's own event source. Uses the {@link UpdateType#UPDATE} default {@link Matcher}.
474+
* controller's own event source. Uses the {@link UpdateType#UPDATE} default {@link Matcher} and
475+
* optimistic locking: the update is skipped when the actual state already matches, otherwise it
476+
* is performed with optimistic locking (the resource version must be set) and the own event is
477+
* filtered.
469478
*
470479
* @param desired the desired primary resource to update
471480
* @return the updated resource as returned by the API server
472481
*/
473482
public P updatePrimary(P desired) {
474-
return updatePrimary(desired, Options.matchAndFilterWithDefaultMatcher(UpdateType.UPDATE));
483+
return updatePrimary(desired, Options.filterWithOptimisticLocking(UpdateType.UPDATE));
475484
}
476485

477486
/**
@@ -493,7 +502,9 @@ public P updatePrimary(P desired, Options options) {
493502
/**
494503
* Updates (HTTP PUT) the primary resource {@code status} subresource, caching and filtering the
495504
* own event through the controller's own event source. Uses the {@link UpdateType#UPDATE_STATUS}
496-
* default {@link Matcher}.
505+
* default {@link Matcher} and optimistic locking: the update is skipped when the actual status
506+
* already matches, otherwise it is performed with optimistic locking (the resource version must
507+
* be set) and the own event is filtered.
497508
*
498509
* @param desired the desired primary resource (with the status to update)
499510
* @return the updated resource as returned by the API server
@@ -503,7 +514,7 @@ public P updatePrimaryStatus(P desired) {
503514
desired,
504515
r -> context.getClient().resource(r).updateStatus(),
505516
context.eventSourceRetriever().getControllerEventSource(),
506-
Options.matchAndFilterWithDefaultMatcher(UpdateType.UPDATE_STATUS));
517+
Options.filterWithOptimisticLocking(UpdateType.UPDATE_STATUS));
507518
}
508519

509520
/**
@@ -1342,6 +1353,20 @@ public static Options filterWithOptimisticLocking(Matcher matcher) {
13421353
return new Options(Mode.FILTER_WITH_OPTIMISTIC_LOCKING, matcher);
13431354
}
13441355

1356+
/**
1357+
* Like {@link #filterWithOptimisticLocking()} but additionally skips the write when the desired
1358+
* state already matches the actual (cached) state according to the default {@link Matcher} of
1359+
* the given {@link UpdateType}. When a write is needed it still requires optimistic locking
1360+
* (see {@link #filterWithOptimisticLocking()}).
1361+
*
1362+
* @param updateType the update type whose default matcher should be used
1363+
* @return options that match using the update type's default matcher and, when a write is
1364+
* needed, filter the own event requiring optimistic locking
1365+
*/
1366+
public static Options filterWithOptimisticLocking(UpdateType updateType) {
1367+
return new Options(Mode.FILTER_WITH_OPTIMISTIC_LOCKING, updateType.getMatcher());
1368+
}
1369+
13451370
/**
13461371
* Filters own updates and, before doing so, checks whether the actual resource already matches
13471372
* the desired state using the given {@link Matcher}.

0 commit comments

Comments
 (0)