11
11
12
12
import io .fabric8 .kubernetes .api .model .HasMetadata ;
13
13
import io .javaoperatorsdk .operator .api .reconciler .Context ;
14
+ import io .javaoperatorsdk .operator .api .reconciler .dependent .Deleter ;
14
15
15
16
public class WorkflowCleanupExecutor <P extends HasMetadata > {
16
17
@@ -20,10 +21,8 @@ public class WorkflowCleanupExecutor<P extends HasMetadata> {
20
21
new HashMap <>();
21
22
private final Map <DependentResourceNode <?, ?>, Exception > exceptionsDuringExecution =
22
23
new HashMap <>();
23
- private final Set <DependentResourceNode <?, ?>> alreadyReconciled = new HashSet <>();
24
+ private final Set <DependentResourceNode <?, ?>> alreadyVisited = new HashSet <>();
24
25
private final Set <DependentResourceNode <?, ?>> notReady = new HashSet <>();
25
- private final Set <DependentResourceNode <?, ?>> ownOrAncestorReconcileConditionConditionNotMet =
26
- new HashSet <>();
27
26
28
27
private final Workflow <P > workflow ;
29
28
private final P primary ;
@@ -35,11 +34,13 @@ public WorkflowCleanupExecutor(Workflow<P> workflow, P primary, Context<P> conte
35
34
this .context = context ;
36
35
}
37
36
37
+ // todo cleanup condition
38
+ // todo error handling
38
39
39
40
public synchronized WorkflowCleanupResult cleanup () {
40
41
for (DependentResourceNode <?, P > dependentResourceNode : workflow
41
42
.getBottomLevelResource ()) {
42
- handleCleanup (dependentResourceNode , false );
43
+ handleCleanup (dependentResourceNode );
43
44
}
44
45
while (true ) {
45
46
try {
@@ -57,15 +58,11 @@ public synchronized WorkflowCleanupResult cleanup() {
57
58
return createCleanupResult ();
58
59
}
59
60
60
- private WorkflowCleanupResult createCleanupResult () {
61
- return new WorkflowCleanupResult ();
62
- }
63
-
64
61
private synchronized boolean noMoreExecutionsScheduled () {
65
62
return actualExecutions .isEmpty ();
66
63
}
67
64
68
- private void handleCleanup (DependentResourceNode <?, P > dependentResourceNode , boolean b ) {
65
+ private synchronized void handleCleanup (DependentResourceNode <?, P > dependentResourceNode ) {
69
66
log .debug ("Submitting for cleanup: {}" , dependentResourceNode );
70
67
71
68
if (alreadyVisited (dependentResourceNode )
@@ -76,24 +73,30 @@ private void handleCleanup(DependentResourceNode<?, P> dependentResourceNode, bo
76
73
return ;
77
74
}
78
75
76
+ Future <?> nodeFuture =
77
+ workflow .getExecutorService ().submit (
78
+ new NodeExecutor (dependentResourceNode ));
79
+ actualExecutions .put (dependentResourceNode , nodeFuture );
80
+ log .debug ("Submitted to reconcile: {}" , dependentResourceNode );
79
81
}
80
82
81
83
private class NodeExecutor implements Runnable {
82
84
83
85
private final DependentResourceNode <?, P > dependentResourceNode ;
84
- private final boolean onlyReconcileForPossibleDelete ;
85
86
86
- private NodeExecutor (DependentResourceNode <?, P > dependentResourceNode ,
87
- boolean onlyReconcileForDelete ) {
87
+ private NodeExecutor (DependentResourceNode <?, P > dependentResourceNode ) {
88
88
this .dependentResourceNode = dependentResourceNode ;
89
- this .onlyReconcileForPossibleDelete = onlyReconcileForDelete ;
90
89
}
91
90
92
91
@ Override
93
92
@ SuppressWarnings ("unchecked" )
94
93
public void run () {
95
94
try {
96
-
95
+ if (dependentResourceNode .getDependentResource () instanceof Deleter ) {
96
+ // todo check if not garbage collected
97
+ ((Deleter <P >) dependentResourceNode .getDependentResource ()).delete (primary , context );
98
+ }
99
+ handleDependentCleaned (dependentResourceNode );
97
100
} catch (RuntimeException e ) {
98
101
handleExceptionInExecutor (dependentResourceNode , e );
99
102
} finally {
@@ -102,12 +105,26 @@ public void run() {
102
105
}
103
106
}
104
107
105
- private synchronized void handleExceptionInExecutor (DependentResourceNode dependentResourceNode ,
108
+ @ SuppressWarnings ("unchecked" )
109
+ private synchronized void handleDependentCleaned (
110
+ DependentResourceNode <?, P > dependentResourceNode ) {
111
+ var dependOns = dependentResourceNode .getDependsOn ();
112
+ if (dependOns != null ) {
113
+ dependOns .forEach (d -> {
114
+ log .debug ("Handle cleanup for dependent: {} of parent:{}" , d , dependentResourceNode );
115
+ handleCleanup (d );
116
+ });
117
+ }
118
+ }
119
+
120
+ private synchronized void handleExceptionInExecutor (
121
+ DependentResourceNode <?, P > dependentResourceNode ,
106
122
RuntimeException e ) {
107
123
exceptionsDuringExecution .put (dependentResourceNode , e );
108
124
}
109
125
110
- private synchronized void handleNodeExecutionFinish (DependentResourceNode dependentResourceNode ) {
126
+ private synchronized void handleNodeExecutionFinish (
127
+ DependentResourceNode <?, P > dependentResourceNode ) {
111
128
log .debug ("Finished execution for: {}" , dependentResourceNode );
112
129
actualExecutions .remove (dependentResourceNode );
113
130
if (actualExecutions .isEmpty ()) {
@@ -119,23 +136,27 @@ private boolean isCleaningNow(DependentResourceNode<?, ?> dependentResourceNode)
119
136
return actualExecutions .containsKey (dependentResourceNode );
120
137
}
121
138
122
-
123
139
private boolean alreadyVisited (
124
140
DependentResourceNode <?, ?> dependentResourceNode ) {
125
- return alreadyReconciled .contains (dependentResourceNode );
141
+ return alreadyVisited .contains (dependentResourceNode );
126
142
}
127
143
128
144
private boolean allParentsCleaned (
129
145
DependentResourceNode <?, ?> dependentResourceNode ) {
130
- return dependentResourceNode .getDependsOn ().isEmpty ()
131
- || dependentResourceNode .getDependsOn ().stream ()
146
+ var parents = workflow .getDependents ().get (dependentResourceNode );
147
+ return parents .isEmpty ()
148
+ || parents .stream ()
132
149
.allMatch (d -> alreadyVisited (d ) && !notReady .contains (d ));
133
150
}
134
151
135
152
private boolean hasErroredParent (
136
153
DependentResourceNode <?, ?> dependentResourceNode ) {
137
- return !dependentResourceNode .getDependsOn ().isEmpty ()
138
- && dependentResourceNode .getDependsOn ().stream ()
139
- .anyMatch (exceptionsDuringExecution ::containsKey );
154
+ var parents = workflow .getDependents ().get (dependentResourceNode );
155
+ return !parents .isEmpty ()
156
+ && parents .stream ().anyMatch (exceptionsDuringExecution ::containsKey );
157
+ }
158
+
159
+ private WorkflowCleanupResult createCleanupResult () {
160
+ return new WorkflowCleanupResult ();
140
161
}
141
162
}
0 commit comments