@@ -82,7 +82,8 @@ private static class RequestExecution<Context> {
82
82
public final List <Context > contexts ;
83
83
public final CompletionStage <BulkResponse > futureResponse ;
84
84
85
- RequestExecution (long id , BulkRequest request , List <Context > contexts , CompletionStage <BulkResponse > futureResponse ) {
85
+ RequestExecution (long id , BulkRequest request , List <Context > contexts ,
86
+ CompletionStage <BulkResponse > futureResponse ) {
86
87
this .id = id ;
87
88
this .request = request ;
88
89
this .contexts = contexts ;
@@ -99,27 +100,30 @@ private BulkIngester(Builder<Context> builder) {
99
100
this .maxOperations = builder .bulkOperations < 0 ? Integer .MAX_VALUE : builder .bulkOperations ;
100
101
this .listener = builder .listener ;
101
102
this .flushIntervalMillis = builder .flushIntervalMillis ;
102
-
103
- if (flushIntervalMillis != null ) {
104
- long flushInterval = flushIntervalMillis ;
105
103
106
- // Create a scheduler if needed
107
- ScheduledExecutorService scheduler ;
104
+ // Create a scheduler if needed
105
+ ScheduledExecutorService scheduler = null ;
106
+ if (flushIntervalMillis != null || listener != null ) {
107
+
108
108
if (builder .scheduler == null ) {
109
- scheduler = Executors .newSingleThreadScheduledExecutor ( (r ) -> {
110
- Thread t = Executors .defaultThreadFactory ().newThread (r );
111
- t .setName ("bulk-ingester-flusher #" + ingesterId );
112
- t .setDaemon (true );
113
- return t ;
114
- });
109
+ scheduler = Executors .newScheduledThreadPool ( maxRequests + 1 , (r ) -> {
110
+ Thread t = Executors .defaultThreadFactory ().newThread (r );
111
+ t .setName ("bulk-ingester-executor #" + ingesterId );
112
+ t .setDaemon (true );
113
+ return t ;
114
+ });
115
115
116
116
// Keep it, we'll have to close it.
117
117
this .scheduler = scheduler ;
118
118
} else {
119
119
// It's not ours, we will not close it.
120
120
scheduler = builder .scheduler ;
121
121
}
122
-
122
+
123
+ }
124
+
125
+ if (flushIntervalMillis != null ) {
126
+ long flushInterval = flushIntervalMillis ;
123
127
this .flushTask = scheduler .scheduleWithFixedDelay (
124
128
this ::failsafeFlush ,
125
129
flushInterval , flushInterval ,
@@ -221,7 +225,7 @@ public long requestCount() {
221
225
* @see Builder#maxConcurrentRequests
222
226
*/
223
227
public long requestContentionsCount () {
224
- return this .sendRequestCondition .contentions ();
228
+ return this .sendRequestCondition .contentions ();
225
229
}
226
230
227
231
//----- Predicates for the condition variables
@@ -265,7 +269,7 @@ private BulkRequest.Builder newRequest() {
265
269
private void failsafeFlush () {
266
270
try {
267
271
flush ();
268
- } catch (Throwable thr ) {
272
+ } catch (Throwable thr ) {
269
273
// Log the error and continue
270
274
logger .error ("Error in background flush" , thr );
271
275
}
@@ -280,7 +284,8 @@ public void flush() {
280
284
() -> {
281
285
// Build the request
282
286
BulkRequest request = newRequest ().operations (operations ).build ();
283
- List <Context > requestContexts = contexts == null ? Collections .nCopies (operations .size (), null ) : contexts ;
287
+ List <Context > requestContexts = contexts == null ? Collections .nCopies (operations .size (),
288
+ null ) : contexts ;
284
289
285
290
// Prepare for next round
286
291
operations = new ArrayList <>();
@@ -291,7 +296,8 @@ public void flush() {
291
296
long id = sendRequestCondition .invocations ();
292
297
293
298
if (listener != null ) {
294
- listener .beforeBulk (id , request , requestContexts );
299
+ BulkRequest finalRequest = request ;
300
+ scheduler .submit (() -> listener .beforeBulk (id , finalRequest , requestContexts ));
295
301
}
296
302
297
303
CompletionStage <BulkResponse > result = client .bulk (request );
@@ -303,7 +309,7 @@ public void flush() {
303
309
}
304
310
305
311
return new RequestExecution <>(id , request , requestContexts , result );
306
- });
312
+ });
307
313
308
314
if (exec != null ) {
309
315
// A request was actually sent
@@ -317,12 +323,14 @@ public void flush() {
317
323
if (resp != null ) {
318
324
// Success
319
325
if (listener != null ) {
320
- listener .afterBulk (exec .id , exec .request , exec .contexts , resp );
326
+ scheduler .submit (() -> listener .afterBulk (exec .id , exec .request ,
327
+ exec .contexts , resp ));
321
328
}
322
329
} else {
323
330
// Failure
324
331
if (listener != null ) {
325
- listener .afterBulk (exec .id , exec .request , exec .contexts , thr );
332
+ scheduler .submit (() -> listener .afterBulk (exec .id , exec .request ,
333
+ exec .contexts , thr ));
326
334
}
327
335
}
328
336
return null ;
@@ -383,7 +391,8 @@ public void close() {
383
391
// Flush buffered operations
384
392
flush ();
385
393
// and wait for all requests to be completed
386
- closeCondition .whenReady (() -> {});
394
+ closeCondition .whenReady (() -> {
395
+ });
387
396
388
397
if (flushTask != null ) {
389
398
flushTask .cancel (false );
@@ -404,7 +413,7 @@ public static class Builder<Context> implements ObjectBuilder<BulkIngester<Conte
404
413
private ElasticsearchAsyncClient client ;
405
414
private BulkRequest globalSettings ;
406
415
private int bulkOperations = 1000 ;
407
- private long bulkSize = 5 * 1024 * 1024 ;
416
+ private long bulkSize = 5 * 1024 * 1024 ;
408
417
private int maxConcurrentRequests = 1 ;
409
418
private Long flushIntervalMillis ;
410
419
private BulkListener <Context > listener ;
@@ -424,7 +433,8 @@ public Builder<Context> client(ElasticsearchClient client) {
424
433
}
425
434
426
435
/**
427
- * Sets when to flush a new bulk request based on the number of operations currently added. Defaults to
436
+ * Sets when to flush a new bulk request based on the number of operations currently added.
437
+ * Defaults to
428
438
* {@code 1000}. Can be set to {@code -1} to disable it.
429
439
*
430
440
* @throws IllegalArgumentException if less than -1.
@@ -438,7 +448,8 @@ public Builder<Context> maxOperations(int count) {
438
448
}
439
449
440
450
/**
441
- * Sets when to flush a new bulk request based on the size in bytes of actions currently added. A request is sent
451
+ * Sets when to flush a new bulk request based on the size in bytes of actions currently added. A
452
+ * request is sent
442
453
* once that size has been exceeded. Defaults to 5 megabytes. Can be set to {@code -1} to disable it.
443
454
*
444
455
* @throws IllegalArgumentException if less than -1.
@@ -452,7 +463,8 @@ public Builder<Context> maxSize(long bytes) {
452
463
}
453
464
454
465
/**
455
- * Sets the number of concurrent requests allowed to be executed. A value of 1 means 1 request is allowed to be executed
466
+ * Sets the number of concurrent requests allowed to be executed. A value of 1 means 1 request is
467
+ * allowed to be executed
456
468
* while accumulating new bulk requests. Defaults to {@code 1}.
457
469
*
458
470
* @throws IllegalArgumentException if less than 1.
@@ -468,7 +480,8 @@ public Builder<Context> maxConcurrentRequests(int max) {
468
480
/**
469
481
* Sets an interval flushing any bulk actions pending if the interval passes. Defaults to not set.
470
482
* <p>
471
- * Flushing is still subject to the maximum number of requests set with {@link #maxConcurrentRequests}.
483
+ * Flushing is still subject to the maximum number of requests set with
484
+ * {@link #maxConcurrentRequests}.
472
485
*
473
486
* @throws IllegalArgumentException if not a positive duration.
474
487
*/
@@ -483,13 +496,21 @@ public Builder<Context> flushInterval(long value, TimeUnit unit) {
483
496
/**
484
497
* Sets an interval flushing any bulk actions pending if the interval passes. Defaults to not set.
485
498
* <p>
486
- * Flushing is still subject to the maximum number of requests set with {@link #maxConcurrentRequests}.
499
+ * Flushing is still subject to the maximum number of requests set with
500
+ * {@link #maxConcurrentRequests}.
501
+ * Deprecated in favor of {@link #scheduler}
487
502
*/
503
+ @ Deprecated
488
504
public Builder <Context > flushInterval (long value , TimeUnit unit , ScheduledExecutorService scheduler ) {
489
505
this .scheduler = scheduler ;
490
506
return flushInterval (value , unit );
491
507
}
492
508
509
+ public Builder <Context > scheduler (ScheduledExecutorService scheduler ) {
510
+ this .scheduler = scheduler ;
511
+ return this ;
512
+ }
513
+
493
514
public Builder <Context > listener (BulkListener <Context > listener ) {
494
515
this .listener = listener ;
495
516
return this ;
@@ -518,7 +539,8 @@ public Builder<Context> globalSettings(Function<BulkRequest.Builder, BulkRequest
518
539
@ Override
519
540
public BulkIngester <Context > build () {
520
541
// Ensure some chunking criteria are defined
521
- boolean hasCriteria = this .bulkOperations >= 0 || this .bulkSize >= 0 || this .flushIntervalMillis != null ;
542
+ boolean hasCriteria =
543
+ this .bulkOperations >= 0 || this .bulkSize >= 0 || this .flushIntervalMillis != null ;
522
544
523
545
if (!hasCriteria ) {
524
546
throw new IllegalStateException ("No bulk operation chunking criteria have been set." );
0 commit comments