feat(pulsaradmin): add PIP-401 batchingConfig to ProducerConfig - #1530
Merged
freeznet merged 1 commit intoAug 25, 2026
Merged
Conversation
utils.ProducerConfig could not express producer batching, so no Go caller could set it on a Function, Source or Sink even though the broker accepts it and the Java admin API has carried it since PIP-401. Add a BatchingConfig type mirroring the Java model and reference it from ProducerConfig. Since ProducerConfig is shared by FunctionConfig, SourceConfig and SinkConfig, this covers all three resource types. Two details worth noting: - Enabled is serialized unconditionally, with no omitempty. The broker reads it as a primitive boolean with no fallback - BatchingUtils.convert() calls setEnabled(config.isEnabled()) - so a payload omitting the field can leave batching off rather than defaulting to on. NewBatchingConfig() returns the same defaults the broker applies when no configuration is present, so tuning a single field does not silently disable batching through Go's zero value. - The numeric fields are *int, mirroring the boxed Integer fields in the Java model, so an unset field is distinguishable from a configured one. Note the broker applies each only when present and greater than zero, so zero is not a way to switch a limit off; this is documented on BatchingMaxPublishDelayMs, where zero reads back as the 10ms default rather than removing the linger. batchingConfig requires Apache Pulsar 4.1.0 or later. It is omitted when nil, so requests to earlier brokers are unchanged. Verified against Pulsar 4.1.0: a function created with a batchingConfig round-trips enabled, batchBuilder and batchingMaxMessages, with unset fields decoding as nil rather than zero. Master Issue: apache#1528 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 20, 2026
freeznet
approved these changes
Aug 21, 2026
4 tasks
freeznet
pushed a commit
to david-streamlio/terraform-provider-pulsar
that referenced
this pull request
Aug 26, 2026
pulsar_source exposes its producer configuration as top-level attributes - max_pending_messages, max_pending_messages_across_partitions, use_thread_local_producers, batch_builder and compression_type. pulsar_function exposes none of it: utils.FunctionConfig carries the same ProducerConfig field, but marshalFunctionConfig never populated it, so it was always sent nil and a function's output producer was stuck on defaults. Add the same five attributes, using the names pulsar_source already uses so the two resources read the same way, and populate FunctionConfig's ProducerConfig from them. The producer config is omitted entirely when none of the attributes are set, so requests for functions that do not configure a producer are unchanged. This is the part of streamnative#220 that needs nothing upstream. The batching_config block is deliberately not included: PIP-401's batchingConfig is absent from utils.ProducerConfig in the pinned admin client - tracked in apache/pulsar-client-go#1528, with a fix open at apache/pulsar-client-go#1530 - and it exists only on Pulsar 4.1.0 and later, whereas the acceptance tests here run against 4.0.3. Master Issue: streamnative#220 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Master Issue: #1528
Motivation
utils.ProducerConfigcannot express producer batching, so no Go caller can set it on a Function, Source or Sink — even though the broker accepts it and the Java admin API has carried it since PIP-401 (apache/pulsar#23860).ProducerConfigis a typed struct serialized to JSON with no passthrough field, so there is no workaround: the key simply cannot be put on the wire from Go.pulsar-admin functions create --producer-config '{"batchingConfig":{...}}'works today; the equivalent is impossible frompulsarctlor the Terraform provider.The user-visible symptom is publish latency.
batchingMaxPublishDelayMsdefaults to 10ms, and below roughly one message per 10ms per instance every message pays the full linger while each batch still contains exactly one message. Tuning or disabling that is whatbatchingConfigexists for.This is the remaining half of #1528; #1529 covered
receiverQueueSizeand does not touchProducerConfig.Modifications
Add a
BatchingConfigtype mirroring the Java model and reference it fromProducerConfig. SinceProducerConfigis shared byFunctionConfig,SourceConfigandSinkConfig, this covers all three resource types in one change.Two decisions worth a reviewer's attention, both driven by how the broker consumes the payload rather than by Go style:
Enabledis serialized unconditionally — noomitempty.BatchingUtils.convert()does:That reads a primitive
booleanwith no null fallback, so a payload that omitsenabledrisks arriving asfalseand disabling batching rather than defaulting to on. Emitting it always makes the caller's intent explicit on the wire.The corollary is that Go's zero value is a hazard:
&BatchingConfig{BatchingMaxMessages: ptr(100)}would serializeenabled: falseand disable batching while appearing to cap batch size.NewBatchingConfig()returns the same defaults the broker applies when no configuration is present (enabled: true,batchingMaxPublishDelayMs: 10, matchingBatchingUtils.convertFromSpec(null)), so the common "tune one field" path is safe. This follows the existingNewAutoSubscriptionCreationOverride()precedent in this package.The numeric fields are
*int, mirroring the boxedIntegerfields in the Java model, so "not configured" stays distinguishable from a configured value.I deliberately did not reuse the
SetX()/HasX()+ custom-marshaller idiom from #1529. That idiom exists there to avoid changing an existing exported field's type and breaking callers;BatchingConfigis a new type with no such constraint, so plain nullable pointers map the Java semantics directly with less machinery. Happy to switch to the #1529 idiom for consistency if you would rather the two match.Note that the broker applies each numeric field only when it is present and greater than zero, so zero is not a way to switch a limit off — unlike
receiverQueueSizein #1529, where zero is meaningful. This is documented onBatchingMaxPublishDelayMs, where zero reads back as the 10ms default rather than removing the linger.batchingConfigrequires Apache Pulsar 4.1.0 or later — the field does not exist onProducerConfigin the 4.0.x line. The field is omitted when nil, so requests to earlier brokers are byte-identical to before this change.Verifying this change
This change added tests and can be verified as follows:
batching_config_test.gocovering the constructor defaults, JSON serialization across zero-value / disabled / defaults / fully-populated cases, a round trip, and that an absent field decodes as nil while an explicit zero does not.ProducerConfigtests assertingbatchingConfigis absent from the payload when nil — so requests to pre-4.1.0 brokers are unchanged — and present and correctly decoded when set.--producer-config '{"compressionType":"ZSTD","batchingConfig":{"enabled":true,"batchingMaxPublishDelayMs":0,"batchingMaxMessages":100,"batchBuilder":"KEY_BASED"}}'decodes through these types withEnabled=true,BatchBuilder="KEY_BASED",BatchingMaxMessages=100, andBatchingMaxBytes/RoundRobinRouterBatchingPartitionSwitchFrequencyasnilrather than0.batchingMaxPublishDelayMs: 10for the zero that was sent.Does this pull request potentially affect one of the following parts:
Additive only: a new
BatchingConfigtype, a newNewBatchingConfig()constructor, a newDefaultBatchingMaxPublishDelayMsconstant, and a new nil-by-default field onProducerConfig. No existing field changes type or serialization.