@@ -125,7 +125,7 @@ type Writer struct {
125
125
BatchBytes int64
126
126
127
127
// Time limit on how often incomplete message batches will be flushed to
128
- // kafka.
128
+ // kafka. This is ignored if SendPartialBatch is set to true
129
129
//
130
130
// The default is to flush at least every second.
131
131
BatchTimeout time.Duration
@@ -158,6 +158,13 @@ type Writer struct {
158
158
// Defaults to false.
159
159
Async bool
160
160
161
+ // SendPartialBatch forces WriteMessages to send a partial batch instead of
162
+ // blocking until a full batch is made. This is useful if you are already batching
163
+ // messages before the producer, and want to flush everything sent to WriteMessages
164
+ // without blocking while also still being synchronous. When set BatchTimeout does
165
+ // nothing.
166
+ SendPartialBatch bool
167
+
161
168
// An optional function called when the writer succeeds or fails the
162
169
// delivery of messages to a kafka partition. When writing the messages
163
170
// fails, the `err` parameter will be non-nil.
@@ -276,6 +283,13 @@ type WriterConfig struct {
276
283
// The default is to use a kafka default value of 1048576.
277
284
BatchBytes int
278
285
286
+ // SendPartialBatch forces WriteMessages to send a partial batch instead of
287
+ // blocking until a full batch is made. This is useful if you are already batching
288
+ // messages before the producer, and want to flush everything sent to WriteMessages
289
+ // without blocking while also still being synchronous. When set BatchTimeout does
290
+ // nothing.
291
+ SendPartialBatch bool
292
+
279
293
// Time limit on how often incomplete message batches will be flushed to
280
294
// kafka.
281
295
//
@@ -487,22 +501,23 @@ func NewWriter(config WriterConfig) *Writer {
487
501
}
488
502
489
503
w := & Writer {
490
- Addr : TCP (config .Brokers ... ),
491
- Topic : config .Topic ,
492
- MaxAttempts : config .MaxAttempts ,
493
- BatchSize : config .BatchSize ,
494
- Balancer : config .Balancer ,
495
- BatchBytes : int64 (config .BatchBytes ),
496
- BatchTimeout : config .BatchTimeout ,
497
- ReadTimeout : config .ReadTimeout ,
498
- WriteTimeout : config .WriteTimeout ,
499
- RequiredAcks : RequiredAcks (config .RequiredAcks ),
500
- Async : config .Async ,
501
- Logger : config .Logger ,
502
- ErrorLogger : config .ErrorLogger ,
503
- Transport : transport ,
504
- transport : transport ,
505
- writerStats : stats ,
504
+ Addr : TCP (config .Brokers ... ),
505
+ Topic : config .Topic ,
506
+ MaxAttempts : config .MaxAttempts ,
507
+ BatchSize : config .BatchSize ,
508
+ Balancer : config .Balancer ,
509
+ BatchBytes : int64 (config .BatchBytes ),
510
+ BatchTimeout : config .BatchTimeout ,
511
+ SendPartialBatch : config .SendPartialBatch ,
512
+ ReadTimeout : config .ReadTimeout ,
513
+ WriteTimeout : config .WriteTimeout ,
514
+ RequiredAcks : RequiredAcks (config .RequiredAcks ),
515
+ Async : config .Async ,
516
+ Logger : config .Logger ,
517
+ ErrorLogger : config .ErrorLogger ,
518
+ Transport : transport ,
519
+ transport : transport ,
520
+ writerStats : stats ,
506
521
}
507
522
508
523
if config .RequiredAcks == 0 {
@@ -1059,13 +1074,26 @@ func (ptw *partitionWriter) writeMessages(msgs []Message, indexes []int32) map[*
1059
1074
batches [batch ] = append (batches [batch ], i )
1060
1075
}
1061
1076
}
1077
+
1078
+ // if we are sending partial batches and the current batch is not empty send
1079
+ // the batch right away instead of lagging.
1080
+ if ptw .w .SendPartialBatch && ! ptw .currBatch .empty () {
1081
+ ptw .currBatch .trigger ()
1082
+ ptw .queue .Put (ptw .currBatch )
1083
+ ptw .currBatch = nil
1084
+ }
1085
+
1062
1086
return batches
1063
1087
}
1064
1088
1065
1089
// ptw.w can be accessed here because this is called with the lock ptw.mutex already held.
1066
1090
func (ptw * partitionWriter ) newWriteBatch () * writeBatch {
1067
1091
batch := newWriteBatch (time .Now (), ptw .w .batchTimeout ())
1068
- ptw .w .spawn (func () { ptw .awaitBatch (batch ) })
1092
+ // if we are sending partial batches we don't need to wait for a timeout
1093
+ if ! ptw .w .SendPartialBatch {
1094
+ ptw .w .spawn (func () { ptw .awaitBatch (batch ) })
1095
+ }
1096
+
1069
1097
return batch
1070
1098
}
1071
1099
@@ -1239,6 +1267,11 @@ func (b *writeBatch) full(maxSize int, maxBytes int64) bool {
1239
1267
return b .size >= maxSize || b .bytes >= maxBytes
1240
1268
}
1241
1269
1270
+ // empty returns if the batch has no data in it at all
1271
+ func (b * writeBatch ) empty () bool {
1272
+ return b == nil || b .size == 0
1273
+ }
1274
+
1242
1275
func (b * writeBatch ) trigger () {
1243
1276
close (b .ready )
1244
1277
}
0 commit comments