@@ -520,6 +520,10 @@ type ReaderConfig struct {
520
520
// This flag is being added to retain backwards-compatibility, so it will be
521
521
// removed in a future version of kafka-go.
522
522
OffsetOutOfRangeError bool
523
+
524
+ // EnablePartitionEoF will notify the reader by throwing PartitionEoF when
525
+ // it reaches the end of partition.
526
+ EnablePartitionEoF bool
523
527
}
524
528
525
529
// Validate method validates ReaderConfig properties.
@@ -1194,23 +1198,24 @@ func (r *Reader) start(offsetsByPartition map[topicPartition]int64) {
1194
1198
defer join .Done ()
1195
1199
1196
1200
(& reader {
1197
- dialer : r .config .Dialer ,
1198
- logger : r .config .Logger ,
1199
- errorLogger : r .config .ErrorLogger ,
1200
- brokers : r .config .Brokers ,
1201
- topic : key .topic ,
1202
- partition : int (key .partition ),
1203
- minBytes : r .config .MinBytes ,
1204
- maxBytes : r .config .MaxBytes ,
1205
- maxWait : r .config .MaxWait ,
1206
- readBatchTimeout : r .config .ReadBatchTimeout ,
1207
- backoffDelayMin : r .config .ReadBackoffMin ,
1208
- backoffDelayMax : r .config .ReadBackoffMax ,
1209
- version : r .version ,
1210
- msgs : r .msgs ,
1211
- stats : r .stats ,
1212
- isolationLevel : r .config .IsolationLevel ,
1213
- maxAttempts : r .config .MaxAttempts ,
1201
+ dialer : r .config .Dialer ,
1202
+ logger : r .config .Logger ,
1203
+ errorLogger : r .config .ErrorLogger ,
1204
+ brokers : r .config .Brokers ,
1205
+ topic : key .topic ,
1206
+ partition : int (key .partition ),
1207
+ minBytes : r .config .MinBytes ,
1208
+ maxBytes : r .config .MaxBytes ,
1209
+ maxWait : r .config .MaxWait ,
1210
+ readBatchTimeout : r .config .ReadBatchTimeout ,
1211
+ backoffDelayMin : r .config .ReadBackoffMin ,
1212
+ backoffDelayMax : r .config .ReadBackoffMax ,
1213
+ version : r .version ,
1214
+ msgs : r .msgs ,
1215
+ stats : r .stats ,
1216
+ isolationLevel : r .config .IsolationLevel ,
1217
+ maxAttempts : r .config .MaxAttempts ,
1218
+ enablePartitionEoF : r .config .EnablePartitionEoF ,
1214
1219
1215
1220
// backwards-compatibility flags
1216
1221
offsetOutOfRangeError : r .config .OffsetOutOfRangeError ,
@@ -1223,23 +1228,24 @@ func (r *Reader) start(offsetsByPartition map[topicPartition]int64) {
1223
1228
// used as a way to asynchronously fetch messages while the main program reads
1224
1229
// them using the high level reader API.
1225
1230
type reader struct {
1226
- dialer * Dialer
1227
- logger Logger
1228
- errorLogger Logger
1229
- brokers []string
1230
- topic string
1231
- partition int
1232
- minBytes int
1233
- maxBytes int
1234
- maxWait time.Duration
1235
- readBatchTimeout time.Duration
1236
- backoffDelayMin time.Duration
1237
- backoffDelayMax time.Duration
1238
- version int64
1239
- msgs chan <- readerMessage
1240
- stats * readerStats
1241
- isolationLevel IsolationLevel
1242
- maxAttempts int
1231
+ dialer * Dialer
1232
+ logger Logger
1233
+ errorLogger Logger
1234
+ brokers []string
1235
+ topic string
1236
+ partition int
1237
+ minBytes int
1238
+ maxBytes int
1239
+ maxWait time.Duration
1240
+ readBatchTimeout time.Duration
1241
+ backoffDelayMin time.Duration
1242
+ backoffDelayMax time.Duration
1243
+ version int64
1244
+ msgs chan <- readerMessage
1245
+ stats * readerStats
1246
+ isolationLevel IsolationLevel
1247
+ maxAttempts int
1248
+ enablePartitionEoF bool
1243
1249
1244
1250
offsetOutOfRangeError bool
1245
1251
}
@@ -1376,6 +1382,10 @@ func (r *reader) run(ctx context.Context, offset int64) {
1376
1382
})
1377
1383
r .stats .timeouts .observe (1 )
1378
1384
continue
1385
+ case errors .Is (err , PartitionEoF ):
1386
+ errcount = 0
1387
+ r .sendError (ctx , err )
1388
+ continue
1379
1389
1380
1390
case errors .Is (err , OffsetOutOfRange ):
1381
1391
first , last , err := r .readOffsets (conn )
@@ -1506,6 +1516,7 @@ func (r *reader) read(ctx context.Context, offset int64, conn *Conn) (int64, err
1506
1516
var err error
1507
1517
var size int64
1508
1518
var bytes int64
1519
+ var newOffset = offset
1509
1520
1510
1521
for {
1511
1522
conn .SetReadDeadline (time .Now ().Add (r .readBatchTimeout ))
@@ -1524,9 +1535,9 @@ func (r *reader) read(ctx context.Context, offset int64, conn *Conn) (int64, err
1524
1535
break
1525
1536
}
1526
1537
1527
- offset = msg .Offset + 1
1528
- r .stats .offset .observe (offset )
1529
- r .stats .lag .observe (highWaterMark - offset )
1538
+ newOffset = msg .Offset + 1
1539
+ r .stats .offset .observe (newOffset )
1540
+ r .stats .lag .observe (highWaterMark - newOffset )
1530
1541
1531
1542
size ++
1532
1543
bytes += n
@@ -1538,7 +1549,11 @@ func (r *reader) read(ctx context.Context, offset int64, conn *Conn) (int64, err
1538
1549
r .stats .readTime .observeDuration (t2 .Sub (t1 ))
1539
1550
r .stats .fetchSize .observe (size )
1540
1551
r .stats .fetchBytes .observe (bytes )
1541
- return offset , err
1552
+
1553
+ if r .enablePartitionEoF && newOffset == highWaterMark && newOffset > offset {
1554
+ return offset , PartitionEoF
1555
+ }
1556
+ return newOffset , err
1542
1557
}
1543
1558
1544
1559
func (r * reader ) readOffsets (conn * Conn ) (first , last int64 , err error ) {
0 commit comments