Skip to content

Commit ed7915d

Browse files
committed
feat: Implemented chunking on the consumer side
1 parent 3a90ce5 commit ed7915d

9 files changed

Lines changed: 817 additions & 153 deletions

pulsar/consumer.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,17 @@ type ConsumerOptions struct {
189189
// error information of the Ack method only contains errors that may occur in the Go SDK's own processing.
190190
// Default: false
191191
AckWithResponse bool
192+
193+
// MaxPendingChunkedMessage sets the maximum pending chunked messages. (default: 100)
194+
MaxPendingChunkedMessage int
195+
196+
// ExpireTimeOfIncompleteChunk sets the expiry time of discarding incomplete chunked message.
197+
// The timing accuracy is 100ms level and the default value is 60 * 1000 millis
198+
ExpireTimeOfIncompleteChunk time.Duration
199+
200+
// AutoAckIncompleteChunk sets whether consumer auto acknowledges incomplete chunked message when it should
201+
// be removed (e.g.the chunked message pending queue is full). (default: false)
202+
AutoAckIncompleteChunk bool
192203
}
193204

194205
// Consumer is an interface that abstracts behavior of Pulsar's consumer

pulsar/consumer_impl.go

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ import (
3636
const defaultNackRedeliveryDelay = 1 * time.Minute
3737

3838
type acker interface {
39-
AckID(id trackingMessageID) error
40-
NackID(id trackingMessageID)
39+
AckID(id MessageID) error
40+
NackID(id MessageID)
4141
NackMsg(msg Message)
4242
}
4343

@@ -91,6 +91,15 @@ func newConsumer(client *client, options ConsumerOptions) (Consumer, error) {
9191
}
9292
}
9393

94+
if options.MaxPendingChunkedMessage == 0 {
95+
options.MaxPendingChunkedMessage = 100
96+
}
97+
98+
// the minimum timer interval is 100ms
99+
if options.ExpireTimeOfIncompleteChunk < 100*time.Millisecond {
100+
options.ExpireTimeOfIncompleteChunk = time.Minute
101+
}
102+
94103
if options.NackBackoffPolicy == nil && options.EnableDefaultNackBackoffPolicy {
95104
options.NackBackoffPolicy = new(defaultNackBackoffPolicy)
96105
}
@@ -342,27 +351,30 @@ func (c *consumer) internalTopicSubscribeToPartitions() error {
342351
nackRedeliveryDelay = c.options.NackRedeliveryDelay
343352
}
344353
opts := &partitionConsumerOpts{
345-
topic: pt,
346-
consumerName: c.consumerName,
347-
subscription: c.options.SubscriptionName,
348-
subscriptionType: c.options.Type,
349-
subscriptionInitPos: c.options.SubscriptionInitialPosition,
350-
partitionIdx: idx,
351-
receiverQueueSize: receiverQueueSize,
352-
nackRedeliveryDelay: nackRedeliveryDelay,
353-
nackBackoffPolicy: c.options.NackBackoffPolicy,
354-
metadata: metadata,
355-
subProperties: subProperties,
356-
replicateSubscriptionState: c.options.ReplicateSubscriptionState,
357-
startMessageID: trackingMessageID{},
358-
subscriptionMode: durable,
359-
readCompacted: c.options.ReadCompacted,
360-
interceptors: c.options.Interceptors,
361-
maxReconnectToBroker: c.options.MaxReconnectToBroker,
362-
keySharedPolicy: c.options.KeySharedPolicy,
363-
schema: c.options.Schema,
364-
decryption: c.options.Decryption,
365-
ackWithResponse: c.options.AckWithResponse,
354+
topic: pt,
355+
consumerName: c.consumerName,
356+
subscription: c.options.SubscriptionName,
357+
subscriptionType: c.options.Type,
358+
subscriptionInitPos: c.options.SubscriptionInitialPosition,
359+
partitionIdx: idx,
360+
receiverQueueSize: receiverQueueSize,
361+
nackRedeliveryDelay: nackRedeliveryDelay,
362+
nackBackoffPolicy: c.options.NackBackoffPolicy,
363+
metadata: metadata,
364+
subProperties: subProperties,
365+
replicateSubscriptionState: c.options.ReplicateSubscriptionState,
366+
startMessageID: trackingMessageID{},
367+
subscriptionMode: durable,
368+
readCompacted: c.options.ReadCompacted,
369+
interceptors: c.options.Interceptors,
370+
maxReconnectToBroker: c.options.MaxReconnectToBroker,
371+
keySharedPolicy: c.options.KeySharedPolicy,
372+
schema: c.options.Schema,
373+
decryption: c.options.Decryption,
374+
ackWithResponse: c.options.AckWithResponse,
375+
maxPendingChunkedMessage: c.options.MaxPendingChunkedMessage,
376+
expireTimeOfIncompleteChunk: c.options.ExpireTimeOfIncompleteChunk,
377+
autoAckIncompleteChunk: c.options.AutoAckIncompleteChunk,
366378
}
367379
cons, err := newPartitionConsumer(c, c.client, opts, c.messageCh, c.dlq, c.metrics)
368380
ch <- ConsumerError{
@@ -453,16 +465,13 @@ func (c *consumer) Ack(msg Message) error {
453465

454466
// AckID the consumption of a single message, identified by its MessageID
455467
func (c *consumer) AckID(msgID MessageID) error {
456-
mid, ok := c.messageID(msgID)
457-
if !ok {
458-
return errors.New("failed to convert trackingMessageID")
459-
}
460-
461-
if mid.consumer != nil {
462-
return mid.Ack()
468+
if msgID.PartitionIdx() < 0 || int(msgID.PartitionIdx()) >= len(c.consumers) {
469+
c.log.Errorf("invalid partition index %d expected a partition between [0-%d]",
470+
msgID.PartitionIdx(), len(c.consumers))
471+
return errors.New("invalid partition index")
463472
}
464473

465-
return c.consumers[mid.partitionIdx].AckID(mid)
474+
return c.consumers[msgID.PartitionIdx()].AckID(msgID)
466475
}
467476

468477
// ReconsumeLater mark a message for redelivery after custom delay

0 commit comments

Comments
 (0)