Skip to content

Commit 96be07e

Browse files
committed
refactor: ReconciliationMaxInterval -> MaxReconciliationInterval
1 parent df44917 commit 96be07e

File tree

12 files changed

+146
-20
lines changed

12 files changed

+146
-20
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import java.util.function.Function;
1414
import java.util.stream.Collectors;
1515

16+
import org.slf4j.Logger;
17+
import org.slf4j.LoggerFactory;
18+
1619
import io.fabric8.kubernetes.api.model.HasMetadata;
1720
import io.javaoperatorsdk.operator.OperatorException;
1821
import io.javaoperatorsdk.operator.ReconcilerUtils;
@@ -30,7 +33,14 @@
3033
import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter;
3134
import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter;
3235
import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilters;
33-
import io.javaoperatorsdk.operator.processing.event.source.filter.*;
36+
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
37+
import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter;
38+
import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter;
39+
import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter;
40+
import io.javaoperatorsdk.operator.processing.event.source.filter.VoidGenericFilter;
41+
import io.javaoperatorsdk.operator.processing.event.source.filter.VoidOnAddFilter;
42+
import io.javaoperatorsdk.operator.processing.event.source.filter.VoidOnDeleteFilter;
43+
import io.javaoperatorsdk.operator.processing.event.source.filter.VoidOnUpdateFilter;
3444
import io.javaoperatorsdk.operator.processing.retry.Retry;
3545

3646
import static io.javaoperatorsdk.operator.api.reconciler.Constants.DEFAULT_NAMESPACES_SET;
@@ -39,6 +49,9 @@
3949
public class AnnotationControllerConfiguration<P extends HasMetadata>
4050
implements io.javaoperatorsdk.operator.api.config.ControllerConfiguration<P> {
4151

52+
private static final Logger log =
53+
LoggerFactory.getLogger(AnnotationControllerConfiguration.class);
54+
4255
protected final Reconciler<P> reconciler;
4356
private final ControllerConfiguration annotation;
4457
private List<DependentResourceSpec> specs;
@@ -136,17 +149,32 @@ public ResourceEventFilter<P> getEventFilter() {
136149

137150
@Override
138151
public Optional<Duration> reconciliationMaxInterval() {
139-
if (annotation.reconciliationMaxInterval() != null) {
140-
if (annotation.reconciliationMaxInterval().interval() <= 0) {
141-
return Optional.empty();
142-
}
143-
return Optional.of(
144-
Duration.of(
145-
annotation.reconciliationMaxInterval().interval(),
146-
annotation.reconciliationMaxInterval().timeUnit().toChronoUnit()));
147-
} else {
148-
return io.javaoperatorsdk.operator.api.config.ControllerConfiguration.super.reconciliationMaxInterval();
152+
return maxReconciliationInterval();
153+
}
154+
155+
@Override
156+
public Optional<Duration> maxReconciliationInterval() {
157+
Duration oldStyle = null;
158+
final var oldConfig = annotation.reconciliationMaxInterval();
159+
if (oldConfig != null && oldConfig.interval() > 0) {
160+
oldStyle = Duration.of(oldConfig.interval(), oldConfig.timeUnit().toChronoUnit());
161+
}
162+
163+
Duration duration = null;
164+
final var newConfig = annotation.maxReconciliationInterval();
165+
if (newConfig != null && newConfig.interval() > 0) {
166+
duration = Duration.of(newConfig.interval(), newConfig.timeUnit().toChronoUnit());
167+
}
168+
169+
if (duration != null && oldStyle != null) {
170+
log.debug(
171+
"Both maxReconciliationInterval ({}) and deprecated reconciliationMaxInterval ({}) are used, keeping the non-deprecated value: {}",
172+
duration, oldStyle, duration);
173+
}
174+
if (duration == null && oldStyle != null) {
175+
return Optional.of(oldStyle);
149176
}
177+
return Optional.ofNullable(duration);
150178
}
151179

152180
@Override

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ default List<DependentResourceSpec> getDependentResources() {
7777
return Collections.emptyList();
7878
}
7979

80+
default Optional<Duration> maxReconciliationInterval() {
81+
return Optional.of(Duration.ofHours(10L));
82+
}
83+
84+
/**
85+
*
86+
* @deprecated use {@link #maxReconciliationInterval()} instead
87+
*/
88+
@Deprecated(forRemoval = true)
8089
default Optional<Duration> reconciliationMaxInterval() {
8190
return Optional.of(Duration.ofHours(10L));
8291
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ private ControllerConfigurationOverrider(ControllerConfiguration<R> original) {
4747
retry = original.getRetry();
4848
labelSelector = original.getLabelSelector();
4949
customResourcePredicate = original.getEventFilter();
50-
reconciliationMaxInterval = original.reconciliationMaxInterval().orElse(null);
50+
reconciliationMaxInterval = original.maxReconciliationInterval().orElse(null);
5151
// make the original specs modifiable
5252
final var dependentResources = original.getDependentResources();
5353
namedDependentResourceSpecs = new LinkedHashMap<>(dependentResources.size());

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public List<DependentResourceSpec> getDependentResources() {
108108
}
109109

110110
@Override
111-
public Optional<Duration> reconciliationMaxInterval() {
111+
public Optional<Duration> maxReconciliationInterval() {
112112
return Optional.ofNullable(reconciliationMaxInterval);
113113
}
114114

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@ public final class Constants {
1616
public static final String NO_VALUE_SET = "";
1717
public static final String WATCH_CURRENT_NAMESPACE = "JOSDK_WATCH_CURRENT";
1818
public static final String WATCH_ALL_NAMESPACES = "JOSDK_ALL_NAMESPACES";
19+
20+
/**
21+
* @deprecated use {@link #NO_MAX_RECONCILIATION_INTERVAL} instead
22+
*/
23+
@Deprecated(forRemoval = true)
1924
public static final long NO_RECONCILIATION_MAX_INTERVAL = -1L;
25+
26+
public static final long NO_MAX_RECONCILIATION_INTERVAL = -1L;
2027
public static final String SAME_AS_CONTROLLER = "JOSDK_SAME_AS_CONTROLLER";
2128

2229
public static final String RESOURCE_GVK_KEY = "josdk.resource.gvk";

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
import io.javaoperatorsdk.operator.processing.event.rate.LinearRateLimiter;
1111
import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter;
1212
import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter;
13-
import io.javaoperatorsdk.operator.processing.event.source.filter.*;
13+
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
14+
import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter;
15+
import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter;
16+
import io.javaoperatorsdk.operator.processing.event.source.filter.VoidGenericFilter;
17+
import io.javaoperatorsdk.operator.processing.event.source.filter.VoidOnAddFilter;
18+
import io.javaoperatorsdk.operator.processing.event.source.filter.VoidOnUpdateFilter;
1419
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
1520
import io.javaoperatorsdk.operator.processing.retry.Retry;
1621

@@ -87,10 +92,21 @@
8792
* to happen before one will be automatically triggered.
8893
*
8994
* @return the maximal interval configuration
95+
* @deprecated use {@link #maxReconciliationInterval()} instead
9096
*/
97+
@Deprecated(forRemoval = true)
9198
ReconciliationMaxInterval reconciliationMaxInterval() default @ReconciliationMaxInterval(
9299
interval = 10);
93100

101+
/**
102+
* Optional configuration of the maximal interval the SDK will wait for a reconciliation request
103+
* to happen before one will be automatically triggered.
104+
*
105+
* @return the maximal reconciliation interval configuration
106+
*/
107+
MaxReconciliationInterval maxReconciliationInterval() default @MaxReconciliationInterval(
108+
interval = 10);
109+
94110

95111
/**
96112
* Optional list of {@link Dependent} configurations which associate a resource type to a
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package io.javaoperatorsdk.operator.api.reconciler;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
import java.util.concurrent.TimeUnit;
8+
9+
@Retention(RetentionPolicy.RUNTIME)
10+
@Target({ElementType.TYPE})
11+
public @interface MaxReconciliationInterval {
12+
13+
/**
14+
* A max delay between two reconciliations. Having this value larger than zero, will ensure that a
15+
* reconciliation is scheduled with a target interval after the last reconciliation. Note that
16+
* this not applies for retries, in case of an exception reconciliation is not scheduled. This is
17+
* not a fixed rate, in other words a new reconciliation is scheduled after each reconciliation.
18+
* <p>
19+
* If an interval is specified by {@link UpdateControl} or {@link DeleteControl}, those take
20+
* precedence.
21+
* <p>
22+
* This is a fail-safe feature, in the sense that if informers are in place and the reconciler
23+
* implementation is correct, this feature can be turned off.
24+
* <p>
25+
* Use {@link Constants#NO_MAX_RECONCILIATION_INTERVAL} to turn off this feature.
26+
*
27+
* @return max delay between reconciliations
28+
**/
29+
long interval();
30+
31+
/**
32+
* @return time unit for max delay between reconciliations
33+
*/
34+
TimeUnit timeUnit() default TimeUnit.HOURS;
35+
36+
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ReconciliationMaxInterval.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66
import java.lang.annotation.Target;
77
import java.util.concurrent.TimeUnit;
88

9+
/**
10+
* @deprecated use {@link MaxReconciliationInterval} instead
11+
*/
912
@Retention(RetentionPolicy.RUNTIME)
1013
@Target({ElementType.TYPE})
14+
@Deprecated(forRemoval = true)
1115
public @interface ReconciliationMaxInterval {
1216

1317
/**
@@ -22,7 +26,7 @@
2226
* This is a fail-safe feature, in the sense that if informers are in place and the reconciler
2327
* implementation is correct, this feature can be turned off.
2428
* <p>
25-
* Use NO_RECONCILIATION_MAX_INTERVAL in {@link Constants} to turn off this feature.
29+
* Use {@link Constants#NO_MAX_RECONCILIATION_INTERVAL} to turn off this feature.
2630
*
2731
* @return max delay between reconciliations
2832
**/

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ private void updatePostExecutionControlWithReschedule(
270270
PostExecutionControl<R> postExecutionControl,
271271
BaseControl<?> baseControl) {
272272
baseControl.getScheduleDelay().ifPresentOrElse(postExecutionControl::withReSchedule,
273-
() -> controller.getConfiguration().reconciliationMaxInterval()
273+
() -> controller.getConfiguration().maxReconciliationInterval()
274274
.ifPresent(m -> postExecutionControl.withReSchedule(m.toMillis())));
275275
}
276276

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ private <R extends HasMetadata> ReconciliationDispatcher<R> init(R customResourc
111111
when(configuration.getName()).thenReturn("EventDispatcherTestController");
112112
when(configuration.getResourceClass()).thenReturn(resourceClass);
113113
when(configuration.getRetry()).thenReturn(new GenericRetry());
114-
when(configuration.reconciliationMaxInterval())
114+
when(configuration.maxReconciliationInterval())
115115
.thenReturn(Optional.of(Duration.ofHours(RECONCILIATION_MAX_INTERVAL)));
116116

117117
Controller<R> controller = new Controller<>(reconciler, configuration,
@@ -618,7 +618,7 @@ void canSkipSchedulingMaxDelayIf() {
618618
testCustomResource.addFinalizer(DEFAULT_FINALIZER);
619619

620620
reconciler.reconcile = (r, c) -> UpdateControl.noUpdate();
621-
when(reconciliationDispatcher.configuration().reconciliationMaxInterval())
621+
when(reconciliationDispatcher.configuration().maxReconciliationInterval())
622622
.thenReturn(Optional.empty());
623623

624624
PostExecutionControl control =

operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfigurationTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.List;
99
import java.util.Optional;
1010
import java.util.Set;
11+
import java.util.concurrent.TimeUnit;
1112

1213
import org.junit.jupiter.api.Assertions;
1314
import org.junit.jupiter.api.Test;
@@ -18,7 +19,9 @@
1819
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
1920
import io.javaoperatorsdk.operator.api.reconciler.Context;
2021
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
22+
import io.javaoperatorsdk.operator.api.reconciler.MaxReconciliationInterval;
2123
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
24+
import io.javaoperatorsdk.operator.api.reconciler.ReconciliationMaxInterval;
2225
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
2326
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
2427
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
@@ -129,6 +132,11 @@ && findByNameOptional(dependents, DependentResource.defaultNameFor(ReadOnlyDepen
129132
.isPresent());
130133
}
131134

135+
@Test
136+
void newMaxIntervalShouldTakePrecedence() {
137+
var config = new AnnotationControllerConfiguration<>(new MaxIntervalReconciler());
138+
assertEquals(50, config.maxReconciliationInterval().map(Duration::getSeconds).orElseThrow());
139+
}
132140

133141
@Test
134142
void checkDefaultRateAndRetryConfigurations() {
@@ -169,6 +177,20 @@ void checkingRetryingGraduallyWorks() {
169177
assertEquals(CheckRetryingGraduallyConfiguration.MAX_INTERVAL, genericRetry.getMaxInterval());
170178
}
171179

180+
@ControllerConfiguration(
181+
maxReconciliationInterval = @MaxReconciliationInterval(interval = 50,
182+
timeUnit = TimeUnit.SECONDS),
183+
reconciliationMaxInterval = @ReconciliationMaxInterval(interval = 20,
184+
timeUnit = TimeUnit.SECONDS))
185+
private static class MaxIntervalReconciler implements Reconciler<ConfigMap> {
186+
187+
@Override
188+
public UpdateControl<ConfigMap> reconcile(ConfigMap resource, Context<ConfigMap> context)
189+
throws Exception {
190+
return null;
191+
}
192+
}
193+
172194
@ControllerConfiguration(namespaces = OneDepReconciler.CONFIGURED_NS,
173195
dependents = @Dependent(type = ReadOnlyDependent.class))
174196
private static class OneDepReconciler implements Reconciler<ConfigMap> {

operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/maxinterval/MaxIntervalTestReconciler.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
import java.util.concurrent.TimeUnit;
44
import java.util.concurrent.atomic.AtomicInteger;
55

6-
import io.javaoperatorsdk.operator.api.reconciler.*;
6+
import io.javaoperatorsdk.operator.api.reconciler.Context;
7+
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
8+
import io.javaoperatorsdk.operator.api.reconciler.MaxReconciliationInterval;
9+
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
10+
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
711
import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider;
812

9-
@ControllerConfiguration(reconciliationMaxInterval = @ReconciliationMaxInterval(interval = 50,
13+
@ControllerConfiguration(maxReconciliationInterval = @MaxReconciliationInterval(interval = 50,
1014
timeUnit = TimeUnit.MILLISECONDS))
1115
public class MaxIntervalTestReconciler
1216
implements Reconciler<MaxIntervalTestCustomResource>, TestExecutionInfoProvider {

0 commit comments

Comments
 (0)