|
1 | 1 | --- |
2 | 2 | title: Welcome read-cache-after-write consistency! |
3 | | -# todo issue with this? |
4 | | -#date: 2026-03-25 |
| 3 | +date: 2026-03-13 |
5 | 4 | author: >- |
6 | 5 | [Attila Mészáros](https://github.com/csviri) |
7 | 6 | --- |
@@ -42,6 +41,8 @@ much simpler to reason about!** |
42 | 41 |
|
43 | 42 | This post will deep dive in this topic, explore the details and rationale behind it. |
44 | 43 |
|
| 44 | +See the related umbrella [issue](https://github.com/operator-framework/java-operator-sdk/issues/2944) on GitHub. |
| 45 | + |
45 | 46 | ## Informers and eventual consistency |
46 | 47 |
|
47 | 48 | First we have to understand a fundamental building block of Kubernetes operators: Informers. |
@@ -229,24 +230,54 @@ events that we received meanwhile, and make a decision to propagate any further |
229 | 230 |
|
230 | 231 | However, this way we significantly reduce the number of reconciliations, thus making the whole process much more efficient. |
231 | 232 |
|
| 233 | +### The case for instant reschedule |
| 234 | + |
| 235 | +We realize that some of our users might rely on the fact that the reconciliation is triggered by own updates. |
| 236 | +To support backwards compatibility or rather migration path, we provide now a way to instruct the framework |
| 237 | +to queue an instant reconciliation: |
| 238 | + |
| 239 | +```java |
| 240 | +public UpdateControl<WebPage> reconcile(WebPage webPage, Context<WebPage> context) { |
| 241 | + |
| 242 | + // omitted reconciliation logic |
| 243 | + |
| 244 | + return UpdateControl.<WebPage>noUpdate().reschedule(); |
| 245 | +} |
| 246 | +``` |
| 247 | + |
232 | 248 | ## Additional considerations and alternatives |
233 | 249 |
|
234 | 250 | An alternative approach would be that when we do an update we don't trigger the next reconciliation until the |
235 | 251 | target resource is not in the Informers cache. The pro side of this is that we don't have to maintain an |
236 | 252 | additional cache of the resource, just the target resource version; therefore there this appraoch might have |
237 | | -a smaller memory footprint, but not necessarily. |
| 253 | +a smaller memory footprint, but not necessarily. This the related [KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/5647-stale-controller-handling#proposal) |
| 254 | +that takes this approach. |
238 | 255 |
|
239 | 256 | On the other hand, when we do a request the response object is always deserialized, regardless if we are going |
240 | 257 | to cache it or not. This object in most cases will be cached for a very short time; and later garbage collected. |
| 258 | +Therefore, the memory overhead should be minimal. |
241 | 259 |
|
| 260 | +Having the TRC has an additional advantage, since we have the resource instantly in our cashes, we can in |
| 261 | +the same reconciliation elegantly continue on reconciliation and reconcile resources that are depending |
| 262 | +on the latest state. More concretely helps also for our [Dependent resources / Workflow](../../docs/documentation/dependent-resource-and-workflows/workflows.md#reconcile-sample) |
| 263 | +which rely on up-to-date caches. In this sense, this is much more optimal regarding throughput. |
242 | 264 |
|
| 265 | +## Conclusion |
243 | 266 |
|
| 267 | +I personally worked on a prototype of an Operator which was depending on an unreleased version of JOSDK already |
| 268 | +implementing these features. The most obvious gain was how much simpler the reasoning is in some cases and how it reduces the corner |
| 269 | +cases that we would have to solve otherwise with [expectation pattern](https://ahmet.im/blog/controller-pitfalls/#expectations-pattern) |
| 270 | +or other facilities. |
244 | 271 |
|
245 | | -## Conclusion |
| 272 | +## Special thanks |
| 273 | + |
| 274 | +I would like to thank all the contributors that directly or indirectly contributed like [metacosm](https://github.com/metacosm), |
| 275 | +[manusa](https://github.com/manusa) and [xstefank](https://github.com/xstefank). |
246 | 276 |
|
247 | | -## Notes |
| 277 | +Last but certainly not least, specially thanks to [Steven Hawkins](https://github.com/shawkins) |
| 278 | +with who maintains the Informer implementation in [fabric8 Kubernetes client](https://github.com/fabric8io/kubernetes-client), |
| 279 | +implemented the first version of the algorithms, then we together iterated multiple times on it. |
| 280 | +Covering all the edge cases was quite an effort. |
| 281 | +Just to as a highlight I put here the [last one](https://github.com/operator-framework/java-operator-sdk/issues/3208). |
248 | 282 |
|
249 | | -TODO: |
250 | | -- alternatives => deferring reconciliation, this is optimized for throughput |
251 | | -- filter events |
252 | | -- reschedule |
| 283 | +Thank you! |
0 commit comments