@@ -121,10 +121,10 @@ public void handleEvent(Event event) {
121121 }
122122
123123 private void handleMarkedEventForResource (ResourceID resourceID ) {
124- if (!eventMarker .deleteEventPresent (resourceID )) {
125- submitReconciliationExecution (resourceID );
126- } else {
124+ if (eventMarker .deleteEventPresent (resourceID )) {
127125 cleanupForDeletedEvent (resourceID );
126+ } else if (!eventMarker .processedMarkForDeletionPresent (resourceID )) {
127+ submitReconciliationExecution (resourceID );
128128 }
129129 }
130130
@@ -157,18 +157,50 @@ private void submitReconciliationExecution(ResourceID resourceID) {
157157 }
158158
159159 private void handleEventMarking (Event event ) {
160- if (event instanceof ResourceEvent
161- && ((ResourceEvent ) event ).getAction () == ResourceAction .DELETED ) {
162- log .debug ("Marking delete event received for: {}" , event .getRelatedCustomResourceID ());
163- eventMarker .markDeleteEventReceived (event );
164- } else if (!eventMarker .deleteEventPresent (event .getRelatedCustomResourceID ())) {
165- log .debug ("Marking event received for: {}" , event .getRelatedCustomResourceID ());
166- eventMarker .markEventReceived (event );
160+ final var relatedCustomResourceID = event .getRelatedCustomResourceID ();
161+ if (event instanceof ResourceEvent ) {
162+ var resourceEvent = (ResourceEvent ) event ;
163+ if (resourceEvent .getAction () == ResourceAction .DELETED ) {
164+ log .debug ("Marking delete event received for: {}" , relatedCustomResourceID );
165+ eventMarker .markDeleteEventReceived (event );
166+ } else {
167+ if (eventMarker .processedMarkForDeletionPresent (relatedCustomResourceID )
168+ && isResourceMarkedForDeletion (resourceEvent )) {
169+ log .debug (
170+ "Skipping mark of event received, since already processed mark for deletion and resource marked for deletion: {}" ,
171+ relatedCustomResourceID );
172+ return ;
173+ }
174+ // Normally when eventMarker is in state PROCESSED_MARK_FOR_DELETION it is expected to
175+ // receive a Delete event or an event where resource is marked for deletion. In a rare edge
176+ // case however it can happen that the finalizer related to the current controller is
177+ // removed, but also the informers websocket is disconnected and later reconnected. So
178+ // meanwhile the resource could be deleted and recreated. In this case we just mark a new
179+ // event as below.
180+ markEventReceived (event );
181+ }
182+ } else if (!eventMarker .deleteEventPresent (relatedCustomResourceID ) ||
183+ !eventMarker .processedMarkForDeletionPresent (relatedCustomResourceID )) {
184+ markEventReceived (event );
185+ } else if (log .isDebugEnabled ()) {
186+ log .debug (
187+ "Skipped marking event as received. Delete event present: {}, processed mark for deletion: {}" ,
188+ eventMarker .deleteEventPresent (relatedCustomResourceID ),
189+ eventMarker .processedMarkForDeletionPresent (relatedCustomResourceID ));
167190 }
168191 }
169192
170- private RetryInfo retryInfo (ResourceID customResourceUid ) {
171- return retryState .get (customResourceUid );
193+ private void markEventReceived (Event event ) {
194+ log .debug ("Marking event received for: {}" , event .getRelatedCustomResourceID ());
195+ eventMarker .markEventReceived (event );
196+ }
197+
198+ private boolean isResourceMarkedForDeletion (ResourceEvent resourceEvent ) {
199+ return resourceEvent .getResource ().map (HasMetadata ::isMarkedForDeletion ).orElse (false );
200+ }
201+
202+ private RetryInfo retryInfo (ResourceID resourceID ) {
203+ return retryState .get (resourceID );
172204 }
173205
174206 void eventProcessingFinished (
@@ -199,6 +231,8 @@ void eventProcessingFinished(
199231 metrics .finishedReconciliation (resourceID );
200232 if (eventMarker .deleteEventPresent (resourceID )) {
201233 cleanupForDeletedEvent (executionScope .getResourceID ());
234+ } else if (postExecutionControl .isFinalizerRemoved ()) {
235+ eventMarker .markProcessedMarkForDeletion (resourceID );
202236 } else {
203237 postExecutionControl
204238 .getUpdatedCustomResource ()
@@ -247,13 +281,13 @@ TimerEventSource<R> retryEventSource() {
247281 private void handleRetryOnException (
248282 ExecutionScope <R > executionScope , Exception exception ) {
249283 RetryExecution execution = getOrInitRetryExecution (executionScope );
250- var customResourceID = executionScope .getResourceID ();
251- boolean eventPresent = eventMarker .eventPresent (customResourceID );
252- eventMarker .markEventReceived (customResourceID );
284+ var resourceID = executionScope .getResourceID ();
285+ boolean eventPresent = eventMarker .eventPresent (resourceID );
286+ eventMarker .markEventReceived (resourceID );
253287
254288 if (eventPresent ) {
255- log .debug ("New events exists for for resource id: {}" , customResourceID );
256- submitReconciliationExecution (customResourceID );
289+ log .debug ("New events exists for for resource id: {}" , resourceID );
290+ submitReconciliationExecution (resourceID );
257291 return ;
258292 }
259293 Optional <Long > nextDelay = execution .nextDelay ();
@@ -263,8 +297,8 @@ private void handleRetryOnException(
263297 log .debug (
264298 "Scheduling timer event for retry with delay:{} for resource: {}" ,
265299 delay ,
266- customResourceID );
267- metrics .failedReconciliation (customResourceID , exception );
300+ resourceID );
301+ metrics .failedReconciliation (resourceID , exception );
268302 retryEventSource ().scheduleOnce (executionScope .getResource (), delay );
269303 },
270304 () -> log .error ("Exhausted retries for {}" , executionScope ));
@@ -288,22 +322,22 @@ private RetryExecution getOrInitRetryExecution(ExecutionScope<R> executionScope)
288322 return retryExecution ;
289323 }
290324
291- private void cleanupForDeletedEvent (ResourceID customResourceUid ) {
292- log .debug ("Cleaning up for delete event for: {}" , customResourceUid );
293- eventMarker .cleanup (customResourceUid );
294- metrics .cleanupDoneFor (customResourceUid );
325+ private void cleanupForDeletedEvent (ResourceID resourceID ) {
326+ log .debug ("Cleaning up for delete event for: {}" , resourceID );
327+ eventMarker .cleanup (resourceID );
328+ metrics .cleanupDoneFor (resourceID );
295329 }
296330
297- private boolean isControllerUnderExecution (ResourceID customResourceUid ) {
298- return underProcessing .contains (customResourceUid );
331+ private boolean isControllerUnderExecution (ResourceID resourceID ) {
332+ return underProcessing .contains (resourceID );
299333 }
300334
301- private void setUnderExecutionProcessing (ResourceID customResourceUid ) {
302- underProcessing .add (customResourceUid );
335+ private void setUnderExecutionProcessing (ResourceID resourceID ) {
336+ underProcessing .add (resourceID );
303337 }
304338
305- private void unsetUnderExecution (ResourceID customResourceUid ) {
306- underProcessing .remove (customResourceUid );
339+ private void unsetUnderExecution (ResourceID resourceID ) {
340+ underProcessing .remove (resourceID );
307341 }
308342
309343 private boolean isRetryConfigured () {
0 commit comments