Master Issue: #26404
Search before reporting
Motivation
The Go runtime picks the subscription type from one field only:
// pulsar-function-go/pf/instance.go:307-310
func (gi *goInstance) setupConsumer() (chan pulsar.ConsumerMessage, error) {
subscriptionType := pulsar.Shared
if int32(gi.context.instanceConf.funcDetails.Source.SubscriptionType) == pb.SubscriptionType_value["FAILOVER"] {
subscriptionType = pulsar.Failover
}
RetainOrdering and RetainKeyOrdering appear nowhere in pulsar-function-go outside the generated pb package — git grep -i "RetainOrdering\|RetainKeyOrdering" -- 'pulsar-function-go/**/*.go' returns nothing once pb/ is excluded.
The Python runtime applies both:
# pulsar-functions/instance/src/main/python/python_instance.py:147-151
if self.instance_config.function_details.retainOrdering or \
self.instance_config.function_details.processingGuarantees == Function_pb2.ProcessingGuarantees.Value("EFFECTIVELY_ONCE"):
mode = pulsar._pulsar.ConsumerType.Failover
elif self.instance_config.function_details.retainKeyOrdering:
mode = pulsar._pulsar.ConsumerType.KeyShared
So this is accepted and has no effect:
pulsar-admin functions create --go fn --retain-key-ordering ...
functions get reports retainKeyOrdering: true, and the function runs on a Shared subscription. Messages sharing a key are distributed across instances and processed concurrently, which is precisely the guarantee the flag exists to provide. --retain-ordering is ignored the same way, so a function that should run on Failover runs Shared.
This is the one gap in #26404 with a live correctness consequence rather than a missing capability: the function does not fail, it produces subtly wrong results, and nothing in the configuration, the admin output or the logs indicates why.
Solution
Apply both fields when selecting the subscription type, matching Python and the Java runtime:
subscriptionType := pulsar.Shared
if int32(funcDetails.Source.SubscriptionType) == pb.SubscriptionType_value["FAILOVER"] {
subscriptionType = pulsar.Failover
}
if funcDetails.RetainOrdering {
subscriptionType = pulsar.Failover
} else if funcDetails.RetainKeyOrdering {
subscriptionType = pulsar.KeyShared
}
Two points for review:
- Precedence. Python applies
retainOrdering (and EFFECTIVELY_ONCE) before retainKeyOrdering, so ordering wins when both are set. Worth matching deliberately rather than by accident.
EFFECTIVELY_ONCE needs no arm here. The Go runtime already panics on it at pulsar-function-go/pf/instanceConf.go:137, so it cannot reach this code.
Also worth considering: a dead letter policy requires a Shared or KeyShared subscription, so this interacts with the sibling issue on retryDetails. Whichever lands second should check the combination.
Alternatives
Refusing at startup — panicking the way EFFECTIVELY_ONCE does — would at least make the gap visible, and is strictly better than the current silence. But KeyShared and Failover are both available in the Go client, so there is no reason not to implement the behaviour.
Anything else?
Verified against origin/master.
Are you willing to submit a PR?
Master Issue: #26404
Search before reporting
Motivation
The Go runtime picks the subscription type from one field only:
RetainOrderingandRetainKeyOrderingappear nowhere inpulsar-function-gooutside the generatedpbpackage —git grep -i "RetainOrdering\|RetainKeyOrdering" -- 'pulsar-function-go/**/*.go'returns nothing oncepb/is excluded.The Python runtime applies both:
So this is accepted and has no effect:
functions getreportsretainKeyOrdering: true, and the function runs on a Shared subscription. Messages sharing a key are distributed across instances and processed concurrently, which is precisely the guarantee the flag exists to provide.--retain-orderingis ignored the same way, so a function that should run on Failover runs Shared.This is the one gap in #26404 with a live correctness consequence rather than a missing capability: the function does not fail, it produces subtly wrong results, and nothing in the configuration, the admin output or the logs indicates why.
Solution
Apply both fields when selecting the subscription type, matching Python and the Java runtime:
Two points for review:
retainOrdering(andEFFECTIVELY_ONCE) beforeretainKeyOrdering, so ordering wins when both are set. Worth matching deliberately rather than by accident.EFFECTIVELY_ONCEneeds no arm here. The Go runtime already panics on it atpulsar-function-go/pf/instanceConf.go:137, so it cannot reach this code.Also worth considering: a dead letter policy requires a Shared or KeyShared subscription, so this interacts with the sibling issue on
retryDetails. Whichever lands second should check the combination.Alternatives
Refusing at startup — panicking the way
EFFECTIVELY_ONCEdoes — would at least make the gap visible, and is strictly better than the current silence. ButKeySharedandFailoverare both available in the Go client, so there is no reason not to implement the behaviour.Anything else?
Verified against
origin/master.Are you willing to submit a PR?