@@ -22,6 +22,7 @@ import (
22
22
"github.com/pingcap/log"
23
23
"github.com/pingcap/tiflow/cdc/model"
24
24
cerror "github.com/pingcap/tiflow/pkg/errors"
25
+ "github.com/pingcap/tiflow/pkg/sink/codec/common"
25
26
"github.com/pingcap/tiflow/pkg/util"
26
27
"go.uber.org/zap"
27
28
)
@@ -76,8 +77,7 @@ type AsyncProducer interface {
76
77
// AsyncSend is the input channel for the user to write messages to that they
77
78
// wish to send.
78
79
AsyncSend (ctx context.Context , topic string ,
79
- partition int32 , key []byte , value []byte ,
80
- callback func ()) error
80
+ partition int32 , message * common.Message ) error
81
81
82
82
// AsyncRunCallback process the messages that has sent to kafka,
83
83
// and run tha attached callback. the caller should call this
@@ -220,9 +220,16 @@ func (p *saramaAsyncProducer) Close() {
220
220
}()
221
221
}
222
222
223
+ type item struct {
224
+ handleKey string
225
+ commitTs string
226
+ offset int64
227
+ }
228
+
223
229
func (p * saramaAsyncProducer ) AsyncRunCallback (
224
230
ctx context.Context ,
225
231
) error {
232
+ memo := make (map [string ]map [int32 ]item )
226
233
for {
227
234
select {
228
235
case <- ctx .Done ():
@@ -242,6 +249,29 @@ func (p *saramaAsyncProducer) AsyncRunCallback(
242
249
if callback != nil {
243
250
callback ()
244
251
}
252
+ tableID := string (ack .Headers [0 ].Value )
253
+ commitTs := string (ack .Headers [1 ].Value )
254
+ handleKey := string (ack .Headers [2 ].Value )
255
+
256
+ partitionMemo := memo [tableID ]
257
+ if partitionMemo == nil {
258
+ partitionMemo = make (map [int32 ]item )
259
+ memo [tableID ] = partitionMemo
260
+ }
261
+ previous := partitionMemo [ack .Partition ]
262
+ if ack .Offset < previous .offset {
263
+ log .Warn ("kafka async producer receive an out-of-order message response" ,
264
+ zap .String ("tableID" , tableID ), zap .Int32 ("partition" , ack .Partition ),
265
+ zap .Int64 ("oldOffset" , previous .offset ), zap .String ("oldCommitTs" , previous .commitTs ),
266
+ zap .String ("oldHandleKey" , previous .handleKey ),
267
+ zap .Int64 ("newOffset" , ack .Offset ), zap .String ("commitTs" , commitTs ),
268
+ zap .String ("handleKey" , handleKey ))
269
+ }
270
+ partitionMemo [ack .Partition ] = item {
271
+ handleKey : handleKey ,
272
+ commitTs : commitTs ,
273
+ offset : ack .Offset ,
274
+ }
245
275
}
246
276
case err := <- p .producer .Errors ():
247
277
// We should not wrap a nil pointer if the pointer
@@ -262,21 +292,24 @@ func (p *saramaAsyncProducer) AsyncRunCallback(
262
292
func (p * saramaAsyncProducer ) AsyncSend (ctx context.Context ,
263
293
topic string ,
264
294
partition int32 ,
265
- key []byte ,
266
- value []byte ,
267
- callback func (),
295
+ message * common.Message ,
268
296
) error {
297
+ headers := message .Headers ()
269
298
msg := & sarama.ProducerMessage {
270
299
Topic : topic ,
271
300
Partition : partition ,
272
- Key : sarama .StringEncoder (key ),
273
- Value : sarama .ByteEncoder (value ),
274
- Metadata : callback ,
301
+ Headers : headers ,
302
+ Key : sarama .StringEncoder (message .Key ),
303
+ Value : sarama .ByteEncoder (message .Value ),
304
+ Metadata : message .Callback ,
275
305
}
276
306
select {
277
307
case <- ctx .Done ():
278
308
return errors .Trace (ctx .Err ())
279
309
case p .producer .Input () <- msg :
280
310
}
311
+ log .Info ("async producer send message" ,
312
+ zap .Int64 ("tableID" , message .TableID ), zap .ByteString ("handleKey" , headers [2 ].Value ),
313
+ zap .Int32 ("partition" , partition ), zap .Uint64 ("commitTs" , message .Ts ))
281
314
return nil
282
315
}
0 commit comments