Skip to content

Commit cb62f6c

Browse files
csvirimetacosm
andcommitted
Removing events from context (#596)
* fix: WIP * fix: Addressing Custom Resource by Name and Namespace refactor + Informer Cache WIP * fix: Build is fixed, (test failing) * fix: Test fixes * fix: minor update * fix: EventSourceManager small fix * fix: Unit tests fixed * fix: DefaultEventHandler init from EventSourceManager * fix: custom resource selector test improvement * fix: wip test imrpovements * fix: test improvements * fix: further improvements * fix: build * feature: add mvn jar to gitignore * Exposing CustomResourceEventSource and informers * fix: cleanup * fix: remove caching optimization since it not possible anymore with informer * fix: formatting * refactor: make name/namespace final * feature: Simple label selector support * fix: formatting * fix: code inspection reports * fix: merge from v2 * fix: removed most deprecated apis * wip: started to remove events from variouse layers * fix: progress with implementation and tests * fix: Updated informer mapping to CustomResourceID * fix: imports * fix: decorational changes * fix: event marker unit test * Default Event Handler Unit tests * fix: fixes after merge * fix: changes from code review * fix: method naming * Update operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventMarker.java Co-authored-by: Chris Laprun <[email protected]> * Update operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventMarker.java Co-authored-by: Chris Laprun <[email protected]> * fix: comment * fix: fixes from merge * fix: remove not used method * fix: formatting Co-authored-by: Chris Laprun <[email protected]> Co-authored-by: Chris Laprun <[email protected]>
1 parent 1c9f257 commit cb62f6c

22 files changed

+278
-363
lines changed

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/Context.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
import java.util.Optional;
44

55
import io.fabric8.kubernetes.client.CustomResource;
6-
import io.javaoperatorsdk.operator.processing.event.EventList;
76

87
public interface Context<T extends CustomResource> {
98

10-
EventList getEvents();
11-
129
Optional<RetryInfo> getRetryInfo();
10+
1311
}

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/DefaultContext.java

+1-9
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,13 @@
33
import java.util.Optional;
44

55
import io.fabric8.kubernetes.client.CustomResource;
6-
import io.javaoperatorsdk.operator.processing.event.EventList;
76

87
public class DefaultContext<T extends CustomResource> implements Context<T> {
98

109
private final RetryInfo retryInfo;
11-
private final EventList events;
1210

13-
public DefaultContext(EventList events, RetryInfo retryInfo) {
11+
public DefaultContext(RetryInfo retryInfo) {
1412
this.retryInfo = retryInfo;
15-
this.events = events;
16-
}
17-
18-
@Override
19-
public EventList getEvents() {
20-
return events;
2113
}
2214

2315
@Override

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ResourceController.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
public interface ResourceController<R extends CustomResource> {
77

88
/**
9+
* Note that this method is used in combination of finalizers. If automatic finalizer handling is
10+
* turned off for the controller, this method is not called.
11+
*
912
* The implementation should delete the associated component(s). Note that this is method is
1013
* called when an object is marked for deletion. After it's executed the custom resource finalizer
1114
* is automatically removed by the framework; unless the return value is
1215
* {@link DeleteControl#noFinalizerRemoval()}, which indicates that the controller has determined
13-
* that the resource should not be deleted yet, in which case it is up to the controller to
14-
* restore the resource's status so that it's not marked for deletion anymore.
16+
* that the resource should not be deleted yet. This is usually a corner case, when a cleanup is
17+
* tried again eventually.
1518
*
1619
* <p>
1720
* It's important that this method be idempotent, as it could be called several times, depending

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/DefaultEventHandler.java

+68-46
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
import io.javaoperatorsdk.operator.processing.event.DefaultEventSourceManager;
2121
import io.javaoperatorsdk.operator.processing.event.Event;
2222
import io.javaoperatorsdk.operator.processing.event.EventHandler;
23+
import io.javaoperatorsdk.operator.processing.event.internal.CustomResourceEvent;
24+
import io.javaoperatorsdk.operator.processing.event.internal.ResourceAction;
2325
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
2426
import io.javaoperatorsdk.operator.processing.retry.Retry;
2527
import io.javaoperatorsdk.operator.processing.retry.RetryExecution;
2628

27-
import static io.javaoperatorsdk.operator.EventListUtils.containsCustomResourceDeletedEvent;
2829
import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.getName;
2930

3031
/**
@@ -38,7 +39,6 @@ public class DefaultEventHandler<R extends CustomResource<?, ?>> implements Even
3839
@Deprecated
3940
private static EventMonitor monitor = EventMonitor.NOOP;
4041

41-
private final EventBuffer eventBuffer;
4242
private final Set<CustomResourceID> underProcessing = new HashSet<>();
4343
private final EventDispatcher<R> eventDispatcher;
4444
private final Retry retry;
@@ -50,6 +50,7 @@ public class DefaultEventHandler<R extends CustomResource<?, ?>> implements Even
5050
private volatile boolean running;
5151
private final ResourceCache<R> resourceCache;
5252
private DefaultEventSourceManager<R> eventSourceManager;
53+
private final EventMarker eventMarker;
5354

5455
public DefaultEventHandler(ConfiguredController<R> controller, ResourceCache<R> resourceCache) {
5556
this(
@@ -58,18 +59,20 @@ public DefaultEventHandler(ConfiguredController<R> controller, ResourceCache<R>
5859
controller.getConfiguration().getName(),
5960
new EventDispatcher<>(controller),
6061
GenericRetry.fromConfiguration(controller.getConfiguration().getRetryConfiguration()),
61-
controller.getConfiguration().getConfigurationService().getMetrics().getEventMonitor());
62+
controller.getConfiguration().getConfigurationService().getMetrics().getEventMonitor(),
63+
new EventMarker());
6264
}
6365

6466
DefaultEventHandler(EventDispatcher<R> eventDispatcher, ResourceCache<R> resourceCache,
6567
String relatedControllerName,
66-
Retry retry) {
67-
this(resourceCache, null, relatedControllerName, eventDispatcher, retry, null);
68+
Retry retry, EventMarker eventMarker) {
69+
this(resourceCache, null, relatedControllerName, eventDispatcher, retry, null, eventMarker);
6870
}
6971

7072
private DefaultEventHandler(ResourceCache<R> resourceCache, ExecutorService executor,
7173
String relatedControllerName,
72-
EventDispatcher<R> eventDispatcher, Retry retry, EventMonitor monitor) {
74+
EventDispatcher<R> eventDispatcher, Retry retry, EventMonitor monitor,
75+
EventMarker eventMarker) {
7376
this.running = true;
7477
this.executor =
7578
executor == null
@@ -79,9 +82,9 @@ private DefaultEventHandler(ResourceCache<R> resourceCache, ExecutorService exec
7982
this.controllerName = relatedControllerName;
8083
this.eventDispatcher = eventDispatcher;
8184
this.retry = retry;
82-
eventBuffer = new EventBuffer();
8385
this.resourceCache = resourceCache;
8486
this.eventMonitor = monitor != null ? monitor : EventMonitor.NOOP;
87+
this.eventMarker = eventMarker;
8588
}
8689

8790
public void setEventSourceManager(DefaultEventSourceManager<R> eventSourceManager) {
@@ -113,71 +116,75 @@ private EventMonitor monitor() {
113116

114117
@Override
115118
public void handleEvent(Event event) {
119+
lock.lock();
116120
try {
117-
lock.lock();
118121
log.debug("Received event: {}", event);
119122
if (!this.running) {
120123
log.debug("Skipping event: {} because the event handler is shutting down", event);
121124
return;
122125
}
123126
final var monitor = monitor();
124-
eventBuffer.addEvent(event.getRelatedCustomResourceID(), event);
125127
monitor.processedEvent(event.getRelatedCustomResourceID(), event);
126-
executeBufferedEvents(event.getRelatedCustomResourceID());
127-
} finally {
128-
lock.unlock();
129-
}
130-
}
131128

132-
@Override
133-
public void close() {
134-
try {
135-
lock.lock();
136-
this.running = false;
129+
handleEventMarking(event);
130+
if (!eventMarker.deleteEventPresent(event.getRelatedCustomResourceID())) {
131+
submitReconciliationExecution(event.getRelatedCustomResourceID());
132+
} else {
133+
cleanupForDeletedEvent(event.getRelatedCustomResourceID());
134+
}
137135
} finally {
138136
lock.unlock();
139137
}
140138
}
141139

142-
private boolean executeBufferedEvents(CustomResourceID customResourceUid) {
143-
boolean newEventForResourceId = eventBuffer.containsEvents(customResourceUid);
140+
private boolean submitReconciliationExecution(CustomResourceID customResourceUid) {
144141
boolean controllerUnderExecution = isControllerUnderExecution(customResourceUid);
145142
Optional<R> latestCustomResource =
146143
resourceCache.getCustomResource(customResourceUid);
147144

148-
if (!controllerUnderExecution && newEventForResourceId && latestCustomResource.isPresent()) {
145+
if (!controllerUnderExecution
146+
&& latestCustomResource.isPresent()) {
149147
setUnderExecutionProcessing(customResourceUid);
150148
ExecutionScope executionScope =
151149
new ExecutionScope(
152-
eventBuffer.getAndRemoveEventsForExecution(customResourceUid),
153150
latestCustomResource.get(),
154151
retryInfo(customResourceUid));
152+
eventMarker.unMarkEventReceived(customResourceUid);
155153
log.debug("Executing events for custom resource. Scope: {}", executionScope);
156154
executor.execute(new ControllerExecution(executionScope));
157155
return true;
158156
} else {
159157
log.debug(
160-
"Skipping executing controller for resource id: {}. Events in queue: {}."
158+
"Skipping executing controller for resource id: {}."
161159
+ " Controller in execution: {}. Latest CustomResource present: {}",
162160
customResourceUid,
163-
newEventForResourceId,
164161
controllerUnderExecution,
165162
latestCustomResource.isPresent());
166163
if (latestCustomResource.isEmpty()) {
167-
log.warn("no custom resource found in cache for CustomResourceID: {}", customResourceUid);
164+
log.warn("no custom resource found in cache for CustomResourceID: {}",
165+
customResourceUid);
168166
}
169167
return false;
170168
}
171169
}
172170

171+
private void handleEventMarking(Event event) {
172+
if (event instanceof CustomResourceEvent &&
173+
((CustomResourceEvent) event).getAction() == ResourceAction.DELETED) {
174+
eventMarker.markDeleteEventReceived(event);
175+
} else if (!eventMarker.deleteEventPresent(event.getRelatedCustomResourceID())) {
176+
eventMarker.markEventReceived(event);
177+
}
178+
}
179+
173180
private RetryInfo retryInfo(CustomResourceID customResourceUid) {
174181
return retryState.get(customResourceUid);
175182
}
176183

177184
void eventProcessingFinished(
178185
ExecutionScope<R> executionScope, PostExecutionControl<R> postExecutionControl) {
186+
lock.lock();
179187
try {
180-
lock.lock();
181188
if (!running) {
182189
return;
183190
}
@@ -188,23 +195,29 @@ void eventProcessingFinished(
188195
postExecutionControl);
189196
unsetUnderExecution(executionScope.getCustomResourceID());
190197

191-
if (retry != null && postExecutionControl.exceptionDuringExecution()) {
198+
// If a delete event present at this phase, it was received during reconciliation.
199+
// So we either removed the finalizer during reconciliation or we don't use finalizers.
200+
// Either way we don't want to retry.
201+
if (retry != null && postExecutionControl.exceptionDuringExecution() &&
202+
!eventMarker.deleteEventPresent(executionScope.getCustomResourceID())) {
192203
handleRetryOnException(executionScope);
193-
final var monitor = monitor();
194-
executionScope.getEvents()
195-
.forEach(e -> monitor.failedEvent(executionScope.getCustomResourceID(), e));
204+
// todo revisit monitoring since events are not present anymore
205+
// final var monitor = monitor(); executionScope.getEvents().forEach(e ->
206+
// monitor.failedEvent(executionScope.getCustomResourceID(), e));
196207
return;
197208
}
198209

199210
if (retry != null) {
200-
markSuccessfulExecutionRegardingRetry(executionScope);
211+
handleSuccessfulExecutionRegardingRetry(executionScope);
201212
}
202-
if (containsCustomResourceDeletedEvent(executionScope.getEvents())) {
203-
cleanupAfterDeletedEvent(executionScope.getCustomResourceID());
213+
if (eventMarker.deleteEventPresent(executionScope.getCustomResourceID())) {
214+
cleanupForDeletedEvent(executionScope.getCustomResourceID());
204215
} else {
205-
var executed = executeBufferedEvents(executionScope.getCustomResourceID());
206-
if (!executed) {
207-
reScheduleExecutionIfInstructed(postExecutionControl, executionScope.getCustomResource());
216+
if (eventMarker.eventPresent(executionScope.getCustomResourceID())) {
217+
submitReconciliationExecution(executionScope.getCustomResourceID());
218+
} else {
219+
reScheduleExecutionIfInstructed(postExecutionControl,
220+
executionScope.getCustomResource());
208221
}
209222
}
210223
} finally {
@@ -227,13 +240,13 @@ private void reScheduleExecutionIfInstructed(PostExecutionControl<R> postExecuti
227240
private void handleRetryOnException(ExecutionScope<R> executionScope) {
228241
RetryExecution execution = getOrInitRetryExecution(executionScope);
229242
var customResourceID = executionScope.getCustomResourceID();
230-
boolean newEventsExists = eventBuffer
231-
.newEventsExists(customResourceID);
232-
eventBuffer.putBackEvents(customResourceID, executionScope.getEvents());
243+
boolean eventPresent = eventMarker.eventPresent(customResourceID);
244+
eventMarker.markEventReceived(customResourceID);
233245

234-
if (newEventsExists) {
235-
log.debug("New events exists for for resource id: {}", customResourceID);
236-
executeBufferedEvents(customResourceID);
246+
if (eventPresent) {
247+
log.debug("New events exists for for resource id: {}",
248+
customResourceID);
249+
submitReconciliationExecution(customResourceID);
237250
return;
238251
}
239252
Optional<Long> nextDelay = execution.nextDelay();
@@ -251,7 +264,7 @@ private void handleRetryOnException(ExecutionScope<R> executionScope) {
251264
() -> log.error("Exhausted retries for {}", executionScope));
252265
}
253266

254-
private void markSuccessfulExecutionRegardingRetry(ExecutionScope<R> executionScope) {
267+
private void handleSuccessfulExecutionRegardingRetry(ExecutionScope<R> executionScope) {
255268
log.debug(
256269
"Marking successful execution for resource: {}",
257270
getName(executionScope.getCustomResource()));
@@ -270,9 +283,9 @@ private RetryExecution getOrInitRetryExecution(ExecutionScope<R> executionScope)
270283
return retryExecution;
271284
}
272285

273-
private void cleanupAfterDeletedEvent(CustomResourceID customResourceUid) {
286+
private void cleanupForDeletedEvent(CustomResourceID customResourceUid) {
274287
eventSourceManager.cleanupForCustomResource(customResourceUid);
275-
eventBuffer.cleanup(customResourceUid);
288+
eventMarker.cleanup(customResourceUid);
276289
}
277290

278291
private boolean isControllerUnderExecution(CustomResourceID customResourceUid) {
@@ -287,6 +300,15 @@ private void unsetUnderExecution(CustomResourceID customResourceUid) {
287300
underProcessing.remove(customResourceUid);
288301
}
289302

303+
@Override
304+
public void close() {
305+
lock.lock();
306+
try {
307+
this.running = false;
308+
} finally {
309+
lock.unlock();
310+
}
311+
}
290312

291313
private class ControllerExecution implements Runnable {
292314
private final ExecutionScope<R> executionScope;

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventBuffer.java

-45
This file was deleted.

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventDispatcher.java

+2-13
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
import io.fabric8.kubernetes.client.dsl.Resource;
1111
import io.javaoperatorsdk.operator.api.*;
1212
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
13-
import io.javaoperatorsdk.operator.processing.event.EventList;
1413

15-
import static io.javaoperatorsdk.operator.EventListUtils.containsCustomResourceDeletedEvent;
1614
import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.getName;
1715
import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.getUID;
1816
import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.getVersion;
@@ -55,15 +53,7 @@ public PostExecutionControl<R> handleExecution(ExecutionScope<R> executionScope)
5553

5654
private PostExecutionControl<R> handleDispatch(ExecutionScope<R> executionScope) {
5755
R resource = executionScope.getCustomResource();
58-
log.debug("Handling events: {} for resource {}", executionScope.getEvents(), getName(resource));
59-
60-
if (containsCustomResourceDeletedEvent(executionScope.getEvents())) {
61-
log.debug(
62-
"Skipping dispatch processing because of a Delete event: {} with version: {}",
63-
getName(resource),
64-
getVersion(resource));
65-
return PostExecutionControl.defaultDispatch();
66-
}
56+
log.debug("Handling dispatch for resource {}", getName(resource));
6757

6858
final var markedForDeletion = resource.isMarkedForDeletion();
6959
if (markedForDeletion && shouldNotDispatchToDelete(resource)) {
@@ -75,8 +65,7 @@ private PostExecutionControl<R> handleDispatch(ExecutionScope<R> executionScope)
7565
}
7666

7767
Context<R> context =
78-
new DefaultContext<>(
79-
new EventList(executionScope.getEvents()), executionScope.getRetryInfo());
68+
new DefaultContext<>(executionScope.getRetryInfo());
8069
if (markedForDeletion) {
8170
return handleDelete(resource, context);
8271
} else {

0 commit comments

Comments
 (0)