@@ -196,7 +196,12 @@ func (ep *eventPoller) eventLoop() {
196
196
close (ep .offsetCommitted )
197
197
}()
198
198
199
+ doBatchDelay := false
199
200
for {
201
+ if doBatchDelay {
202
+ ep .waitForBatchTimeout ()
203
+ }
204
+
200
205
// Read messages from the DB - in an error condition we retry until success, or a closed context
201
206
events , err := ep .readPage ()
202
207
if err != nil {
@@ -205,6 +210,15 @@ func (ep *eventPoller) eventLoop() {
205
210
}
206
211
207
212
eventCount := len (events )
213
+
214
+ // We might want to wait for the batch to fill - so we delay and re-poll
215
+ if ep .conf .eventBatchTimeout > 0 && ! doBatchDelay && eventCount < ep .conf .eventBatchSize {
216
+ doBatchDelay = true
217
+ l .Tracef ("Batch delay: detected=%d, batchSize=%d batchTimeout=%s" , eventCount , ep .conf .eventBatchSize , ep .conf .eventBatchTimeout )
218
+ continue
219
+ }
220
+ doBatchDelay = false // clear any batch delay for next iteration
221
+
208
222
repoll := false
209
223
if eventCount > 0 {
210
224
// We process all the events in the page in a single database run group, and
@@ -280,6 +294,16 @@ func (ep *eventPoller) shoulderTap() {
280
294
}
281
295
}
282
296
297
+ func (ep * eventPoller ) waitForBatchTimeout () {
298
+ // For throughput optimized environments, we can set an eventBatchingTimeout to allow
299
+ // dispatching of incomplete batches at a shorter timeout than the
300
+ // long timeout between polling cycles (at the cost of some dispatch latency)
301
+ select {
302
+ case <- time .After (ep .conf .eventBatchTimeout ):
303
+ case <- ep .ctx .Done ():
304
+ }
305
+ }
306
+
283
307
func (ep * eventPoller ) waitForShoulderTapOrPollTimeout (lastEventCount int ) bool {
284
308
l := log .L (ep .ctx )
285
309
longTimeoutDuration := ep .conf .eventPollTimeout
@@ -289,21 +313,6 @@ func (ep *eventPoller) waitForShoulderTapOrPollTimeout(lastEventCount int) bool
289
313
return true
290
314
}
291
315
292
- // For throughput optimized environments, we can set an eventBatchingTimeout to allow
293
- // dispatching of incomplete batches at a shorter timeout than the
294
- // long timeout between polling cycles (at the cost of some dispatch latency)
295
- if ep .conf .eventBatchTimeout > 0 && lastEventCount > 0 {
296
- shortTimeout := time .NewTimer (ep .conf .eventBatchTimeout )
297
- select {
298
- case <- shortTimeout .C :
299
- l .Tracef ("Woken after batch timeout" )
300
- return true
301
- case <- ep .ctx .Done ():
302
- l .Debugf ("Exiting due to cancelled context" )
303
- return false
304
- }
305
- }
306
-
307
316
longTimeout := time .NewTimer (longTimeoutDuration )
308
317
select {
309
318
case <- longTimeout .C :
0 commit comments