From be22a885bdcaef7925e2958f97c82be15429c783 Mon Sep 17 00:00:00 2001 From: Sam Barker Date: Wed, 1 Jul 2026 17:40:16 +1200 Subject: [PATCH] test: failing test for EventFilterWindow coalesced foreign spec change (#3455) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a controller's SSA patch merges with a concurrent foreign spec change, the informer can coalesce both events into a single event at the own-write RV. EventFilterWindow sees relatedEvents == ownResourceVersions and silently drops the event, causing the controller to miss the foreign change entirely (stuck until maxReconciliationInterval). The test is @Disabled pending a fix — it documents the expected behaviour that events carrying a generation change should propagate even when their RV matches the controller's own write. Assisted-by: Claude claude-opus-4-6 Signed-off-by: Sam Barker --- .../informer/EventFilterWindowTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/EventFilterWindowTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/EventFilterWindowTest.java index 70f6d1621c..22add73737 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/EventFilterWindowTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/EventFilterWindowTest.java @@ -537,6 +537,38 @@ void reListBetweenTwoUpdates() { assertThat(eventFilterWindow.canBeRemoved()).isTrue(); } + @Test + @Disabled("EventFilterWindow drops coalesced foreign spec changes — #3455") + void coalescedForeignSpecChangeShouldNotBeFilteredByOwnWriteRV() { + // Reproduces the scenario where a controller's SSA patch merges with a concurrent + // foreign spec change. The informer coalesces both events into one at the own-write RV. + // + // Real-world sequence (from Kroxylicious GHA failure): + // 1. Controller reconciles resource at gen=1 + // 2. Foreign actor changes spec → gen=2 → new RV on API server + // 3. Controller's SSA patchResource merges on top → returns RV=5 (gen=2) + // 4. Informer coalesces both events (same resource key) into one at RV=5 + // 5. EventFilterWindow sees relatedEvents={5} == ownResourceVersions={5} → drops + // 6. Controller never learns about gen=2 → stuck until maxReconciliationInterval + eventFilterWindow.increaseActiveUpdates(); + eventFilterWindow.addToOwnUpdateVersions(s(FIRST_OWN_VERSION)); + + var resource = testResource(FIRST_OWN_VERSION); + resource.getMetadata().setGeneration(2L); + var previousResource = testResource(FIRST_OWN_VERSION - 1); + previousResource.getMetadata().setGeneration(1L); + eventFilterWindow.addRelatedEvent( + new ExtendedResourceEvent(UPDATED, resource, previousResource, null)); + + eventFilterWindow.decreaseActiveUpdates(); + + assertThat(eventFilterWindow.check()) + .as( + "Event at own-write RV with generation change (1→2) should propagate:" + + " a foreign spec change was coalesced with the own-write echo") + .isPresent(); + } + @Test void combinedCaseWithEarlyEvent() { // Scenario: an own write is in flight (RV recorded), a foreign event with a