Skip to content

improve: filter only own updates for read-after-write-conistency#3414

Open
csviri wants to merge 38 commits into
operator-framework:mainfrom
csviri:event-filter-support
Open

improve: filter only own updates for read-after-write-conistency#3414
csviri wants to merge 38 commits into
operator-framework:mainfrom
csviri:event-filter-support

Conversation

@csviri

@csviri csviri commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Updated implementation of event filtering for read after write consistency. Now we are filtering only events for our own updates, and always eagerly producing an event that is equivalent to a real life possible event.

The algorithm is now relatively simple and easily unit testable.

The idead is that we just maintain a state and in every place it might produce an event we execute the same check method, see in EventFilterWindow:

The PR is prepared for re-list callback, but that part is commented out, but tested in EventFilterSupportTest,EventFilterWindowTest.

See: fabric8io/kubernetes-client#7899

@openshift-ci openshift-ci Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Jun 11, 2026
@csviri csviri linked an issue Jun 11, 2026 that may be closed by this pull request
@csviri csviri changed the title fix: only filter own events improve: filter only own updates for read-after-write-conistency Jun 11, 2026
@csviri csviri changed the title improve: filter only own updates for read-after-write-conistency [WIP] improve: filter only own updates for read-after-write-conistency Jun 11, 2026
@csviri csviri force-pushed the event-filter-support branch 2 times, most recently from 5dc5f9c to a18c124 Compare June 11, 2026 12:58
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 11, 2026
@csviri csviri requested a review from Copilot June 12, 2026 08:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the “read cache after write / filter only own updates” logic into dedicated event-filtering classes and expands coverage with new regression/integration tests for tricky timing scenarios (external updates during own writes, concurrent delete vs status update, etc.) in the operator framework’s informer/controller event pipelines.

Changes:

  • Replaces the previous ad-hoc temp-cache filtering logic with EventFilterSupport / EventFilterWindow and a unified GenericResourceEvent model.
  • Updates informer/controller event sources to use the new filtering API and adjusts unit tests accordingly.
  • Adds new integration tests covering external updates racing with controller updates and deletion racing with status patch.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pom.xml Adds a commented Fabric8 client SNAPSHOT override line.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/readownupdates/ReadOwnUpdatesStatus.java Renames/moves the status model into the new readownupdates package.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/readownupdates/ReadOwnUpdatesReconciler.java Renames/moves reconciler and adapts types to ReadOwnUpdates* classes.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/readownupdates/ReadOwnUpdatesIT.java Renames/moves IT and updates references to new reconciler/CR types.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/readownupdates/ReadOwnUpdatesCustomResource.java Renames/moves CR class and updates short name/type parameters.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/filterpatchevent/FilterPatchEventTestReconciler.java Moves test reconciler into readcacheafterwrite package and updates static import.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/filterpatchevent/FilterPatchEventTestCustomResourceStatus.java Moves status class into readcacheafterwrite package.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/filterpatchevent/FilterPatchEventTestCustomResource.java Moves CR class into readcacheafterwrite package.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/filterpatchevent/FilterPatchEventIT.java Moves IT into readcacheafterwrite package.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/externalupdateduringownupdate/ExternalUpdateDuringOwnUpdateStatus.java New status model for external-update-during-own-update IT.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/externalupdateduringownupdate/ExternalUpdateDuringOwnUpdateReconciler.java New reconciler to coordinate a status patch while an external label update occurs.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/externalupdateduringownupdate/ExternalUpdateDuringOwnUpdateIT.java New IT validating external updates aren’t incorrectly filtered during own write windows.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/externalupdateduringownupdate/ExternalUpdateDuringOwnUpdateCustomResource.java New CR type for the external-update-during-own-update scenario.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/externalsecondaryupdate/ExternalSecondaryUpdateStatus.java New status model for external secondary update scenario.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/externalsecondaryupdate/ExternalSecondaryUpdateReconciler.java New reconciler exercising secondary SSA updates with external metadata changes between them.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/externalsecondaryupdate/ExternalSecondaryUpdateIT.java New IT ensuring external secondary events propagate and are visible via merged caches.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/externalsecondaryupdate/ExternalSecondaryUpdateCustomResource.java New CR type for the external-secondary-update scenario.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/deletionduringstatusupdate/DeletionDuringStatusUpdateStatus.java New status model for deletion-during-status-update regression scenario.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/deletionduringstatusupdate/DeletionDuringStatusUpdateReconciler.java New reconciler that patches status while delete races, to reproduce regression.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/deletionduringstatusupdate/DeletionDuringStatusUpdateIT.java New IT verifying cleanup is triggered when delete races with a status update.
operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/readcacheafterwrite/deletionduringstatusupdate/DeletionDuringStatusUpdateCustomResource.java New CR type for deletion-during-status-update scenario.
operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/TemporaryResourceCacheTest.java Updates unit tests to new filtering API and adds new regression assertions.
operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSourceTest.java Reworks informer event source tests for the new filtering model and behaviors.
operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/EventFilterWindowTest.java New unit test suite for EventFilterWindow behavior.
operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/EventFilterSupportTest.java New unit tests for EventFilterSupport orchestration and lifecycle.
operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSourceTest.java Updates controller event-source tests to new filtering semantics and expected propagation.
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/TemporaryResourceCache.java Refactors temp cache to delegate filtering to EventFilterSupport and emit GenericResourceEvent.
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java Updates the event-filtering update wrapper to use the new GenericResourceEvent path.
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java Updates add/update/delete handling to work with Optional event emission/defer semantics.
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/GenericResourceEvent.java Renames/repurposes the prior event type and adds delete “unknown state” support.
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/EventFilterWindow.java New implementation encapsulating filter-window state + synthesis logic.
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/EventFilterSupport.java New support class coordinating windows per resource ID.
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/EventFilterDetails.java Removes the previous EventFilterDetails implementation (replaced by the new classes).
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSource.java Updates controller event path to use Optional events from the new temp-cache filter.
Comments suppressed due to low confidence (2)

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/GenericResourceEvent.java:30

  • The field name lastStateUnknow (and its getter) is misspelled; this becomes part of a public API on a public class and will likely be used by callers/tests. Consider renaming to lastStateUnknown (and updating call sites) to avoid locking in the typo.
    operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/GenericResourceEvent.java:71
  • equals currently ignores lastStateUnknow, and hashCode therefore can’t reflect that state either. That can cause delete events that differ only by deletedFinalStateUnknown to be treated as identical (e.g., in tests or de-duplication logic).

Comment thread pom.xml Outdated
<fabric8-httpclient-impl.name>jdk</fabric8-httpclient-impl.name>
<junit.version>6.1.0</junit.version>
<fabric8-client.version>7.7.0</fabric8-client.version>
<!-- <fabric8-client.version>999-SNAPSHOT</fabric8-client.version>-->
Comment on lines +86 to +88
public synchronized void setStartingReList(String lastKnownVersion) {
eventFilterWindows.values().forEach(au -> au.setReListStartedFrom(lastKnownVersion));
}
Comment on lines +125 to +129
var resultEvent =
temporaryResourceCache.onDeleteEvent(resource, deletedFinalStateUnknown);
if (resultEvent.isEmpty()) {
return;
}
@csviri csviri requested a review from Copilot June 12, 2026 14:09
@csviri csviri changed the title [WIP] improve: filter only own updates for read-after-write-conistency improve: filter only own updates for read-after-write-conistency Jun 12, 2026
@csviri csviri marked this pull request as ready for review June 12, 2026 14:09
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 12, 2026
@openshift-ci openshift-ci Bot requested review from metacosm and xstefank June 12, 2026 14:09
csviri added 11 commits June 12, 2026 16:09
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
csviri and others added 18 commits June 12, 2026 16:09
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
… re-list

Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 34 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/GenericResourceEvent.java:49

  • Typo in public API: getLastStateUnknow() should be getLastStateUnknown() (and the underlying field name as well) to match existing terminology like deletedFinalStateUnknown. Keeping the typo in a public method will be hard to change later.

Comment thread pom.xml Outdated
<fabric8-httpclient-impl.name>jdk</fabric8-httpclient-impl.name>
<junit.version>6.1.0</junit.version>
<fabric8-client.version>7.7.0</fabric8-client.version>
<!-- <fabric8-client.version>999-SNAPSHOT</fabric8-client.version>-->
Comment on lines +125 to +129
var resultEvent =
temporaryResourceCache.onDeleteEvent(resource, deletedFinalStateUnknown);
if (resultEvent.isEmpty()) {
return;
}
Comment on lines +153 to +156
// @Override
// public void onBeforeList(String lastSyncResourceVersion) {
// temporaryResourceCache.setOngoingRelist(lastSyncResourceVersion);
// }
csviri added 5 commits June 12, 2026 16:21
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 33 out of 33 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/GenericResourceEvent.java:49

  • Typo in API: lastStateUnknow / getLastStateUnknow() should be lastStateUnknown / getLastStateUnknown(). The misspelling is now part of a public type and is referenced across the codebase, making future cleanup harder.

Comment on lines +125 to 136
var resultEvent =
temporaryResourceCache.onDeleteEvent(resource, deletedFinalStateUnknown);
if (resultEvent.isEmpty()) {
return;
}
if (resultEvent.orElseThrow().getAction() != ResourceAction.DELETED) {
log.warn("Non delete event received on onDelete handling. This should not happen.");
}
primaryToSecondaryIndex.onDelete(resource);
temporaryResourceCache.onDeleteEvent(resource, deletedFinalStateUnknown);
if (acceptedByDeleteFilters(resource, deletedFinalStateUnknown)) {
propagateEvent(resource);
}
Comment on lines 85 to 88
if (log.isDebugEnabled()) {
log.debug("Event received with action: {}", action);
log.trace("Event Old resource: {},\n new resource: {}", oldResource, resource);
log.debug("Event Old resource: {},\n new resource: {}", oldResource, resource);
}
Comment on lines +256 to +258
public synchronized void setOngoingRelist(String lastKnownSyncVersion) {
eventFilteringSupport.setStartingReList();
}
Comment on lines +260 to 263
public synchronized void setRelistFinished(String syncResourceVersions) {
// turned off until client support
// eventFilteringSupport.setRelistFinished();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Filtering ONLY own events in read-after-write-consitency

2 participants