20
20
import org .apache .kafka .common .Uuid ;
21
21
import org .apache .kafka .common .protocol .Errors ;
22
22
import org .apache .kafka .common .requests .DeleteShareGroupStateResponse ;
23
+ import org .apache .kafka .common .requests .InitializeShareGroupStateResponse ;
23
24
import org .apache .kafka .common .requests .ReadShareGroupStateResponse ;
24
25
import org .apache .kafka .common .requests .ReadShareGroupStateSummaryResponse ;
25
26
import org .apache .kafka .common .requests .WriteShareGroupStateResponse ;
33
34
import java .util .List ;
34
35
import java .util .Map ;
35
36
import java .util .concurrent .CompletableFuture ;
36
- import java .util .stream .Collectors ;
37
37
38
38
/**
39
39
* The default implementation of the {@link Persister} interface which is used by the
@@ -70,7 +70,48 @@ public void stop() {
70
70
* @return A completable future of InitializeShareGroupStateResult
71
71
*/
72
72
public CompletableFuture <InitializeShareGroupStateResult > initializeState (InitializeShareGroupStateParameters request ) {
73
- throw new RuntimeException ("not implemented" );
73
+ try {
74
+ validate (request );
75
+ } catch (Exception e ) {
76
+ log .error ("Unable to validate initialize state request" , e );
77
+ return CompletableFuture .failedFuture (e );
78
+ }
79
+ GroupTopicPartitionData <PartitionStateData > gtp = request .groupTopicPartitionData ();
80
+ String groupId = gtp .groupId ();
81
+
82
+ Map <Uuid , Map <Integer , CompletableFuture <InitializeShareGroupStateResponse >>> futureMap = new HashMap <>();
83
+ List <PersisterStateManager .InitializeStateHandler > handlers = new ArrayList <>();
84
+
85
+ gtp .topicsData ().forEach (topicData -> {
86
+ topicData .partitions ().forEach (partitionData -> {
87
+ CompletableFuture <InitializeShareGroupStateResponse > future = futureMap
88
+ .computeIfAbsent (topicData .topicId (), k -> new HashMap <>())
89
+ .computeIfAbsent (partitionData .partition (), k -> new CompletableFuture <>());
90
+
91
+ handlers .add (
92
+ stateManager .new InitializeStateHandler (
93
+ groupId ,
94
+ topicData .topicId (),
95
+ partitionData .partition (),
96
+ partitionData .stateEpoch (),
97
+ partitionData .startOffset (),
98
+ future ,
99
+ null
100
+ )
101
+ );
102
+ });
103
+ });
104
+
105
+ for (PersisterStateManager .PersisterStateManagerHandler handler : handlers ) {
106
+ stateManager .enqueue (handler );
107
+ }
108
+
109
+ CompletableFuture <Void > combinedFuture = CompletableFuture .allOf (
110
+ handlers .stream ()
111
+ .map (PersisterStateManager .InitializeStateHandler ::result )
112
+ .toArray (CompletableFuture []::new ));
113
+
114
+ return combinedFuture .thenApply (v -> initializeResponsesToResult (futureMap ));
74
115
}
75
116
76
117
/**
@@ -125,6 +166,51 @@ stateManager.new WriteStateHandler(
125
166
return combinedFuture .thenApply (v -> writeResponsesToResult (futureMap ));
126
167
}
127
168
169
+ /**
170
+ * Takes in a list of COMPLETED futures and combines the results,
171
+ * taking care of errors if any, into a single InitializeShareGroupStateResult
172
+ *
173
+ * @param futureMap - HashMap of {topic -> {partition -> future}}
174
+ * @return Object representing combined result of type InitializeShareGroupStateResult
175
+ */
176
+ // visible for testing
177
+ InitializeShareGroupStateResult initializeResponsesToResult (
178
+ Map <Uuid , Map <Integer , CompletableFuture <InitializeShareGroupStateResponse >>> futureMap
179
+ ) {
180
+ List <TopicData <PartitionErrorData >> topicsData = futureMap .keySet ().stream ()
181
+ .map (topicId -> {
182
+ List <PartitionErrorData > partitionErrData = futureMap .get (topicId ).entrySet ().stream ()
183
+ .map (partitionFuture -> {
184
+ int partition = partitionFuture .getKey ();
185
+ CompletableFuture <InitializeShareGroupStateResponse > future = partitionFuture .getValue ();
186
+ try {
187
+ // already completed because of allOf application in the caller
188
+ InitializeShareGroupStateResponse partitionResponse = future .join ();
189
+ return partitionResponse .data ().results ().get (0 ).partitions ().stream ()
190
+ .map (partitionResult -> PartitionFactory .newPartitionErrorData (
191
+ partitionResult .partition (),
192
+ partitionResult .errorCode (),
193
+ partitionResult .errorMessage ()))
194
+ .toList ();
195
+ } catch (Exception e ) {
196
+ log .error ("Unexpected exception while initializing data in share coordinator" , e );
197
+ return List .of (PartitionFactory .newPartitionErrorData (
198
+ partition ,
199
+ Errors .UNKNOWN_SERVER_ERROR .code (), // No specific public error code exists for InterruptedException / ExecutionException
200
+ "Error initializing state in share coordinator: " + e .getMessage ())
201
+ );
202
+ }
203
+ })
204
+ .flatMap (List ::stream )
205
+ .toList ();
206
+ return new TopicData <>(topicId , partitionErrData );
207
+ })
208
+ .toList ();
209
+ return new InitializeShareGroupStateResult .Builder ()
210
+ .setTopicsData (topicsData )
211
+ .build ();
212
+ }
213
+
128
214
/**
129
215
* Takes in a list of COMPLETED futures and combines the results,
130
216
* taking care of errors if any, into a single WriteShareGroupStateResult
@@ -150,21 +236,21 @@ WriteShareGroupStateResult writeResponsesToResult(
150
236
partitionResult .partition (),
151
237
partitionResult .errorCode (),
152
238
partitionResult .errorMessage ()))
153
- .collect ( Collectors . toList () );
239
+ .toList ();
154
240
} catch (Exception e ) {
155
241
log .error ("Unexpected exception while writing data to share coordinator" , e );
156
- return Collections . singletonList (PartitionFactory .newPartitionErrorData (
242
+ return List . of (PartitionFactory .newPartitionErrorData (
157
243
partition ,
158
244
Errors .UNKNOWN_SERVER_ERROR .code (), // No specific public error code exists for InterruptedException / ExecutionException
159
245
"Error writing state to share coordinator: " + e .getMessage ())
160
246
);
161
247
}
162
248
})
163
249
.flatMap (List ::stream )
164
- .collect ( Collectors . toList () );
250
+ .toList ();
165
251
return new TopicData <>(topicId , partitionErrData );
166
252
})
167
- .collect ( Collectors . toList () );
253
+ .toList ();
168
254
return new WriteShareGroupStateResult .Builder ()
169
255
.setTopicsData (topicsData )
170
256
.build ();
@@ -248,12 +334,12 @@ ReadShareGroupStateResult readResponsesToResult(
248
334
partitionResult .startOffset (),
249
335
partitionResult .errorCode (),
250
336
partitionResult .errorMessage (),
251
- partitionResult .stateBatches ().stream ().map (PersisterStateBatch ::from ).collect ( Collectors . toList () )
337
+ partitionResult .stateBatches ().stream ().map (PersisterStateBatch ::from ).toList ()
252
338
))
253
- .collect ( Collectors . toList () );
339
+ .toList ();
254
340
} catch (Exception e ) {
255
341
log .error ("Unexpected exception while getting data from share coordinator" , e );
256
- return Collections . singletonList (PartitionFactory .newPartitionAllData (
342
+ return List . of (PartitionFactory .newPartitionAllData (
257
343
partition ,
258
344
-1 ,
259
345
-1 ,
@@ -264,10 +350,10 @@ ReadShareGroupStateResult readResponsesToResult(
264
350
}
265
351
})
266
352
.flatMap (List ::stream )
267
- .collect ( Collectors . toList () );
353
+ .toList ();
268
354
return new TopicData <>(topicId , partitionAllData );
269
355
})
270
- .collect ( Collectors . toList () );
356
+ .toList ();
271
357
return new ReadShareGroupStateResult .Builder ()
272
358
.setTopicsData (topicsData )
273
359
.build ();
@@ -403,10 +489,10 @@ ReadShareGroupStateSummaryResult readSummaryResponsesToResult(
403
489
partitionResult .startOffset (),
404
490
partitionResult .errorCode (),
405
491
partitionResult .errorMessage ()))
406
- .collect ( Collectors . toList () );
492
+ .toList ();
407
493
} catch (Exception e ) {
408
494
log .error ("Unexpected exception while getting data from share coordinator" , e );
409
- return Collections . singletonList (PartitionFactory .newPartitionStateSummaryData (
495
+ return List . of (PartitionFactory .newPartitionStateSummaryData (
410
496
partition ,
411
497
-1 ,
412
498
-1 ,
@@ -415,10 +501,10 @@ ReadShareGroupStateSummaryResult readSummaryResponsesToResult(
415
501
}
416
502
})
417
503
.flatMap (List ::stream )
418
- .collect ( Collectors . toList () );
504
+ .toList ();
419
505
return new TopicData <>(topicId , partitionStateErrorData );
420
506
})
421
- .collect ( Collectors . toList () );
507
+ .toList ();
422
508
return new ReadShareGroupStateSummaryResult .Builder ()
423
509
.setTopicsData (topicsData )
424
510
.build ();
@@ -464,15 +550,27 @@ DeleteShareGroupStateResult deleteResponsesToResult(
464
550
}
465
551
})
466
552
.flatMap (List ::stream )
467
- .collect ( Collectors . toList () );
553
+ .toList ();
468
554
return new TopicData <>(topicId , partitionErrorData );
469
555
})
470
- .collect ( Collectors . toList () );
556
+ .toList ();
471
557
return new DeleteShareGroupStateResult .Builder ()
472
558
.setTopicsData (topicsData )
473
559
.build ();
474
560
}
475
561
562
+ private static void validate (InitializeShareGroupStateParameters params ) {
563
+ String prefix = "Initialize share group parameters" ;
564
+ if (params == null ) {
565
+ throw new IllegalArgumentException (prefix + " cannot be null." );
566
+ }
567
+ if (params .groupTopicPartitionData () == null ) {
568
+ throw new IllegalArgumentException (prefix + " data cannot be null." );
569
+ }
570
+
571
+ validateGroupTopicPartitionData (prefix , params .groupTopicPartitionData ());
572
+ }
573
+
476
574
private static void validate (WriteShareGroupStateParameters params ) {
477
575
String prefix = "Write share group parameters" ;
478
576
if (params == null ) {
0 commit comments