Skip to content

refactor(subscriber): make OutboxSubscriberConfig validate itself#111

Merged
lesnik512 merged 2 commits into
mainfrom
refactor/self-validating-subscriber-config
Jun 23, 2026
Merged

refactor(subscriber): make OutboxSubscriberConfig validate itself#111
lesnik512 merged 2 commits into
mainfrom
refactor/self-validating-subscriber-config

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Summary

Subscriber-knob validation lived in subscriber/factory.py::_validate_subscriber_config, called from create_subscriber. OutboxSubscriberConfig was a bare @dataclass with no __post_init__, so constructing it directly bypassed every guard. This moves validation into OutboxSubscriberConfig.__post_init__ so every construction path — @broker.subscriber, @router.subscriber, direct construction — is validated; there's no way in that skips it. The factory shrinks to construction/wiring.

Candidate #3 from the 2026-06-23 architecture review. Change record: planning/changes/2026-06-23.03-self-validating-subscriber-config/change.md.

What changed

  • OutboxSubscriberConfig.__post_init__ → guarded super().__post_init__() (upstream SubscriberUsecaseConfig has none today, but dataclasses call only the most-derived one — the guard keeps a future upstream init running) then self._validate().
  • _validate() holds the relocated checks. Behavior preserved exactly: maps _ack_policy is EMPTY → None so checks match on the explicitly-passed policy as before (the NACK+NoRetry advisory still fires only on an explicit NACK_ON_ERROR, not on the default that resolves to it).
  • factory.py drops _validate_subscriber_config and its call.

Version-robustness wrinkle (the interesting part)

Moving validation under the dataclass-generated __init__ inserts a frame whose co_filename is the literal "<string>" between the user's call and __post_init__. The 3.13 C warnings.warn(skip_file_prefixes=...) does not skip that frame (3.14 does), so warnings mis-attributed to <string> and the FastAPI-router attribution test failed under docker/3.13.

Replaced skip_file_prefixes with _subscriber_warn, which computes stacklevel by walking out to the first non-internal frame (this package / faststream / <string>) — robust across CPython versions and across the direct vs router paths (which differ in frame count).

Verification

  • Existing validation tests are the regression guard, unchanged: test_unit.py reject/warn/no-warning cases (via @broker.subscriber), test_fastapi.py router-path attribution, test_fake.py direct-construction.
  • just test: 543 passed, 100% coverage (docker / Python 3.13). just lint-ci: clean.

🤖 Generated with Claude Code

lesnik512 and others added 2 commits June 23, 2026 18:55
Move subscriber-knob validation from factory._validate_subscriber_config into
OutboxSubscriberConfig.__post_init__ (guarded super-call + _validate) so every
construction path is guarded, not just the factory's. Behavior preserved exactly
(EMPTY->None ack_policy mapping). Replace skip_file_prefixes with a manual
stacklevel walk (_subscriber_warn) since the 3.13 C warn won't skip the dataclass
__init__ '<string>' frame now between __post_init__ and the user.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…hange

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lesnik512 lesnik512 merged commit 302a820 into main Jun 23, 2026
3 checks passed
@lesnik512 lesnik512 deleted the refactor/self-validating-subscriber-config branch June 23, 2026 16:42
lesnik512 added a commit that referenced this pull request Jun 23, 2026
Patch release: internal refactors (#109-#111, no behavior change) + richer PyPI
metadata (#108). Drop-in upgrade. Tag/publish gated on explicit go per the
release procedure.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant