From 47dac487d3660bf7c8f155e9c47658e03aae887f Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 22 Aug 2023 13:02:00 +0200 Subject: [PATCH] feat: re-schedule from error handler --- .../operator/api/reconciler/BaseControl.java | 2 +- .../reconciler/ErrorStatusUpdateControl.java | 17 +++++++++++++++-- .../event/ReconciliationDispatcher.java | 8 ++++++-- .../event/ReconciliationDispatcherTest.java | 18 ++++++++++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/BaseControl.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/BaseControl.java index ac51bb7263..a5cdb85257 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/BaseControl.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/BaseControl.java @@ -9,7 +9,7 @@ public abstract class BaseControl> { private Long scheduleDelay = null; public T rescheduleAfter(long delay) { - this.scheduleDelay = delay; + rescheduleAfter(Duration.ofMillis(delay)); return (T) this; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ErrorStatusUpdateControl.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ErrorStatusUpdateControl.java index 6d317161f7..48c0e32946 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ErrorStatusUpdateControl.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ErrorStatusUpdateControl.java @@ -1,16 +1,17 @@ package io.javaoperatorsdk.operator.api.reconciler; +import java.time.Duration; import java.util.Optional; import io.fabric8.kubernetes.api.model.HasMetadata; -public class ErrorStatusUpdateControl

{ +public class ErrorStatusUpdateControl

+ extends BaseControl> { private final P resource; private final boolean patch; private boolean noRetry = false; - public static ErrorStatusUpdateControl patchStatus(T resource) { return new ErrorStatusUpdateControl<>(resource, true); } @@ -49,4 +50,16 @@ public boolean isNoRetry() { public boolean isPatch() { return patch; } + + /** + * If re-scheduled using this method, it is not considered as retry, it effectively cancels retry. + * + * @param delay for next execution + * @return ErrorStatusUpdateControl + */ + @Override + public ErrorStatusUpdateControl

rescheduleAfter(Duration delay) { + withNoRetry(); + return super.rescheduleAfter(delay); + } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java index 78f42e3bed..9a110a7ba8 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java @@ -201,13 +201,17 @@ public boolean isLastAttempt() { .updateStatus(errorStatusUpdateControl.getResource().orElseThrow()); } if (errorStatusUpdateControl.isNoRetry()) { + PostExecutionControl

postExecutionControl; if (updatedResource != null) { - return errorStatusUpdateControl.isPatch() + postExecutionControl = errorStatusUpdateControl.isPatch() ? PostExecutionControl.customResourceStatusPatched(updatedResource) : PostExecutionControl.customResourceUpdated(updatedResource); } else { - return PostExecutionControl.defaultDispatch(); + postExecutionControl = PostExecutionControl.defaultDispatch(); } + errorStatusUpdateControl.getScheduleDelay() + .ifPresent(postExecutionControl::withReSchedule); + return postExecutionControl; } } catch (RuntimeException ex) { log.error("Error during error status handling.", ex); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java index 9b113625df..c6aacb9071 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java @@ -673,6 +673,24 @@ void retriesAddingFinalizer() { verify(customResourceFacade, times(2)).updateResource(any()); } + @Test + void reSchedulesFromErrorHandler() { + var delay = 1000L; + testCustomResource.addFinalizer(DEFAULT_FINALIZER); + reconciler.reconcile = (r, c) -> { + throw new IllegalStateException("Error Status Test"); + }; + reconciler.errorHandler = + (r, ri, e) -> ErrorStatusUpdateControl.noStatusUpdate() + .rescheduleAfter(delay); + + var res = reconciliationDispatcher.handleExecution( + new ExecutionScope(null).setResource(testCustomResource)); + + assertThat(res.getReScheduleDelay()).contains(delay); + assertThat(res.getRuntimeException()).isEmpty(); + } + private ObservedGenCustomResource createObservedGenCustomResource() { ObservedGenCustomResource observedGenCustomResource = new ObservedGenCustomResource(); observedGenCustomResource.setMetadata(new ObjectMeta());