Skip to content

Commit 99626cb

Browse files
committed
refactor!: replace Closeable by explicit Stoppable interface
This ensures that stoppable classes can also be started if needed. Fixes #629
1 parent c5c83af commit 99626cb

File tree

13 files changed

+72
-65
lines changed

13 files changed

+72
-65
lines changed

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

+15-16
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package io.javaoperatorsdk.operator;
22

3-
import java.io.Closeable;
4-
import java.io.IOException;
53
import java.net.ConnectException;
64
import java.util.ArrayList;
75
import java.util.HashMap;
@@ -16,13 +14,14 @@
1614
import io.fabric8.kubernetes.client.KubernetesClient;
1715
import io.fabric8.kubernetes.client.Version;
1816
import io.javaoperatorsdk.operator.api.ResourceController;
17+
import io.javaoperatorsdk.operator.api.Stoppable;
1918
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
2019
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
2120
import io.javaoperatorsdk.operator.api.config.ExecutorServiceManager;
2221
import io.javaoperatorsdk.operator.processing.ConfiguredController;
2322

2423
@SuppressWarnings("rawtypes")
25-
public class Operator implements AutoCloseable {
24+
public class Operator implements AutoCloseable, Stoppable {
2625
private static final Logger log = LoggerFactory.getLogger(Operator.class);
2726
private final KubernetesClient kubernetesClient;
2827
private final ConfigurationService configurationService;
@@ -90,18 +89,23 @@ public void start() {
9089
controllers.start();
9190
}
9291

93-
/** Stop the operator. */
9492
@Override
95-
public void close() {
93+
public void stop() throws OperatorException {
9694
log.info(
9795
"Operator SDK {} is shutting down...", configurationService.getVersion().getSdkVersion());
9896

99-
controllers.close();
97+
controllers.stop();
10098

101-
ExecutorServiceManager.close();
99+
ExecutorServiceManager.stop();
102100
kubernetesClient.close();
103101
}
104102

103+
/** Stop the operator. */
104+
@Override
105+
public void close() {
106+
stop();
107+
}
108+
105109
/**
106110
* Add a registration requests for the specified controller with this operator. The effective
107111
* registration of the controller is delayed till the operator is started.
@@ -159,7 +163,7 @@ public <R extends CustomResource> void register(
159163
}
160164
}
161165

162-
private static class ControllerManager implements Closeable {
166+
private static class ControllerManager implements Stoppable {
163167
private final Map<String, ConfiguredController> controllers = new HashMap<>();
164168
private boolean started = false;
165169

@@ -178,19 +182,14 @@ public synchronized void start() {
178182
started = true;
179183
}
180184

181-
@Override
182-
public synchronized void close() {
185+
public synchronized void stop() {
183186
if (!started) {
184187
return;
185188
}
186189

187190
this.controllers.values().parallelStream().forEach(closeable -> {
188-
try {
189-
log.debug("closing {}", closeable);
190-
closeable.close();
191-
} catch (IOException e) {
192-
log.warn("Error closing {}", closeable, e);
193-
}
191+
log.debug("closing {}", closeable);
192+
closeable.stop();
194193
});
195194

196195
started = false;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.javaoperatorsdk.operator.api;
2+
3+
import io.javaoperatorsdk.operator.OperatorException;
4+
5+
public interface Stoppable {
6+
void start() throws OperatorException;
7+
8+
void stop() throws OperatorException;
9+
}

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ public static void init(ConfigurationService configuration) {
3434
}
3535
}
3636

37-
public static void close() {
37+
public static void stop() {
3838
if (instance != null) {
39-
instance.stop();
39+
instance.doStop();
4040
}
4141
// make sure that we remove the singleton so that the thread pool is re-created on next call to
4242
// start
@@ -55,7 +55,7 @@ public ExecutorService executorService() {
5555
return executor;
5656
}
5757

58-
private void stop() {
58+
private void doStop() {
5959
try {
6060
log.debug("Closing executor");
6161
executor.shutdown();

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

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package io.javaoperatorsdk.operator.processing;
22

3-
import java.io.Closeable;
4-
import java.io.IOException;
53
import java.util.Objects;
64

75
import io.fabric8.kubernetes.api.model.KubernetesResourceList;
@@ -20,7 +18,7 @@
2018
import io.javaoperatorsdk.operator.processing.event.EventSourceManager;
2119

2220
public class ConfiguredController<R extends CustomResource<?, ?>> implements ResourceController<R>,
23-
Closeable, EventSourceInitializer {
21+
Stoppable, EventSourceInitializer {
2422
private final ResourceController<R> controller;
2523
private final ControllerConfiguration<R> configuration;
2624
private final KubernetesClient kubernetesClient;
@@ -214,10 +212,9 @@ public EventSourceManager getEventSourceManager() {
214212
return eventSourceManager;
215213
}
216214

217-
@Override
218-
public void close() throws IOException {
215+
public void stop() {
219216
if (eventSourceManager != null) {
220-
eventSourceManager.close();
217+
eventSourceManager.stop();
221218
}
222219
}
223220
}

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

+18-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.javaoperatorsdk.operator.processing;
22

3-
import java.io.Closeable;
43
import java.util.HashMap;
54
import java.util.HashSet;
65
import java.util.Map;
@@ -14,11 +13,16 @@
1413
import org.slf4j.LoggerFactory;
1514

1615
import io.fabric8.kubernetes.client.CustomResource;
16+
import io.javaoperatorsdk.operator.OperatorException;
1717
import io.javaoperatorsdk.operator.api.RetryInfo;
18+
import io.javaoperatorsdk.operator.api.Stoppable;
1819
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
1920
import io.javaoperatorsdk.operator.api.config.ExecutorServiceManager;
2021
import io.javaoperatorsdk.operator.api.monitoring.Metrics;
21-
import io.javaoperatorsdk.operator.processing.event.*;
22+
import io.javaoperatorsdk.operator.processing.event.CustomResourceID;
23+
import io.javaoperatorsdk.operator.processing.event.DefaultEventSourceManager;
24+
import io.javaoperatorsdk.operator.processing.event.Event;
25+
import io.javaoperatorsdk.operator.processing.event.EventHandler;
2226
import io.javaoperatorsdk.operator.processing.event.internal.CustomResourceEvent;
2327
import io.javaoperatorsdk.operator.processing.event.internal.ResourceAction;
2428
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
@@ -33,7 +37,7 @@
3337
* UID, while buffering events which are received during an execution.
3438
*/
3539
public class DefaultEventHandler<R extends CustomResource<?, ?>>
36-
implements EventHandler, Closeable {
40+
implements EventHandler, Stoppable {
3741

3842
private static final Logger log = LoggerFactory.getLogger(DefaultEventHandler.class);
3943

@@ -315,7 +319,7 @@ private boolean isRetryConfigured() {
315319
}
316320

317321
@Override
318-
public void close() {
322+
public void stop() {
319323
lock.lock();
320324
try {
321325
this.running = false;
@@ -324,6 +328,16 @@ public void close() {
324328
}
325329
}
326330

331+
@Override
332+
public void start() throws OperatorException {
333+
lock.lock();
334+
try {
335+
this.running = true;
336+
} finally {
337+
lock.unlock();
338+
}
339+
}
340+
327341
private class ControllerExecution implements Runnable {
328342
private final ExecutionScope<R> executionScope;
329343

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

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.javaoperatorsdk.operator.processing.event;
22

3-
import java.io.Closeable;
43
import java.util.*;
54
import java.util.concurrent.locks.ReentrantLock;
65

@@ -10,13 +9,14 @@
109
import io.fabric8.kubernetes.client.CustomResource;
1110
import io.javaoperatorsdk.operator.MissingCRDException;
1211
import io.javaoperatorsdk.operator.OperatorException;
12+
import io.javaoperatorsdk.operator.api.Stoppable;
1313
import io.javaoperatorsdk.operator.processing.ConfiguredController;
1414
import io.javaoperatorsdk.operator.processing.DefaultEventHandler;
1515
import io.javaoperatorsdk.operator.processing.event.internal.CustomResourceEventSource;
1616
import io.javaoperatorsdk.operator.processing.event.internal.TimerEventSource;
1717

1818
public class DefaultEventSourceManager<R extends CustomResource<?, ?>>
19-
implements EventSourceManager<R>, Closeable {
19+
implements EventSourceManager<R>, Stoppable {
2020

2121
private static final Logger log = LoggerFactory.getLogger(DefaultEventSourceManager.class);
2222

@@ -45,18 +45,23 @@ private void init(DefaultEventHandler<R> defaultEventHandler) {
4545
}
4646

4747
@Override
48-
public void close() {
48+
public void start() throws OperatorException {
49+
defaultEventHandler.start();
50+
}
51+
52+
@Override
53+
public void stop() {
4954
lock.lock();
5055
try {
5156
try {
52-
defaultEventHandler.close();
57+
defaultEventHandler.stop();
5358
} catch (Exception e) {
5459
log.warn("Error closing event handler", e);
5560
}
5661
log.debug("Closing event sources.");
5762
for (var eventSource : eventSources) {
5863
try {
59-
eventSource.close();
64+
eventSource.stop();
6065
} catch (Exception e) {
6166
log.warn("Error closing {} -> {}", eventSource, e);
6267
}

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

+2-16
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,8 @@
11
package io.javaoperatorsdk.operator.processing.event;
22

3-
import java.io.Closeable;
4-
import java.io.IOException;
3+
import io.javaoperatorsdk.operator.api.Stoppable;
54

6-
public interface EventSource extends Closeable {
7-
8-
/**
9-
* This method is invoked when this {@link EventSource} instance is properly registered to a
10-
* {@link EventSourceManager}.
11-
*/
12-
default void start() {}
13-
14-
/**
15-
* This method is invoked when this {@link EventSource} instance is de-registered from a
16-
* {@link EventSourceManager}.
17-
*/
18-
@Override
19-
default void close() throws IOException {}
5+
public interface EventSource extends Stoppable {
206

217
void setEventHandler(EventHandler eventHandler);
228

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/internal/CustomResourceEventSource.java

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.javaoperatorsdk.operator.processing.event.internal;
22

3-
import java.io.IOException;
43
import java.util.*;
54
import java.util.concurrent.ConcurrentHashMap;
65

@@ -105,13 +104,13 @@ public void start() {
105104
}
106105

107106
@Override
108-
public void close() throws IOException {
107+
public void stop() {
109108
for (SharedIndexInformer<T> informer : sharedIndexInformers.values()) {
110109
try {
111-
log.info("Closing informer {} -> {}", controller, informer);
112-
informer.close();
110+
log.info("Stopping informer {} -> {}", controller, informer);
111+
informer.stop();
113112
} catch (Exception e) {
114-
log.warn("Error closing informer {} -> {}", controller, informer, e);
113+
log.warn("Error stopping informer {} -> {}", controller, informer, e);
115114
}
116115
}
117116
}

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/internal/InformerEventSource.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.javaoperatorsdk.operator.processing.event.internal;
22

3-
import java.io.IOException;
43
import java.util.Objects;
54
import java.util.Set;
65
import java.util.function.Function;
@@ -93,7 +92,7 @@ public void start() {
9392
}
9493

9594
@Override
96-
public void close() throws IOException {
95+
public void stop() {
9796
sharedInformer.close();
9897
}
9998

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/internal/TimerEventSource.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.javaoperatorsdk.operator.processing.event.internal;
22

3-
import java.io.IOException;
43
import java.util.Map;
54
import java.util.Timer;
65
import java.util.TimerTask;
@@ -76,7 +75,7 @@ public void start() {
7675
}
7776

7877
@Override
79-
public void close() throws IOException {
78+
public void stop() {
8079
running.set(false);
8180
onceTasks.keySet().forEach(this::cancelOnceSchedule);
8281
timerTasks.keySet().forEach(this::cancelSchedule);

Diff for: operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/DefaultEventHandlerTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ public void reScheduleOnlyIfNotExecutedBufferedEvents() {
194194

195195
@Test
196196
public void doNotFireEventsIfClosing() {
197-
defaultEventHandler.close();
197+
defaultEventHandler.stop();
198198
defaultEventHandler.handleEvent(prepareCREvent());
199199

200200
verify(eventDispatcherMock, timeout(50).times(0)).handleExecution(any());

Diff for: operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/DefaultEventSourceManagerTest.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ public void closeShouldCascadeToEventSources() throws IOException {
4242
defaultEventSourceManager.registerEventSource(eventSource);
4343
defaultEventSourceManager.registerEventSource(eventSource2);
4444

45-
defaultEventSourceManager.close();
45+
defaultEventSourceManager.stop();
4646

47-
verify(eventSource, times(1)).close();
48-
verify(eventSource2, times(1)).close();
47+
verify(eventSource, times(1)).stop();
48+
verify(eventSource2, times(1)).stop();
4949
}
5050

5151
@Test

Diff for: operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/internal/TimerEventSourceTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,15 @@ public void deRegistersOnceEventSources() {
112112
public void eventNotRegisteredIfStopped() throws IOException {
113113
TestCustomResource customResource = TestUtils.testCustomResource();
114114

115-
timerEventSource.close();
115+
timerEventSource.stop();
116116
assertThatExceptionOfType(IllegalStateException.class).isThrownBy(
117117
() -> timerEventSource.scheduleOnce(customResource, PERIOD));
118118
}
119119

120120
@Test
121121
public void eventNotFiredIfStopped() throws IOException {
122122
timerEventSource.scheduleOnce(TestUtils.testCustomResource(), PERIOD);
123-
timerEventSource.close();
123+
timerEventSource.stop();
124124

125125
untilAsserted(() -> assertThat(eventHandlerMock.events).isEmpty());
126126
}

0 commit comments

Comments
 (0)