Repository navigation
[Go Functions] deadLetterTopic and maxMessageRetries are carried into the instance but never applied #26406
Description
Master Issue: #26404
Search before reporting
- I searched in the issues and found nothing similar. [Python Functions] Python instance runtime silently ignores deadLetterTopic / maxMessageRetries #26397 is the same defect in the Python runtime, with a fix open at [fix][fn] Support deadLetterTopic and maxMessageRetries for Python functions #26400; this is the Go counterpart.
Motivation
The Go runtime builds RetryDetails into its own FunctionDetails from the instance configuration:
// pulsar-function-go/pf/instanceConf.go:115-118
RetryDetails: &pb.RetryDetails{
MaxMessageRetries: cfg.MaxMessageRetries,
DeadLetterTopic: cfg.DeadLetterTopic,
},and then never reads it. git grep -in "DLQ\|DeadLetter\|MaxRedeliver" -- 'pulsar-function-go/pf/*.go' returns only that one construction site. No pulsar.DLQPolicy is ever built, and setupConsumer passes no DLQ options to Subscribe.
The configuration is therefore accepted end to end and has no effect: a Go function created with --dead-letter-topic and --max-message-retries reports both back from functions get, and messages that fail repeatedly are redelivered forever instead of being routed to the dead letter topic. The Java runtime applies them in PulsarSource (guarded by hasRetryDetails() in JavaInstanceRunnable).
Populating the field and never consuming it is worse than not carrying it at all — it makes the gap invisible to anyone reading the instance configuration.
Solution
Build a pulsar.DLQPolicy from funcDetails.RetryDetails in setupConsumer and pass it in the ConsumerOptions. The Go client supports this:
type DLQPolicy struct {
MaxDeliveries uint32
DeadLetterTopic string
RetryLetterTopic string
InitialSubscriptionName string
}Points worth settling, mirroring the ones raised on the Python fix in #26400:
- Presence check.
RetryDetailsis a message field, sofuncDetails.GetRetryDetails() != nilis the equivalent of Java'shasRetryDetails(). A scalar check onMaxMessageRetriescannot distinguish unset from zero. maxMessageRetriesof 0. Java accepts>= 0. Whether the Go client'sMaxDeliveriesaccepts 0 meaningfully should be confirmed rather than assumed — the Python client rejects a redelivery count below 1, which is why [fix][fn] Support deadLetterTopic and maxMessageRetries for Python functions #26400 attaches no policy in that case and warns.- Empty
deadLetterTopic. Java sets the topic only when non-empty, leaving the client to derive<topic>-<subscription>-DLQ. Passing an empty string through would override that with an invalid name. - Subscription type. A dead letter policy only takes effect on Shared or KeyShared. That interacts with the sibling issue [Go Functions] retainOrdering and retainKeyOrdering are ignored, so key ordering is silently not preserved #26405, where
retainOrderingcurrently selects nothing andretainKeyOrderingis ignored; whichever lands second should handle the combination rather than silently producing an ineffective policy.
Alternatives
Removing the RetryDetails construction so the configuration is visibly absent would be honest but strictly less useful — the fields are already plumbed, and the Go client supports the feature.
Anything else?
Verified against origin/master.
Are you willing to submit a PR?
- I'm willing to submit a PR!
Activity