Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9ca8ae9

Browse files
committedMar 6, 2024
expiration improvements
Signed-off-by: Attila Mészáros <csviri@gmail.com>
1 parent 670636a commit 9ca8ae9

File tree

6 files changed

+91
-80
lines changed

6 files changed

+91
-80
lines changed
 

‎operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/CRDPresentActivationCondition.java

+31-45
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.util.Map;
44
import java.util.concurrent.ConcurrentHashMap;
55

6+
import io.javaoperatorsdk.operator.processing.expiration.Expiration;
7+
import io.javaoperatorsdk.operator.processing.expiration.RetryExpiration;
68
import org.slf4j.Logger;
79
import org.slf4j.LoggerFactory;
810

@@ -12,30 +14,31 @@
1214
import io.javaoperatorsdk.operator.api.reconciler.Context;
1315
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
1416
import io.javaoperatorsdk.operator.processing.GroupVersionKind;
15-
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
16-
import io.javaoperatorsdk.operator.processing.expiration.Expiration;
17-
import io.javaoperatorsdk.operator.processing.expiration.RetryExpiration;
17+
import io.javaoperatorsdk.operator.processing.expiration.ExpirationExecution;
1818
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
1919
import io.javaoperatorsdk.operator.processing.retry.Retry;
2020

2121
public class CRDPresentActivationCondition implements Condition<HasMetadata, HasMetadata> {
2222

23-
public static Retry DEFAULT_EXPIRATION_RETRY = new GenericRetry().setInitialInterval(2000)
24-
.setMaxInterval(1000 * 60 * 60)
25-
.setIntervalMultiplier(2);
26-
2723
private static final Logger log = LoggerFactory.getLogger(CRDPresentActivationCondition.class);
2824

25+
/**
26+
*
27+
* */
28+
public static Retry DEFAULT_EXPIRATION_RETRY = new GenericRetry().setInitialInterval(2000)
29+
.setIntervalMultiplier(2)
30+
.setMaxAttempts(10);
31+
2932
private final Map<GroupVersionKind, CRDCheckState> crdPresenceCache = new ConcurrentHashMap<>();
3033

31-
private final Retry expirationRetry;
34+
private final Expiration expiration;
3235

3336
public CRDPresentActivationCondition() {
34-
this(DEFAULT_EXPIRATION_RETRY);
37+
this(new RetryExpiration(DEFAULT_EXPIRATION_RETRY));
3538
}
3639

37-
public CRDPresentActivationCondition(Retry expirationRetry) {
38-
this.expirationRetry = expirationRetry;
40+
public CRDPresentActivationCondition(Expiration expiration) {
41+
this.expiration = expiration;
3942
}
4043

4144
@Override
@@ -47,60 +50,43 @@ public boolean isMet(DependentResource<HasMetadata, HasMetadata> dependentResour
4750
var kind = HasMetadata.getKind(resourceClass);
4851
var gvk = new GroupVersionKind(apiVersion, kind);
4952

50-
InformerEventSource<CustomResourceDefinition, HasMetadata> crdInformer = null;
51-
try {
52-
crdInformer = (InformerEventSource<CustomResourceDefinition, HasMetadata>) context
53-
.eventSourceRetriever().getResourceEventSourceFor(CustomResourceDefinition.class);
54-
} catch (IllegalArgumentException e) {
55-
log.trace("Error when finding event source for CustomResourceDefinitions", e);
56-
}
57-
58-
if (crdInformer != null) {
59-
return crdInformer
60-
.list(crd -> crd.getSpec().getNames().getKind().equals(kind)
61-
&& crd.getSpec().getGroup().equals(gvk.getGroup()))
62-
.findAny().isPresent();
63-
} else {
64-
var crdCheckState = crdPresenceCache.computeIfAbsent(gvk,
65-
g -> new CRDCheckState(new RetryExpiration(expirationRetry.initExecution())));
66-
// in case of parallel execution it is only refreshed once
67-
synchronized (crdCheckState) {
68-
if (crdCheckState.getExpiration().isExpired()) {
69-
refreshCache(gvk, context.getClient());
70-
}
53+
var crdCheckState = crdPresenceCache.computeIfAbsent(gvk,
54+
g -> new CRDCheckState(expiration.initExecution()));
55+
// in case of parallel execution it is only refreshed once
56+
synchronized (crdCheckState) {
57+
if (crdCheckState.getExpiration().isExpired()) {
58+
refreshCache(crdCheckState,gvk, context.getClient());
7159
}
72-
return crdPresenceCache.get(gvk).getCrdPresent();
7360
}
61+
return crdPresenceCache.get(gvk).getCrdPresent();
7462
}
7563

76-
private void refreshCache(GroupVersionKind gvk, KubernetesClient client) {
77-
var state = crdPresenceCache.computeIfAbsent(gvk,
78-
g -> new CRDCheckState(new RetryExpiration(expirationRetry.initExecution())));
64+
private void refreshCache(CRDCheckState crdCheckState, GroupVersionKind gvk, KubernetesClient client) {
7965

8066
boolean found = client.resources(CustomResourceDefinition.class).list().getItems()
8167
.stream().anyMatch(crd -> crd.getSpec().getNames().getKind().equals(gvk.getKind())
8268
&& crd.getSpec().getGroup().equals(gvk.getGroup()));
8369

84-
state.setCrdPresent(found);
85-
state.getExpiration().refreshed();
70+
crdCheckState.setCrdPresent(found);
71+
crdCheckState.getExpiration().refreshed();
8672
}
8773

8874
static class CRDCheckState {
8975

90-
public CRDCheckState(Expiration expiration) {
91-
this.expiration = expiration;
76+
public CRDCheckState(ExpirationExecution expirationExecution) {
77+
this.expirationExecution = expirationExecution;
9278
}
9379

94-
private Expiration expiration;
80+
private ExpirationExecution expirationExecution;
9581

9682
private Boolean crdPresent;
9783

98-
public Expiration getExpiration() {
99-
return expiration;
84+
public ExpirationExecution getExpiration() {
85+
return expirationExecution;
10086
}
10187

102-
public void setExpiration(Expiration expiration) {
103-
this.expiration = expiration;
88+
public void setExpiration(ExpirationExecution expirationExecution) {
89+
this.expirationExecution = expirationExecution;
10490
}
10591

10692
public Boolean getCrdPresent() {
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package io.javaoperatorsdk.operator.processing.expiration;
22

3-
public interface Expiration {
43

5-
boolean isExpired();
4+
public interface Expiration {
65

7-
void refreshed();
6+
ExpirationExecution initExecution();
87

98
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.javaoperatorsdk.operator.processing.expiration;
2+
3+
public interface ExpirationExecution {
4+
5+
boolean isExpired();
6+
7+
void refreshed();
8+
9+
}
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,17 @@
11
package io.javaoperatorsdk.operator.processing.expiration;
22

3-
import java.time.LocalDateTime;
4-
import java.time.temporal.ChronoUnit;
5-
import java.util.Objects;
6-
7-
import io.javaoperatorsdk.operator.processing.retry.RetryExecution;
3+
import io.javaoperatorsdk.operator.processing.retry.Retry;
84

95
public class RetryExpiration implements Expiration {
106

11-
public static final long NO_MORE_EXPIRATION = -1L;
12-
13-
private LocalDateTime lastRefreshTime;
14-
private Long delayUntilExpiration;
15-
private final RetryExecution retryExecution;
16-
17-
public RetryExpiration(RetryExecution retryExecution) {
18-
this.retryExecution = retryExecution;
19-
}
7+
private final Retry retry;
208

21-
@Override
22-
public boolean isExpired() {
23-
if (lastRefreshTime == null) {
24-
return true;
9+
public RetryExpiration(Retry retry) {
10+
this.retry = retry;
2511
}
26-
if (Objects.equals(delayUntilExpiration, NO_MORE_EXPIRATION)) {
27-
return false;
28-
} else {
29-
return LocalDateTime.now()
30-
.isAfter(lastRefreshTime.plus(delayUntilExpiration, ChronoUnit.MILLIS));
31-
}
32-
}
3312

34-
@Override
35-
public void refreshed() {
36-
lastRefreshTime = LocalDateTime.now();
37-
delayUntilExpiration = retryExecution.nextDelay().orElse(NO_MORE_EXPIRATION);
38-
}
13+
@Override
14+
public ExpirationExecution initExecution() {
15+
return new RetryExpirationExecution(retry.initExecution());
16+
}
3917
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package io.javaoperatorsdk.operator.processing.expiration;
2+
3+
import java.time.LocalDateTime;
4+
import java.time.temporal.ChronoUnit;
5+
import java.util.Objects;
6+
7+
import io.javaoperatorsdk.operator.processing.retry.RetryExecution;
8+
9+
public class RetryExpirationExecution implements ExpirationExecution {
10+
11+
public static final long NO_MORE_EXPIRATION = -1L;
12+
13+
private LocalDateTime lastRefreshTime;
14+
private Long delayUntilExpiration;
15+
private final RetryExecution retryExecution;
16+
17+
public RetryExpirationExecution(RetryExecution retryExecution) {
18+
this.retryExecution = retryExecution;
19+
}
20+
21+
@Override
22+
public boolean isExpired() {
23+
if (lastRefreshTime == null) {
24+
return true;
25+
}
26+
if (Objects.equals(delayUntilExpiration, NO_MORE_EXPIRATION)) {
27+
return false;
28+
} else {
29+
return LocalDateTime.now()
30+
.isAfter(lastRefreshTime.plus(delayUntilExpiration, ChronoUnit.MILLIS));
31+
}
32+
}
33+
34+
@Override
35+
public void refreshed() {
36+
lastRefreshTime = LocalDateTime.now();
37+
delayUntilExpiration = retryExecution.nextDelay().orElse(NO_MORE_EXPIRATION);
38+
}
39+
}
+2-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66

77
import static org.assertj.core.api.Assertions.assertThat;
88

9-
public class RetryExpirationTest {
9+
public class RetryExpirationTestExecution {
1010

1111
public static final int INITIAL_INTERVAL = 25;
1212
public static final int INITIAL_INTERVAL_PLUS_SLACK = INITIAL_INTERVAL + 10;
1313

14-
RetryExpiration expiration = new RetryExpiration(new GenericRetry()
14+
RetryExpirationExecution expiration = new RetryExpirationExecution(new GenericRetry()
1515
.setInitialInterval(INITIAL_INTERVAL)
1616
.setMaxAttempts(2)
1717
.initExecution());

0 commit comments

Comments
 (0)
Please sign in to comment.