Skip to content

Commit ad7c9c6

Browse files
committed
wip
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
1 parent 461e78e commit ad7c9c6

3 files changed

Lines changed: 52 additions & 35 deletions

File tree

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

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ private synchronized <R> void handleReconcile(DependentResourceNode<R, P> depend
100100
isConditionMet(dependentResourceNode.getReconcilePrecondition(), dependentResourceNode);
101101
}
102102
if (!reconcileConditionMet || !activationConditionMet) {
103-
handleReconcileOrActivationConditionNotMet(dependentResourceNode, activationConditionMet);
103+
handleReconcileOrActivationConditionNotMet(dependentResourceNode);
104104
} else {
105105
submit(dependentResourceNode, new NodeReconcileExecutor<>(dependentResourceNode), RECONCILE);
106106
}
@@ -183,7 +183,10 @@ private NodeDeleteExecutor(DependentResourceNode<R, P> dependentResourceNode) {
183183
@SuppressWarnings("unchecked")
184184
protected void doRun(DependentResourceNode<R, P> dependentResourceNode) {
185185
boolean deletePostConditionMet = true;
186-
if (isConditionMet(dependentResourceNode.getActivationCondition(), dependentResourceNode)) {
186+
var active =
187+
isConditionMet(dependentResourceNode.getActivationCondition(), dependentResourceNode);
188+
registerOrDeregisterEventSourceBasedOnActivation(active, dependentResourceNode);
189+
if (active) {
187190
// GarbageCollected status is irrelevant here, as this method is only called when a
188191
// precondition does not hold,
189192
// a deleter should be deleted even if it is otherwise garbage collected
@@ -194,7 +197,6 @@ protected void doRun(DependentResourceNode<R, P> dependentResourceNode) {
194197
deletePostConditionMet =
195198
isConditionMet(dependentResourceNode.getDeletePostcondition(), dependentResourceNode);
196199
}
197-
198200
createOrGetResultFor(dependentResourceNode).markAsVisited();
199201
if (deletePostConditionMet) {
200202
handleDependentDeleted(dependentResourceNode);
@@ -232,44 +234,20 @@ private synchronized void handleDependentsReconcile(
232234
}
233235

234236
private void handleReconcileOrActivationConditionNotMet(
235-
DependentResourceNode<?, P> dependentResourceNode, boolean activationConditionMet) {
237+
DependentResourceNode<?, P> dependentResourceNode) {
236238
Set<DependentResourceNode> bottomNodes = new HashSet<>();
237-
markDependentsForDelete(dependentResourceNode, bottomNodes, activationConditionMet);
239+
markDependentsForDelete(dependentResourceNode, bottomNodes);
238240
bottomNodes.forEach(this::handleDelete);
239241
}
240242

241-
private <R> void markDependentsForDelete(
242-
DependentResourceNode<R, P> dependentResourceNode, Set<DependentResourceNode> bottomNodes) {
243-
boolean activationConditionMet =
244-
isConditionMet(dependentResourceNode.getActivationCondition(), dependentResourceNode);
245-
markDependentsForDelete(dependentResourceNode, bottomNodes, activationConditionMet);
246-
}
247-
248243
private void markDependentsForDelete(
249-
DependentResourceNode<?, P> dependentResourceNode,
250-
Set<DependentResourceNode> bottomNodes,
251-
boolean activationConditionMet) {
252-
// this is a check so the activation condition is not evaluated twice,
253-
// so if the activation condition was false, this node is not meant to be deleted.
244+
DependentResourceNode<?, P> dependentResourceNode, Set<DependentResourceNode> bottomNodes) {
254245
var dependents = dependentResourceNode.getParents();
255-
if (activationConditionMet) {
256-
// make sure we register the dependent's event source if it hasn't been added already
257-
// this might be needed in corner cases such as
258-
registerOrDeregisterEventSourceBasedOnActivation(true, dependentResourceNode);
259-
createOrGetResultFor(dependentResourceNode).markForDelete();
260-
if (dependents.isEmpty()) {
261-
bottomNodes.add(dependentResourceNode);
262-
} else {
263-
dependents.forEach(d -> markDependentsForDelete(d, bottomNodes));
264-
}
246+
createOrGetResultFor(dependentResourceNode).markForDelete();
247+
if (dependents.isEmpty()) {
248+
bottomNodes.add(dependentResourceNode);
265249
} else {
266-
if (dependents.isEmpty()) {
267-
createOrGetResultFor(dependentResourceNode).markAsVisited();
268-
handleNodeExecutionFinish(dependentResourceNode);
269-
} else {
270-
createOrGetResultFor(dependentResourceNode).markForDelete();
271-
dependents.forEach(d -> markDependentsForDelete(d, bottomNodes));
272-
}
250+
dependents.forEach(d -> markDependentsForDelete(d, bottomNodes));
273251
}
274252
}
275253

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ protected void handleEvent(
139139

140140
@Override
141141
public synchronized void start() {
142+
if (isRunning()) {
143+
return;
144+
}
142145
super.start();
143146
// this makes sure that on first reconciliation all resources are
144147
// present on the index

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowReconcileExecutorTest.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class WorkflowReconcileExecutorTest extends AbstractWorkflowExecutorTest {
4545
Context<TestCustomResource> mockContext = spy(Context.class);
4646

4747
ExecutorService executorService = Executors.newCachedThreadPool();
48+
EventSourceRetriever eventSourceRetriever = mock(EventSourceRetriever.class);
4849

4950
TestDependent dr3 = new TestDependent("DR_3");
5051
TestDependent dr4 = new TestDependent("DR_4");
@@ -56,7 +57,7 @@ void setup(TestInfo testInfo) {
5657
when(mockContext.managedWorkflowAndDependentResourceContext())
5758
.thenReturn(mock(ManagedWorkflowAndDependentResourceContext.class));
5859
when(mockContext.getWorkflowExecutorService()).thenReturn(executorService);
59-
when(mockContext.eventSourceRetriever()).thenReturn(mock(EventSourceRetriever.class));
60+
when(mockContext.eventSourceRetriever()).thenReturn(eventSourceRetriever);
6061
}
6162

6263
@Test
@@ -693,6 +694,41 @@ void activationConditionOnlyCalledOnceOnDeleteDependents() {
693694
verify(condition, times(1)).isMet(any(), any(), any());
694695
}
695696

697+
@Test
698+
@SuppressWarnings("unchecked")
699+
void activationConditionEventSourceRegistrationWithParentWithFalsePrecondition() {
700+
var workflow =
701+
new WorkflowBuilder<TestCustomResource>()
702+
.addDependentResourceAndConfigure(dr1)
703+
.withReconcilePrecondition(notMetCondition)
704+
.addDependentResourceAndConfigure(drDeleter)
705+
.withActivationCondition(notMetCondition)
706+
.dependsOn(dr1)
707+
.build();
708+
709+
workflow.reconcile(new TestCustomResource(), mockContext);
710+
assertThat(executionHistory).notReconciled(dr1, drDeleter);
711+
verify(eventSourceRetriever, never()).dynamicallyRegisterEventSource(any());
712+
verify(eventSourceRetriever, times(1)).dynamicallyDeRegisterEventSource(any());
713+
}
714+
715+
@Test
716+
@SuppressWarnings("unchecked")
717+
void activationConditionEventSourceRegistration() {
718+
var workflow =
719+
new WorkflowBuilder<TestCustomResource>()
720+
.addDependentResourceAndConfigure(dr1)
721+
.addDependentResourceAndConfigure(drDeleter)
722+
.withActivationCondition(notMetCondition)
723+
.dependsOn(dr1)
724+
.build();
725+
726+
workflow.reconcile(new TestCustomResource(), mockContext);
727+
assertThat(executionHistory).reconciled(dr1).notReconciled(drDeleter);
728+
verify(eventSourceRetriever, never()).dynamicallyRegisterEventSource(any());
729+
verify(eventSourceRetriever, atLeast(1)).dynamicallyDeRegisterEventSource(any());
730+
}
731+
696732
@Test
697733
void resultFromReadyConditionShouldBeAvailableIfExisting() {
698734
final var result = Integer.valueOf(42);

0 commit comments

Comments
 (0)