Skip to content

[fix][fn] Honour consumerCryptoFailureAction in the Python function runtime - #26490

Open
Zhianii wants to merge 1 commit into
apache:masterfrom
Zhianii:fix/python-consumer-crypto-failure-action
Open

[fix][fn] Honour consumerCryptoFailureAction in the Python function runtime#26490
Zhianii wants to merge 1 commit into
apache:masterfrom
Zhianii:fix/python-consumer-crypto-failure-action

Conversation

@Zhianii

@Zhianii Zhianii commented Sep 8, 2026

Copy link
Copy Markdown

Fixes #26481

Motivation

ConsumerSpec.cryptoSpec.consumerCryptoFailureAction tells the client what to do when an input message cannot be decrypted (FAIL / DISCARD / CONSUME). The Java runtime applies it in PulsarSource (cb.cryptoFailureAction(...)), but the Python runtime built its consumer_args with only the crypto key reader and never read the action: the config was accepted by pulsar-admin, reported back faithfully by functions get, and silently dropped, so the client default (FAIL) always applied and a configured DISCARD or CONSUME was ignored.

The pinned pulsar-client-python (3.13.0) already exposes crypto_failure_action on subscribe(), so no client change is needed — this closes the runtime gap only. The producer side (producerCryptoFailureAction) is still unread but has no client parameter to map onto and stays out of scope.

Modifications

  • pulsar-functions/instance/src/main/python/python_instance.py: new get_crypto_failure_action_args(consumer_conf) builds the crypto_failure_action argument as a dict splatted into subscribe(), following the get_negative_ack_args pattern:
    • no cryptoSpec configured → the argument is omitted (subscribe() validates it with _check_type, which rejects None), so every function without crypto keeps today's call shape;
    • cryptoSpec present → the action is always forwarded; the proto3 enum default (FAIL) equals the client default, so an unset action leaves behavior unchanged while DISCARD and CONSUME now reach the client;
    • the producer-only SEND value falls back to FAIL, like the existing compression mapping treats values without a consumer equivalent.

Verifying this change

This change added tests and can be verified as follows:

  • New TestConsumerCryptoFailureAction in pulsar-functions/instance/src/test/python/test_python_instance.py (same suite and mock-client style as the existing TestNegativeAckRedeliveryDelay / TestSinkProducerBatchingConfig): action omitted without a cryptoSpec, unset action keeps the client default, DISCARD / CONSUME forwarded, SEND falls back to FAIL, and the result is splattable into the subscribe() kwargs.
  • The new tests fail on unpatched master with AttributeError: 'PythonInstance' object has no attribute 'get_crypto_failure_action_args' (verified by stashing the instance change) and pass with it.
  • Full suite via pulsar-functions/instance/src/scripts/run_python_instance_tests.sh: 36 tests pass (33 in test_python_instance including the 6 new ones).

Run locally with pulsar-client 3.8.0 (same crypto_failure_action API surface as the pinned 3.13.0; CI runs the pinned version).

Does this pull request potentially affect one of the following parts:

If the box was checked, please highlight the changes

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

…untime

Forward ConsumerSpec.cryptoSpec.consumerCryptoFailureAction to the Python
client's subscribe() call, mirroring how the Java runtime applies it in
PulsarSource. The action was previously accepted by pulsar-admin, reported
back by `functions get` and then silently dropped, so the client default
(FAIL) always applied and a configured DISCARD or CONSUME was ignored.

The argument is omitted when no cryptoSpec is configured - subscribe()
validates it with _check_type, which rejects None. When a cryptoSpec is
present the action is always forwarded; the proto3 enum default (FAIL)
equals the client default, so unset behavior is unchanged. The
producer-only SEND value falls back to FAIL, like the compression mapping
treats values without a consumer equivalent.

Fixes apache#26481

Assisted-by: Claude Code
Copilot AI lite review requested due to automatic review settings September 8, 2026 02:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The consumer setup still calls get_crypto_reader(consumer_conf.cryptoSpec) unconditionally, which can trigger noisy startup errors for non-crypto consumers due to parsing an empty default cryptoKeyReaderConfig.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR fixes a Python Functions runtime parity gap by honoring ConsumerSpec.cryptoSpec.consumerCryptoFailureAction when subscribing to input topics, aligning Python behavior with the Java runtime and ensuring configured DISCARD/CONSUME actions reach the Pulsar Python client.

Changes:

  • Add get_crypto_failure_action_args(consumer_conf) and wire it into input consumer subscribe() kwargs.
  • Map proto CryptoSpec.FailureAction values to pulsar.ConsumerCryptoFailureAction, falling back to FAIL for unsupported SEND.
  • Add Python instance tests covering omitted/forwarded/fallback behavior and ensuring kwargs are splattable into subscribe().
File summaries
File Description
pulsar-functions/instance/src/main/python/python_instance.py Forwards consumer crypto failure action into subscribe() kwargs via a new helper.
pulsar-functions/instance/src/test/python/test_python_instance.py Adds unit tests validating crypto failure action forwarding and omission behavior.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pulsar-functions/instance/src/main/python/python_instance.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Python Functions] Python instance runtime silently ignores consumerCryptoFailureAction

2 participants