diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java index 1ab750d8f0..8aba49d90e 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java @@ -148,10 +148,18 @@ public void run() { var primary = primaryResourceCache.get(primaryID); if (primary.isEmpty()) { log.warn("No resource in cache for resource ID: {}", primaryID); - // no new execution is scheduled in this case, an on delete event should be received shortly + // no new execution is scheduled in this case, an on delete event should be received + // shortly; + // the entry is dropped so that it can't block a registration of a recreated resource + scheduledFutures.remove(primaryID); } else { - var actualResources = primary.map(p -> getAndCacheResource(p, false)); - scheduleNextExecution(primary.get(), actualResources.orElse(null)); + Set actualResources = null; + try { + actualResources = getAndCacheResource(primary.get(), false); + } catch (RuntimeException e) { + log.error("Error during polling resources for: {}", primaryID, e); + } + scheduleNextExecution(primary.get(), actualResources); } } } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSourceTest.java index 907ed19fe5..359a54fca0 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSourceTest.java @@ -88,6 +88,33 @@ void pollsTheResourceAfterAwareOfIt() { }); } + @Test + void keepsPollingAfterTheFetcherFailed() { + when(supplier.fetchResources(any())) + .thenThrow(new IllegalStateException("temporary failure")) + .thenReturn(Set.of(SampleExternalResource.testResource1())); + + source.onResourceCreated(testCustomResource); + + await() + .untilAsserted(() -> verify(supplier, atLeast(3)).fetchResources(eq(testCustomResource))); + } + + @Test + void resourceAbsentFromTheCacheCanBeRegisteredAgain() { + when(resourceCache.get(any())).thenReturn(Optional.empty()); + source.onResourceCreated(testCustomResource); + await() + .pollDelay(Duration.ofMillis(2 * PERIOD)) + .untilAsserted(() -> verify(supplier, never()).fetchResources(any())); + + when(resourceCache.get(any())).thenReturn(Optional.of(testCustomResource)); + source.onResourceUpdated(testCustomResource, testCustomResource); + + await() + .untilAsserted(() -> verify(supplier, atLeast(1)).fetchResources(eq(testCustomResource))); + } + @Test void registeringTaskOnAPredicate() { setUpSource(