From ff1d78da0b4394eebdc7f45eb9b68693c39c3f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:03:22 +0100 Subject: [PATCH 01/12] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../en/docs/documentation/reconciler.md | 106 +++++++++++++++--- 1 file changed, 93 insertions(+), 13 deletions(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index a1e3e802a3..cf667e799a 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -160,7 +160,87 @@ annotation. If you do not specify a finalizer name, one will be automatically ge From v5, by default, the finalizer is added using Server Side Apply. See also `UpdateControl` in docs. -### Making sure the primary resource is up to date for the next reconciliation +### Read-cache-after-write consistency and event filtering + +It is an inherent issue with Informers that their caches are eventually consistent even +with the updates to Kubernetes API done from the controller. From version 5.3.0 the framework +supports stronger guarantees, both for primary and secondary resources. If this feature is used: + +1. Reading cache after our update - even withing same reconciliation - returns the fresh resource. + Fresh means at least the version of the resource that is in the response form our update. + Or more recent one if some other party updated the resource after our update. +2. Filtering events for the update from the controller. If the controller updates a resource + the event produced the Kubernetes API and propagated to Informer would normally trigger a next + reconciliation, however this is not ideal, since we already have that up-to-date resource + in the cache in the current reconciliation, so in general it is not desirable to reconcile that again. + This feature makes sure that the reconciliation is not triggered from the event from our writes. + + +In order to have these guarantees use [`ResourceOperations`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceOperations.java) +from the context of the reconciliation: + +```java + +public UpdateControl reconcile(WebPage webPage, Context context) { + + ConfigMap managedConfigMap = prepareConfigMap(webPage); + // filtering and caching update + context.resourceOperations().serverSideApply(desiredIngress); + + // fresh resource already available from our update in caches + var upToDateResource = context.getSecondaryResource(ConfigMap.class); + + makeStatusChanages(webPage); + + // built in update methods by default uses this approach + return UpdateControl.patchStatus(webPage); +} +``` + +### Built-in patches + +`UpdateControl` and `ErrorStatusUpdateControl` by default uses this functionality. + +Mainly to cover migration path for the cases when somebody expected events for their update +a these controls now contain a new method: `UpdateControl.reschedule()`, that instantly propagates +an event to reschedule the reconciliation. + +### Allocated values + +If you want to store some state - like generated IDs - in `.status` sub-resource, you +can do it safely with this feature. Since it is guaranteed that you will see the update +in the next reconciliation. + +Note that this is not just with `UpdateControl` you can also do update any time on primary resource +with `resourceOperations`: + +```java + +public UpdateControl reconcile(WebPage webPage, Context context) { + + makeStatusChanages(webPage); + // this is equivalent with the update done by UpdateControl + context.resourceOperations().serverSideApplyPrimaryStatus(desiredIngress); + + return UpdateControl.noUpdate(); +} +``` + +### Notes +- Talk about this feature in this [talk](https://www.youtube.com/watch?v=HrwHh5Yh6AM&t=1387s). +- [Umbrella issue](https://github.com/operator-framework/java-operator-sdk/issues/2944) on our GitHub. +- We were able to implement this feature since Kubernetes introduces guideline to compare + resource versions. See the details [here](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/5504-comparable-resource-version). + +### Making sure the primary resource is up to date for the next reconciliation (deprecated) + +{{% alert title="Deprecated" %}} + +Read-cache-after-write consistency feature replaces this functionality. + +> It provides this functionality also for secondary resources and optimistic locking + is not required anymore. See details above. +{{% /alert %}} It is typical to want to update the status subresource with the information that is available during the reconciliation. This is sometimes referred to as the last observed state. When the primary resource is updated, though, the framework @@ -263,30 +343,30 @@ See also [sample](https://github.com/operator-framework/java-operator-sdk/blob/m ### Expectations Expectations are a pattern to ensure that, during reconciliation, your secondary resources are in a certain state. -For a more detailed explanation see [this blogpost](https://ahmet.im/blog/controller-pitfalls/#expectations-pattern). -You can find framework support for this pattern in [`io.javaoperatorsdk.operator.processing.expectation`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/expectation/) -package. See also related [integration test](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/expectation/ExpectationReconciler.java). -Note that this feature is marked as `@Experimental`, since based on feedback the API might be improved / changed, but we intend -to support it, later also might be integrated to Dependent Resources and/or Workflows. +For a more detailed explanation, see [this blogpost](https://ahmet.im/blog/controller-pitfalls/#expectations-pattern). +You can find framework support for this pattern in the [`io.javaoperatorsdk.operator.processing.expectation`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/expectation/) +package. See also the related [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/expectation/ExpectationReconciler.java). +Note that this feature is marked as `@Experimental`: based on feedback the API may be improved or changed, but we intend +to keep supporting it and may later integrate it into Dependent Resources and/or Workflows. -The idea is the nutshell, is that you can track your expectations in the expectation manager in the reconciler -which has an API that covers the common use cases. +The idea, in a nutshell, is that you can track your expectations in the expectation manager within the reconciler, +which provides an API covering the common use cases. -The following sample is the simplified version of the integration test that implements the logic that creates a -deployment and sets status message if there are the target three replicas ready: +The following is a simplified version of the integration test that implements the logic to create a +deployment and set a status message once the target three replicas are ready: ```java public class ExpectationReconciler implements Reconciler { // some code is omitted - + private final ExpectationManager expectationManager = new ExpectationManager<>(); @Override public UpdateControl reconcile( ExpectationCustomResource primary, Context context) { - // exiting asap if there is an expectation that is not timed out neither fulfilled yet + // exit early if there is an expectation that has not yet timed out or been fulfilled if (expectationManager.ongoingExpectationPresent(primary, context)) { return UpdateControl.noUpdate(); } @@ -299,7 +379,7 @@ public class ExpectationReconciler implements Reconciler Date: Sun, 1 Mar 2026 20:13:19 +0100 Subject: [PATCH 02/12] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/docs/documentation/reconciler.md | 16 ++++++++++++---- .../docs/documentation/working-with-es-caches.md | 6 ++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index cf667e799a..edd1fdade2 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -169,11 +169,11 @@ supports stronger guarantees, both for primary and secondary resources. If this 1. Reading cache after our update - even withing same reconciliation - returns the fresh resource. Fresh means at least the version of the resource that is in the response form our update. Or more recent one if some other party updated the resource after our update. -2. Filtering events for the update from the controller. If the controller updates a resource - the event produced the Kubernetes API and propagated to Informer would normally trigger a next - reconciliation, however this is not ideal, since we already have that up-to-date resource +2. Filtering events for our updates. If the controller updates a resource + an event is produced by the Kubernetes API and propagated to Informer, what would normally trigger a next + reconciliation. However, this is not ideal, since we already have that up-to-date resource in the cache in the current reconciliation, so in general it is not desirable to reconcile that again. - This feature makes sure that the reconciliation is not triggered from the event from our writes. + This feature also makes sure that the reconciliation is not triggered from the event from our writes. In order to have these guarantees use [`ResourceOperations`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceOperations.java) @@ -226,6 +226,14 @@ public UpdateControl reconcile(WebPage webPage, Context contex } ``` +### Caveats + +- This feature is implemented on top of fabric8 client informers using additional caches in `InformerEventSource`, + so it is safe to use `context.getSecondaryResources(..)` or `InformerEventSource.get(ResourceID)` + methods. However won't work with `InformerEventSource.list(..)` method, since it directly reads + the underlying informer cache. + + ### Notes - Talk about this feature in this [talk](https://www.youtube.com/watch?v=HrwHh5Yh6AM&t=1387s). - [Umbrella issue](https://github.com/operator-framework/java-operator-sdk/issues/2944) on our GitHub. diff --git a/docs/content/en/docs/documentation/working-with-es-caches.md b/docs/content/en/docs/documentation/working-with-es-caches.md index bb1e140303..a190d2a6cb 100644 --- a/docs/content/en/docs/documentation/working-with-es-caches.md +++ b/docs/content/en/docs/documentation/working-with-es-caches.md @@ -216,3 +216,9 @@ With this index in place, you can retrieve the target resources very efficiently .collect(Collectors.toSet())) .withNamespacesInheritedFromController().build(), context); ``` + +## Read-cache-after-write consistency and event filtering + +From version 5.3.0 we provide stronger consistency guarantees and +other features on top of basic informers, see [this section](reconciler.md#read-cache-after-write-consistency-and-event-filtering) +for details. \ No newline at end of file From ba64b156903fe3607839377c18f0ccafe998e4d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:16:52 +0100 Subject: [PATCH 03/12] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/docs/documentation/reconciler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index edd1fdade2..c4566457de 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -187,7 +187,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex // filtering and caching update context.resourceOperations().serverSideApply(desiredIngress); - // fresh resource already available from our update in caches + // fresh resource instantly available from our update in the cache var upToDateResource = context.getSecondaryResource(ConfigMap.class); makeStatusChanages(webPage); From 6b8077a3ebaba5438fe0ff94ad67a9b8f8dc549b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:18:15 +0100 Subject: [PATCH 04/12] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/docs/documentation/reconciler.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index c4566457de..4c1e1e4d32 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -219,9 +219,8 @@ with `resourceOperations`: public UpdateControl reconcile(WebPage webPage, Context context) { makeStatusChanages(webPage); - // this is equivalent with the update done by UpdateControl + // this is equivalent to UpdateControl.patchStatus(webpage) context.resourceOperations().serverSideApplyPrimaryStatus(desiredIngress); - return UpdateControl.noUpdate(); } ``` From 3f54e58f43601c6077f5ad9056a0cfe46d419424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:26:22 +0100 Subject: [PATCH 05/12] Update docs/content/en/docs/documentation/reconciler.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Attila Mészáros --- docs/content/en/docs/documentation/reconciler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index 4c1e1e4d32..a8062ceb0b 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -185,7 +185,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex ConfigMap managedConfigMap = prepareConfigMap(webPage); // filtering and caching update - context.resourceOperations().serverSideApply(desiredIngress); + context.resourceOperations().serverSideApply(managedConfigMap); // fresh resource instantly available from our update in the cache var upToDateResource = context.getSecondaryResource(ConfigMap.class); From 7a8b94654290126f3629ed9f4a138578da5b0140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:26:35 +0100 Subject: [PATCH 06/12] Update docs/content/en/docs/documentation/reconciler.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Attila Mészáros --- docs/content/en/docs/documentation/reconciler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index a8062ceb0b..ba2894430a 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -220,7 +220,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex makeStatusChanages(webPage); // this is equivalent to UpdateControl.patchStatus(webpage) - context.resourceOperations().serverSideApplyPrimaryStatus(desiredIngress); + context.resourceOperations().serverSideApplyPrimaryStatus(webPage); return UpdateControl.noUpdate(); } ``` From 5b65852c2821c01ea484702fee92f938dd5793b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:26:44 +0100 Subject: [PATCH 07/12] Update docs/content/en/docs/documentation/reconciler.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Attila Mészáros --- docs/content/en/docs/documentation/reconciler.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index ba2894430a..b831c825c0 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -166,9 +166,9 @@ It is an inherent issue with Informers that their caches are eventually consiste with the updates to Kubernetes API done from the controller. From version 5.3.0 the framework supports stronger guarantees, both for primary and secondary resources. If this feature is used: -1. Reading cache after our update - even withing same reconciliation - returns the fresh resource. - Fresh means at least the version of the resource that is in the response form our update. - Or more recent one if some other party updated the resource after our update. +1. Reading from the cache after our update — even within the same reconciliation — returns a fresh resource. + "Fresh" means at least the version of the resource that is in the response from our update, + or a more recent version if some other party updated the resource after our update. 2. Filtering events for our updates. If the controller updates a resource an event is produced by the Kubernetes API and propagated to Informer, what would normally trigger a next reconciliation. However, this is not ideal, since we already have that up-to-date resource From 8e8a918b7aa184e2da6b1a4f8ba0239b36e0aa38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:28:07 +0100 Subject: [PATCH 08/12] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Attila Mészáros --- docs/content/en/docs/documentation/reconciler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index b831c825c0..e90392605b 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -352,7 +352,7 @@ See also [sample](https://github.com/operator-framework/java-operator-sdk/blob/m Expectations are a pattern to ensure that, during reconciliation, your secondary resources are in a certain state. For a more detailed explanation, see [this blogpost](https://ahmet.im/blog/controller-pitfalls/#expectations-pattern). You can find framework support for this pattern in the [`io.javaoperatorsdk.operator.processing.expectation`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/expectation/) -package. See also the related [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/expectation/ExpectationReconciler.java). +package. See also the related [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/expectation/onallevent/ExpectationReconciler.java). Note that this feature is marked as `@Experimental`: based on feedback the API may be improved or changed, but we intend to keep supporting it and may later integrate it into Dependent Resources and/or Workflows. From 53bec13f1ba4e07f224bc95db13665bcd2471b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:29:36 +0100 Subject: [PATCH 09/12] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/docs/documentation/reconciler.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index e90392605b..8ca67feabe 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -192,7 +192,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex makeStatusChanages(webPage); - // built in update methods by default uses this approach + // built in update methods by default use this feature return UpdateControl.patchStatus(webPage); } ``` @@ -202,7 +202,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex `UpdateControl` and `ErrorStatusUpdateControl` by default uses this functionality. Mainly to cover migration path for the cases when somebody expected events for their update -a these controls now contain a new method: `UpdateControl.reschedule()`, that instantly propagates +these controls now contain a new method: `UpdateControl.reschedule()`, that instantly propagates an event to reschedule the reconciliation. ### Allocated values From 5919299532a1b54904da89383a60e6f72708df46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:39:39 +0100 Subject: [PATCH 10/12] Update docs/content/en/docs/documentation/reconciler.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/content/en/docs/documentation/reconciler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index 8ca67feabe..fa43e708c4 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -218,7 +218,7 @@ with `resourceOperations`: public UpdateControl reconcile(WebPage webPage, Context context) { - makeStatusChanages(webPage); + makeStatusChanges(webPage); // this is equivalent to UpdateControl.patchStatus(webpage) context.resourceOperations().serverSideApplyPrimaryStatus(webPage); return UpdateControl.noUpdate(); From 4c5ebbc5c89e00c7c90a42d94524d55eea89b047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 20:39:45 +0100 Subject: [PATCH 11/12] Update docs/content/en/docs/documentation/reconciler.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/content/en/docs/documentation/reconciler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/docs/documentation/reconciler.md b/docs/content/en/docs/documentation/reconciler.md index fa43e708c4..4bb253054f 100644 --- a/docs/content/en/docs/documentation/reconciler.md +++ b/docs/content/en/docs/documentation/reconciler.md @@ -190,7 +190,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex // fresh resource instantly available from our update in the cache var upToDateResource = context.getSecondaryResource(ConfigMap.class); - makeStatusChanages(webPage); + makeStatusChanges(webPage); // built in update methods by default use this feature return UpdateControl.patchStatus(webPage); From 5fbba8c772a72f8d571371fde686d741f1f74558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 1 Mar 2026 21:30:29 +0100 Subject: [PATCH 12/12] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../content/en/blog/news/primary-cache-for-next-recon.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/content/en/blog/news/primary-cache-for-next-recon.md b/docs/content/en/blog/news/primary-cache-for-next-recon.md index 67326a6f17..be84e08a7e 100644 --- a/docs/content/en/blog/news/primary-cache-for-next-recon.md +++ b/docs/content/en/blog/news/primary-cache-for-next-recon.md @@ -5,6 +5,15 @@ author: >- [Attila Mészáros](https://github.com/csviri) and [Chris Laprun](https://github.com/metacosm) --- +{{% alert title="Deprecated" %}} + +Read-cache-after-write consistency feature replaces this functionality. (since version 5.3.0) + +> It provides this functionality also for secondary resources and optimistic locking +is not required anymore. See [details here](./../../docs/documentation/reconciler.md#read-cache-after-write-consistency-and-event-filtering). +{{% /alert %}} + + We recently released v5.1 of Java Operator SDK (JOSDK). One of the highlights of this release is related to a topic of so-called [allocated values](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#representing-allocated-values