Skip to content

Read a pull subscription's stream and consumer names from its consumer info - #183

Merged
lalinsky merged 1 commit into
mainfrom
fix/pull-subscribe-owned-stream-name
Oct 5, 2026
Merged

lalinsky merged 1 commit into
mainfrom
fix/pull-subscribe-owned-stream-name

Conversation

@lalinsky

@lalinsky lalinsky commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Fixes #182.

Without options.stream, pullSubscribe looks the stream name up by subject and frees it when it returns. The returned PullSubscription kept that slice, so every fetch() built its CONSUMER.MSG.NEXT subject from freed memory.

The subscription already owns the consumer info, and that carries both names as the server reports them. This removes the separate stream_name and consumer_name fields, and fetch() reads consumer_info.value.stream_name and consumer_info.value.name instead. nats.c and nats.go also take the consumer name from the info's Name.

The old consumer name chain (config.name, then config.durable_name, then the caller's durable) always resolved to the same value. nats-server sets the info's name from Durable or Name and rejects a config where the two differ, so the durable fallback was never reached.

Breaking change: PullSubscription.stream_name and .consumer_name are gone. Use consumer_info.value.stream_name and .name instead.

Testing

  • New test: pullSubscribe without .stream, then fetch(). It fails on main (the freed name produces an invalid subject) and passes with this change.
  • Full ./check.sh passes.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: lalinsky/nats.zig/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6c2e7ced-a2c7-4792-8083-67439c4f9086
📥 Commits

Reviewing files that changed from the base of the PR and between 24b135a and 72999d4.

📒 Files selected for processing (2)
  • src/jetstream.zig
  • tests/jetstream_pull_test.zig

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

pullSubscribe now sets the subscription’s stream and consumer names from the returned consumer information. A new test subscribes without .stream, publishes a matching message, and checks that fetching returns it without a batch error.

Changes

Pull subscription name assignment

Layer / File(s) Summary
Assign and verify subscription names
src/jetstream.zig, tests/jetstream_pull_test.zig
pullSubscribe stores stream and consumer names from consumer information instead of using the previous consumer-name fallback chain and locally resolved stream name. The test subscribes without .stream and checks the fetched message contents and batch error status.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 72999

The change addresses the reported pull-subscription lifetime issue, with no identified issue requiring resolution before merge.

Architecture Summary

Architecture risk: 🔵 Low · up to 72999

The change affects 2 systems.

Changed systems: src, tests

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — src (service) was modified; 1 changed file maps to changed impact.
  • observed — tests (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in src/jetstream.zig: pullSubscribe still applies pending limits before allocation, but now stores the stream and consumer names from consumer_info.value. It removes the previous consumer-name fallback chain (config.name, config.durable_name, then durable) and no longer stores the locally resolved stream_name.
  • observed — Modified behavior in tests/jetstream_pull_test.zig: Added a test that creates a stream, subscribes to its subject without specifying .stream, publishes a matching message, and asserts that fetching returns one message with the expected contents and no batch error.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Issue #182 requires pullSubscribe to keep a valid stream name after return and tests the lookup-by-subject path. PullSubscription now uses stream_name and name from the consumer_info value t…
Out of Scope Changes check ✅ Passed The source change and regression test address issue #182's name-lifetime defect. No unrelated changes appear in the whole-PR diff.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Title check ✅ Passed The title clearly summarizes the main change: read the pull subscription's stream and consumer names from consumer info.
Description check ✅ Passed The description explains the freed-memory issue, the consumer-info approach, the API change, and the test coverage. It is directly related to the changeset.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…r info

Without options.stream, pullSubscribe looks the stream name up by subject
and frees it on return, but the PullSubscription kept that slice, so
every fetch() built its request subject from freed memory.

The subscription already owns the consumer info, which carries both
names as the server reports them, so drop the separate stream_name and
consumer_name fields and have fetch() read them from there. The old
consumer name chain (config name, then durable name, then the caller's
durable) always resolved to the same value as the info's name.
@lalinsky
lalinsky force-pushed the fix/pull-subscribe-owned-stream-name branch from 72999d4 to 322c404 Compare October 5, 2026 08:22
@lalinsky lalinsky changed the title Keep a pull subscription's stream and consumer names in its consumer info Read a pull subscription's stream and consumer names from its consumer info Oct 5, 2026
@lalinsky
lalinsky merged commit fc37079 into main Oct 5, 2026
2 checks passed
@lalinsky
lalinsky deleted the fix/pull-subscribe-owned-stream-name branch October 5, 2026 08:28
lalinsky added a commit that referenced this pull request Oct 6, 2026
…r info (#183)

Without options.stream, pullSubscribe looked the stream name up by subject and freed it on return, but the PullSubscription kept that slice, so every fetch() built its request subject from freed memory.

The subscription already owns the consumer info, which carries both names as the server reports them, so the separate stream_name and consumer_name fields are gone and fetch() reads them from there.

Fixes #182.
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.

pullSubscribe keeps a freed stream name when the stream is looked up by subject

1 participant