1
1
package io .javaoperatorsdk .operator .processing .dependent ;
2
2
3
+ import java .util .ArrayList ;
4
+ import java .util .List ;
3
5
import java .util .Optional ;
4
6
5
7
import org .slf4j .Logger ;
@@ -20,25 +22,73 @@ public abstract class AbstractDependentResource<R, P extends HasMetadata>
20
22
21
23
protected final boolean creatable = this instanceof Creator ;
22
24
protected final boolean updatable = this instanceof Updater ;
25
+ protected final boolean bulk = this instanceof BulkDependentResource ;
23
26
24
27
protected Creator <R , P > creator ;
25
28
protected Updater <R , P > updater ;
29
+ protected BulkDependentResource <R , P > bulkDependentResource ;
26
30
27
- private ResourceDiscriminator <R , P > resourceDiscriminator ;
31
+ private final List < ResourceDiscriminator <R , P >> resourceDiscriminator = new ArrayList <>( 1 ) ;
28
32
29
33
@ SuppressWarnings ("unchecked" )
30
34
public AbstractDependentResource () {
31
35
creator = creatable ? (Creator <R , P >) this : null ;
32
36
updater = updatable ? (Updater <R , P >) this : null ;
37
+
38
+ bulkDependentResource = bulk ? (BulkDependentResource <R , P >) this : null ;
33
39
}
34
40
35
41
@ Override
36
42
public ReconcileResult <R > reconcile (P primary , Context <P > context ) {
37
- Optional <R > maybeActual = getSecondaryResource (primary , context );
43
+ if (bulk ) {
44
+ final var count = bulkDependentResource .count (primary , context );
45
+ deleteBulkResourcesIfRequired (count , lastKnownBulkSize (), primary , context );
46
+ adjustDiscriminators (count );
47
+ @ SuppressWarnings ("unchecked" )
48
+ final ReconcileResult <R >[] results = new ReconcileResult [count ];
49
+ for (int i = 0 ; i < count ; i ++) {
50
+ results [i ] = reconcileIndexAware (primary , i , context );
51
+ }
52
+ return ReconcileResult .aggregatedResult (results );
53
+ } else {
54
+ return reconcileIndexAware (primary , 0 , context );
55
+ }
56
+ }
57
+
58
+ protected void deleteBulkResourcesIfRequired (int targetCount , int actualCount , P primary ,
59
+ Context <P > context ) {
60
+ if (targetCount >= actualCount ) {
61
+ return ;
62
+ }
63
+ for (int i = targetCount ; i < actualCount ; i ++) {
64
+ var resource = getSecondaryResourceIndexAware (primary , i , context );
65
+ var index = i ;
66
+ resource .ifPresent (
67
+ r -> bulkDependentResource .deleteBulkResourceWithIndex (primary , r , index , context ));
68
+ }
69
+ }
70
+
71
+ private void adjustDiscriminators (int count ) {
72
+ if (resourceDiscriminator .size () == count ) {
73
+ return ;
74
+ }
75
+ if (resourceDiscriminator .size () < count ) {
76
+ for (int i = resourceDiscriminator .size (); i < count ; i ++) {
77
+ resourceDiscriminator .add (bulkDependentResource .getResourceDiscriminator (i ));
78
+ }
79
+ }
80
+ if (resourceDiscriminator .size () > count ) {
81
+ resourceDiscriminator .subList (count , resourceDiscriminator .size ()).clear ();
82
+ }
83
+ }
84
+
85
+ protected ReconcileResult <R > reconcileIndexAware (P primary , int i , Context <P > context ) {
86
+ Optional <R > maybeActual = bulk ? getSecondaryResourceIndexAware (primary , i , context )
87
+ : getSecondaryResource (primary , context );
38
88
if (creatable || updatable ) {
39
89
if (maybeActual .isEmpty ()) {
40
90
if (creatable ) {
41
- var desired = desired (primary , context );
91
+ var desired = desiredIndexAware (primary , i , context );
42
92
throwIfNull (desired , primary , "Desired" );
43
93
logForOperation ("Creating" , primary , desired );
44
94
var createdResource = handleCreate (desired , primary , context );
@@ -47,9 +97,15 @@ public ReconcileResult<R> reconcile(P primary, Context<P> context) {
47
97
} else {
48
98
final var actual = maybeActual .get ();
49
99
if (updatable ) {
50
- final var match = updater .match (actual , primary , context );
100
+ final Matcher .Result <R > match ;
101
+ if (bulk ) {
102
+ match = updater .match (actual , primary , i , context );
103
+ } else {
104
+ match = updater .match (actual , primary , context );
105
+ }
51
106
if (!match .matched ()) {
52
- final var desired = match .computedDesired ().orElseGet (() -> desired (primary , context ));
107
+ final var desired =
108
+ match .computedDesired ().orElse (desiredIndexAware (primary , i , context ));
53
109
throwIfNull (desired , primary , "Desired" );
54
110
logForOperation ("Updating" , primary , desired );
55
111
var updatedResource = handleUpdate (actual , desired , primary , context );
@@ -67,9 +123,18 @@ public ReconcileResult<R> reconcile(P primary, Context<P> context) {
67
123
return ReconcileResult .noOperation (maybeActual .orElse (null ));
68
124
}
69
125
126
+ private R desiredIndexAware (P primary , int i , Context <P > context ) {
127
+ return bulk ? desired (primary , i , context )
128
+ : desired (primary , context );
129
+ }
130
+
70
131
public Optional <R > getSecondaryResource (P primary , Context <P > context ) {
71
- return resourceDiscriminator == null ? context .getSecondaryResource (resourceType ())
72
- : resourceDiscriminator .distinguish (resourceType (), primary , context );
132
+ return resourceDiscriminator .isEmpty () ? context .getSecondaryResource (resourceType ())
133
+ : resourceDiscriminator .get (0 ).distinguish (resourceType (), primary , context );
134
+ }
135
+
136
+ protected Optional <R > getSecondaryResourceIndexAware (P primary , int index , Context <P > context ) {
137
+ return context .getSecondaryResource (resourceType (), resourceDiscriminator .get (index ));
73
138
}
74
139
75
140
private void throwIfNull (R desired , P primary , String descriptor ) {
@@ -97,7 +162,7 @@ protected R handleCreate(R desired, P primary, Context<P> context) {
97
162
}
98
163
99
164
/**
100
- * Allows sub-classes to perform additional processing (e.g. caching) on the created resource if
165
+ * Allows subclasses to perform additional processing (e.g. caching) on the created resource if
101
166
* needed.
102
167
*
103
168
* @param primaryResourceId the {@link ResourceID} of the primary resource associated with the
@@ -129,12 +194,29 @@ protected R desired(P primary, Context<P> context) {
129
194
"desired method must be implemented if this DependentResource can be created and/or updated" );
130
195
}
131
196
132
- public void setResourceDiscriminator (
197
+ protected R desired (P primary , int index , Context <P > context ) {
198
+ throw new IllegalStateException (
199
+ "Must be implemented for bulk DependentResource creation" );
200
+ }
201
+
202
+ public AbstractDependentResource <R , P > setResourceDiscriminator (
133
203
ResourceDiscriminator <R , P > resourceDiscriminator ) {
134
- this .resourceDiscriminator = resourceDiscriminator ;
204
+ if (resourceDiscriminator != null ) {
205
+ this .resourceDiscriminator .add (resourceDiscriminator );
206
+ }
207
+ return this ;
135
208
}
136
209
137
210
public ResourceDiscriminator <R , P > getResourceDiscriminator () {
138
- return resourceDiscriminator ;
211
+ if (this .resourceDiscriminator .isEmpty ()) {
212
+ return null ;
213
+ } else {
214
+ return this .resourceDiscriminator .get (0 );
215
+ }
139
216
}
217
+
218
+ protected int lastKnownBulkSize () {
219
+ return resourceDiscriminator .size ();
220
+ }
221
+
140
222
}
0 commit comments