Skip to content

Commit 609d764

Browse files
committed
execution results
1 parent 2953539 commit 609d764

File tree

4 files changed

+146
-50
lines changed

4 files changed

+146
-50
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ public Workflow(List<DependentResourceNode<?, P>> dependentResourceNodes, int gl
4242
this(dependentResourceNodes, Executors.newFixedThreadPool(globalParallelism));
4343
}
4444

45-
public void reconcile(P primary, Context<P> context) {
46-
WorkflowReconcileExecutor<P> workflowReconcileExecutor =
45+
public WorkflowExecutionResult reconcile(P primary, Context<P> context) {
46+
WorkflowReconcileExecutor workflowReconcileExecutor =
4747
new WorkflowReconcileExecutor<>(this, primary, context);
48-
workflowReconcileExecutor.reconcile();
48+
return workflowReconcileExecutor.reconcile();
4949
}
5050

5151
public void cleanup(P resource, Context<P> context) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package io.javaoperatorsdk.operator.processing.dependent.workflow;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
import io.javaoperatorsdk.operator.AggregatedOperatorException;
9+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
10+
11+
public class WorkflowExecutionResult {
12+
13+
// this includes also possibly deleted ones
14+
private List<DependentResource<?, ?>> reconciledDependents = new ArrayList<>();
15+
private List<DependentResource<?, ?>> notReconciledDependents = new ArrayList<>();
16+
private List<DependentResource<?, ?>> notReadyDependents = new ArrayList<>();
17+
private Map<DependentResource<?, ?>, Exception> erroredDependents = new HashMap<>();
18+
19+
public Map<DependentResource<?, ?>, Exception> getErroredDependents() {
20+
return erroredDependents;
21+
}
22+
23+
public WorkflowExecutionResult setErroredDependents(
24+
Map<DependentResource<?, ?>, Exception> erroredDependents) {
25+
this.erroredDependents = erroredDependents;
26+
return this;
27+
}
28+
29+
public List<DependentResource<?, ?>> getReconciledDependents() {
30+
return reconciledDependents;
31+
}
32+
33+
public WorkflowExecutionResult setReconciledDependents(
34+
List<DependentResource<?, ?>> reconciledDependents) {
35+
this.reconciledDependents = reconciledDependents;
36+
return this;
37+
}
38+
39+
public List<DependentResource<?, ?>> getNotReadyDependents() {
40+
return notReadyDependents;
41+
}
42+
43+
public WorkflowExecutionResult setNotReadyDependents(
44+
List<DependentResource<?, ?>> notReadyDependents) {
45+
this.notReadyDependents = notReadyDependents;
46+
return this;
47+
}
48+
49+
public List<DependentResource<?, ?>> getNotReconciledDependents() {
50+
return notReconciledDependents;
51+
}
52+
53+
public WorkflowExecutionResult setNotReconciledDependents(
54+
List<DependentResource<?, ?>> notReconciledDependents) {
55+
this.notReconciledDependents = notReconciledDependents;
56+
return this;
57+
}
58+
59+
public void throwAggregatedExceptionIfErrorsPresent() {
60+
if (!erroredDependents.isEmpty()) {
61+
throw createFinalException();
62+
}
63+
}
64+
65+
private AggregatedOperatorException createFinalException() {
66+
return new AggregatedOperatorException("Exception during workflow.",
67+
new ArrayList<>(erroredDependents.values()));
68+
}
69+
}

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

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
import java.util.*;
44
import java.util.concurrent.*;
5+
import java.util.stream.Collectors;
56

67
import org.slf4j.Logger;
78
import org.slf4j.LoggerFactory;
89

910
import io.fabric8.kubernetes.api.model.HasMetadata;
10-
import io.javaoperatorsdk.operator.AggregatedOperatorException;
1111
import io.javaoperatorsdk.operator.api.reconciler.Context;
1212
import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
1313
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
@@ -20,17 +20,14 @@ public class WorkflowReconcileExecutor<P extends HasMetadata> {
2020

2121
private final Workflow<P> workflow;
2222

23-
private final Set<DependentResourceNode<?, ?>> alreadyReconciled = ConcurrentHashMap.newKeySet();
24-
private final Set<DependentResourceNode<?, ?>> errored = ConcurrentHashMap.newKeySet();
25-
private final Set<DependentResourceNode<?, ?>> notReady =
26-
ConcurrentHashMap.newKeySet();
27-
private final Set<DependentResourceNode<?, ?>> reconcileConditionOrParentsConditionNotMet =
28-
ConcurrentHashMap.newKeySet();
29-
23+
private final Set<DependentResourceNode<?, ?>> alreadyReconciled = new HashSet<>();
24+
private final Set<DependentResourceNode<?, ?>> notReady = new HashSet<>();
25+
private final Set<DependentResourceNode<?, ?>> ownOrAncestorReconcileConditionConditionNotMet =
26+
new HashSet<>();
3027
private final Map<DependentResourceNode<?, ?>, Future<?>> actualExecutions =
31-
new ConcurrentHashMap<>();
32-
private final List<Exception> exceptionsDuringExecution =
33-
Collections.synchronizedList(new ArrayList<>());
28+
new HashMap<>();
29+
private final Map<DependentResourceNode<?, ?>, Exception> exceptionsDuringExecution =
30+
new HashMap<>();
3431

3532
private final P primary;
3633
private final Context<P> context;
@@ -42,18 +39,14 @@ public WorkflowReconcileExecutor(Workflow<P> workflow, P primary, Context<P> con
4239
}
4340

4441
// add reconcile results
45-
public synchronized void reconcile() {
42+
public synchronized WorkflowExecutionResult reconcile() {
4643
for (DependentResourceNode<?, P> dependentResourceNode : workflow
4744
.getTopLevelDependentResources()) {
4845
handleReconcile(dependentResourceNode, false);
4946
}
5047
while (true) {
5148
try {
5249
this.wait();
53-
if (!exceptionsDuringExecution.isEmpty()) {
54-
log.debug("Exception during reconciliation for: {}", primary);
55-
throw createFinalException();
56-
}
5750
if (noMoreExecutionsScheduled()) {
5851
break;
5952
} else {
@@ -64,6 +57,7 @@ public synchronized void reconcile() {
6457
Thread.currentThread().interrupt();
6558
}
6659
}
60+
return createReconcileResult();
6761
}
6862

6963
private synchronized void handleReconcile(
@@ -80,7 +74,7 @@ private synchronized void handleReconcile(
8074
}
8175

8276
if (onlyReconcileForPossibleDelete) {
83-
reconcileConditionOrParentsConditionNotMet.add(dependentResourceNode);
77+
ownOrAncestorReconcileConditionConditionNotMet.add(dependentResourceNode);
8478
} else {
8579
dependentResourceNode.getReconcileCondition()
8680
.ifPresent(reconcileCondition -> handleReconcileCondition(dependentResourceNode,
@@ -98,8 +92,7 @@ private synchronized void handleReconcile(
9892

9993
private synchronized void handleExceptionInExecutor(DependentResourceNode dependentResourceNode,
10094
RuntimeException e) {
101-
exceptionsDuringExecution.add(e);
102-
errored.add(dependentResourceNode);
95+
exceptionsDuringExecution.put(dependentResourceNode, e);
10396
}
10497

10598
private synchronized void handleNodeExecutionFinish(DependentResourceNode dependentResourceNode) {
@@ -125,9 +118,9 @@ private synchronized void setAlreadyReconciledButNotReady(
125118

126119
private boolean ownOrParentsReconcileConditionNotMet(
127120
DependentResourceNode<?, ?> dependentResourceNode) {
128-
return reconcileConditionOrParentsConditionNotMet.contains(dependentResourceNode) ||
121+
return ownOrAncestorReconcileConditionConditionNotMet.contains(dependentResourceNode) ||
129122
dependentResourceNode.getDependsOn().stream()
130-
.anyMatch(reconcileConditionOrParentsConditionNotMet::contains);
123+
.anyMatch(ownOrAncestorReconcileConditionConditionNotMet::contains);
131124
}
132125

133126
private class NodeExecutor implements Runnable {
@@ -196,10 +189,6 @@ private boolean noMoreExecutionsScheduled() {
196189
return actualExecutions.isEmpty();
197190
}
198191

199-
private AggregatedOperatorException createFinalException() {
200-
return new AggregatedOperatorException("Exception during workflow.", exceptionsDuringExecution);
201-
}
202-
203192
private boolean alreadyReconciled(
204193
DependentResourceNode<?, ?> dependentResourceNode) {
205194
return alreadyReconciled.contains(dependentResourceNode);
@@ -211,7 +200,7 @@ private void handleReconcileCondition(DependentResourceNode<?, ?> dependentResou
211200
boolean conditionMet =
212201
reconcileCondition.isMet(dependentResourceNode.getDependentResource(), primary, context);
213202
if (!conditionMet) {
214-
reconcileConditionOrParentsConditionNotMet.add(dependentResourceNode);
203+
ownOrAncestorReconcileConditionConditionNotMet.add(dependentResourceNode);
215204
}
216205
}
217206

@@ -226,6 +215,29 @@ private boolean hasErroredParent(
226215
DependentResourceNode<?, ?> dependentResourceNode) {
227216
return !dependentResourceNode.getDependsOn().isEmpty()
228217
&& dependentResourceNode.getDependsOn().stream()
229-
.anyMatch(errored::contains);
218+
.anyMatch(exceptionsDuringExecution::containsKey);
230219
}
220+
221+
private WorkflowExecutionResult createReconcileResult() {
222+
WorkflowExecutionResult workflowExecutionResult = new WorkflowExecutionResult();
223+
224+
workflowExecutionResult.setErroredDependents(exceptionsDuringExecution
225+
.entrySet().stream()
226+
.collect(Collectors.toMap(e -> e.getKey().getDependentResource(), Map.Entry::getValue)));
227+
workflowExecutionResult.setNotReadyDependents(notReady.stream()
228+
.map(DependentResourceNode::getDependentResource)
229+
.collect(Collectors.toList()));
230+
231+
workflowExecutionResult.setReconciledDependents(alreadyReconciled.stream()
232+
.map(DependentResourceNode::getDependentResource).collect(Collectors.toList()));
233+
234+
var notReconciledDependentResources =
235+
new HashSet<DependentResourceNode<?, ?>>(workflow.getDependents().keySet());
236+
notReconciledDependentResources.removeAll(alreadyReconciled);
237+
workflowExecutionResult.setNotReconciledDependents(notReconciledDependentResources.stream()
238+
.map(DependentResourceNode::getDependentResource).collect(Collectors.toList()));
239+
240+
return workflowExecutionResult;
241+
}
242+
231243
}

0 commit comments

Comments
 (0)