You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/content/en/docs/documentation/reconciler.md
+118Lines changed: 118 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -169,3 +169,121 @@ You can specify the name of the finalizer to use for your `Reconciler` using the
169
169
annotation. If you do not specify a finalizer name, one will be automatically generated for you.
170
170
171
171
From v5, by default, the finalizer is added using Server Side Apply. See also `UpdateControl` in docs.
172
+
173
+
### Making sure primary is up to date for the next reconciliation
174
+
175
+
When you implement a reconciler as a final step (but maybe also multiple times during one reconciliation), you
176
+
usually update the status subresource with the information that was available during the reconciliation.
177
+
Sometimes this is referred to as the last observed state.
178
+
When the resource is updated, the framework does not cache the resource directly from the response of the update.
179
+
Instead, the underlying informer eventually receives an event with the updated resource and caches the resource.
180
+
Therefore, it can happen that on next reconciliation the primary resource is not up-to-date regarding your updated (note that other event sources
181
+
can trigger the reconciliation meanwhile). This is not usually a problem, since the status is not used as an input,
182
+
the reconciliation runs again, and the status us updated again. The caches are eventually consistent.
183
+
184
+
However, there are cases when you would like to store some state in the status, typically generated
185
+
IDs of external resources.
186
+
See related topic in Kubernetes docs: [Representing Allocated Values](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#representing-allocated-values).
187
+
In this case, it is reasonable to expect to have the state always available for the next reconciliation,
188
+
to avoid generating the resource again and other race conditions.
189
+
190
+
Therefore,
191
+
the framework provides facilities
192
+
to cover these use cases withing [`PrimaryUpdateAndCacheUtils`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/PrimaryUpdateAndCacheUtils.java#L16).
193
+
These utility methods come in two flavors:
194
+
195
+
#### Using internal cache
196
+
197
+
In almost all cases for this purpose, you can use internal caches:
var updatedResource =PrimaryUpdateAndCacheUtils.ssaPatchAndCacheStatus(resource, freshCopy, context);
212
+
213
+
returnUpdateControl.noUpdate();
214
+
}
215
+
```
216
+
217
+
In the background `PrimaryUpdateAndCacheUtils.ssaPatchAndCacheStatusWith` puts the result of the update into an internal
218
+
cache of the event source of primary resource, and will make sure that the next reconciliation will contain the most
219
+
recent version of the resource. Note that it is not necessarily the version from the update response, it can be newer
220
+
since other parties can do additional updates meanwhile, but if not explicitly modified, it will contain the up-to-date
221
+
status.
222
+
223
+
See related integration test [here](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuscache/internal).
224
+
225
+
This approach works with the default configuration of the framework and should be good to go in most of the cases.
226
+
Without going further into the details, this won't work if `ConfigurtionService.parseResourceVersionsForEventFilteringAndCaching`
227
+
is set to `false` (more precisely there are some edge cases when it won't work). For that case framework provides the following solution:
228
+
229
+
#### Using `PrimaryResourceCache` cache
230
+
231
+
As an alternative, you can use an explicit caching approach that the framework supports:
232
+
233
+
```java
234
+
235
+
// We on purpose don't use the provided predicate to show what a custom one could look like.
As shown in the example above, it is up to you to provide a predicate to determine if the resource is more recent than the one available.
277
+
In other words, when to evict the resource from the cache. Typically, as show in the [integration test](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuscache/primarycache)
278
+
you can have a counter in status to check on that.
279
+
280
+
Since all of this happens explicitly, you cannot use it for now with managed dependent resources and workflows.
281
+
282
+
#### Additional remarks
283
+
284
+
As shown in the integration tests, there is no optimistic locking used when updating the
Copy file name to clipboardExpand all lines: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/PrimaryUpdateAndCacheUtils.java
Copy file name to clipboardExpand all lines: operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuscache/internal/StatusPatchCacheReconciler.java
+2-4Lines changed: 2 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -20,8 +20,7 @@ public class StatusPatchCacheReconciler implements Reconciler<StatusPatchCacheCu
Copy file name to clipboardExpand all lines: operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuscache/primarycache/StatusPatchPrimaryCacheReconciler.java
+1-4Lines changed: 1 addition & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -33,8 +33,7 @@ public class StatusPatchPrimaryCacheReconciler
0 commit comments