36
36
import java .util .Collections ;
37
37
import java .util .List ;
38
38
import java .util .concurrent .CompletionStage ;
39
+ import java .util .concurrent .ExecutorService ;
39
40
import java .util .concurrent .Executors ;
40
41
import java .util .concurrent .ScheduledExecutorService ;
41
42
import java .util .concurrent .ScheduledFuture ;
@@ -58,10 +59,11 @@ public class BulkIngester<Context> implements AutoCloseable {
58
59
private final long maxSize ;
59
60
private final int maxOperations ;
60
61
private final @ Nullable BulkListener <Context > listener ;
62
+ private ExecutorService listenerExecutor = null ; // Created only if listener is present
61
63
private final Long flushIntervalMillis ;
62
64
63
65
private @ Nullable ScheduledFuture <?> flushTask ;
64
- private @ Nullable ScheduledExecutorService scheduler ;
66
+ private @ Nullable ScheduledExecutorService flushScheduler ;
65
67
66
68
// Current state
67
69
private List <BulkOperation > operations = new ArrayList <>();
@@ -98,6 +100,14 @@ private BulkIngester(Builder<Context> builder) {
98
100
this .maxSize = builder .bulkSize < 0 ? Long .MAX_VALUE : builder .bulkSize ;
99
101
this .maxOperations = builder .bulkOperations < 0 ? Integer .MAX_VALUE : builder .bulkOperations ;
100
102
this .listener = builder .listener ;
103
+ if (listener != null ) {
104
+ this .listenerExecutor = Executors .newSingleThreadScheduledExecutor ((r ) -> {
105
+ Thread t = Executors .defaultThreadFactory ().newThread (r );
106
+ t .setName ("listener-executor#" + ingesterId );
107
+ t .setDaemon (true );
108
+ return t ;
109
+ });
110
+ }
101
111
this .flushIntervalMillis = builder .flushIntervalMillis ;
102
112
103
113
if (flushIntervalMillis != null ) {
@@ -114,7 +124,7 @@ private BulkIngester(Builder<Context> builder) {
114
124
});
115
125
116
126
// Keep it, we'll have to close it.
117
- this .scheduler = scheduler ;
127
+ this .flushScheduler = scheduler ;
118
128
} else {
119
129
// It's not ours, we will not close it.
120
130
scheduler = builder .scheduler ;
@@ -291,7 +301,8 @@ public void flush() {
291
301
long id = sendRequestCondition .invocations ();
292
302
293
303
if (listener != null ) {
294
- listener .beforeBulk (id , request , requestContexts );
304
+ BulkRequest finalRequest = request ;
305
+ listenerExecutor .submit (() -> listener .beforeBulk (id , finalRequest , requestContexts ));
295
306
}
296
307
297
308
CompletionStage <BulkResponse > result = client .bulk (request );
@@ -317,12 +328,12 @@ public void flush() {
317
328
if (resp != null ) {
318
329
// Success
319
330
if (listener != null ) {
320
- listener .afterBulk (exec .id , exec .request , exec .contexts , resp );
331
+ listenerExecutor . submit (() -> listener .afterBulk (exec .id , exec .request , exec .contexts , resp ) );
321
332
}
322
333
} else {
323
334
// Failure
324
335
if (listener != null ) {
325
- listener .afterBulk (exec .id , exec .request , exec .contexts , thr );
336
+ listenerExecutor . submit (() -> listener .afterBulk (exec .id , exec .request , exec .contexts , thr ) );
326
337
}
327
338
}
328
339
return null ;
@@ -389,8 +400,12 @@ public void close() {
389
400
flushTask .cancel (false );
390
401
}
391
402
392
- if (scheduler != null ) {
393
- scheduler .shutdownNow ();
403
+ if (flushScheduler != null ) {
404
+ flushScheduler .shutdownNow ();
405
+ }
406
+
407
+ if (listenerExecutor != null ){
408
+ listenerExecutor .shutdownNow ();
394
409
}
395
410
}
396
411
0 commit comments