Skip to content

fix(rabbit): validate cached declarations - #3089

Open
lxingy3 wants to merge 3 commits into
ag2ai:mainfrom
lxingy3:fix/2034-rabbit-declaration-cache
Open

lxingy3 wants to merge 3 commits into
ag2ai:mainfrom
lxingy3:fix/2034-rabbit-declaration-cache

Conversation

@lxingy3

@lxingy3 lxingy3 commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

Cache RabbitMQ queues and exchanges by name. Reusing an active declaration with different broker settings now raises SetupError before another broker call; passive lookups reuse a cached object without treating their placeholder settings as a declaration. An active declaration made after a passive lookup replaces that cache entry. Binding-only settings are not part of declaration identity.

Using the object name as the cache key also allows nested declaration arguments that cannot be hashed. The tests use separate RabbitQueue and RabbitExchange instances when checking changed settings.

Addresses #2034. The issue's original 0.6.0 branch is no longer available, so this PR targets main.

Validation

  • Focused declaration tests: 23 passed
  • Ruff format and lint, Pyright, Pyrefly, Bandit, and codespell passed
  • Mypy passed for faststream and the changed declaration test file; the full run also passed when excluding an unrelated Windows-only SIGKILL test file

@lxingy3
lxingy3 force-pushed the fix/2034-rabbit-declaration-cache branch from 919599a to 8a96faf Compare September 2, 2026 00:44
@lxingy3

lxingy3 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

The only failing job is test-confluent-real. It passed on the previous head, while the current head changes only RabbitMQ code and tests. This attempt passed 274 of 277 Confluent tests; the three failures are existing docs tests that exhausted their flaky reruns after consumer-group LeaveGroupRequest timeouts.

The RabbitMQ real tests and every other completed job passed. GitHub does not allow me to rerun the upstream job from the fork because that action requires repository admin permission. Could a maintainer rerun the failed job?

Comment thread faststream/rabbit/helpers/declarer.py Outdated
Comment thread faststream/rabbit/helpers/declarer.py Outdated
Comment thread faststream/rabbit/helpers/declarer.py Outdated
Comment thread faststream/rabbit/helpers/declarer.py Outdated
Comment thread faststream/rabbit/helpers/declarer.py Outdated
Comment thread faststream/rabbit/helpers/declarer.py Outdated
Comment thread faststream/rabbit/helpers/declarer.py Outdated
Comment thread faststream/rabbit/helpers/declarer.py Outdated
Comment thread faststream/rabbit/helpers/declarer.py Outdated
@lxingy3
lxingy3 force-pushed the fix/2034-rabbit-declaration-cache branch from 8a96faf to 99d490c Compare September 4, 2026 22:42
@lxingy3

lxingy3 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the review in 99d490c2:

  • Inlined the one-use declaration helpers and clarified the cache validation names.
  • Kept one deep copy per declaration only as the nested cache snapshot needed to detect later schema mutations; removed the redundant copy passed to aio-pika.
  • Switched the diagnostics to RabbitQueue.__name__ / RabbitExchange.__name__ and kept the mutation regressions focused on cache validation.

The updated CI is fully green. @IvanKirpichnikov, could you take another look?

Comment thread faststream/rabbit/helpers/declarer.py Outdated
"durable": queue.durable,
"exclusive": queue.exclusive,
"auto_delete": queue.auto_delete,
"arguments": deepcopy(queue.arguments or {}),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why deepcopy?

Comment thread faststream/rabbit/helpers/declarer.py Outdated
"type": exchange.type,
"durable": exchange.durable,
"auto_delete": exchange.auto_delete,
"arguments": deepcopy(exchange.arguments or {}),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why deepcopy?

Comment on lines +361 to +376
@pytest.mark.rabbit()
@pytest.mark.asyncio()
async def test_disconnect_clears_declaration_settings(
async_mock: AsyncMock,
queue: str,
) -> None:
declarer = RabbitDeclarerImpl(FakeChannelManager(async_mock))
await declarer.declare_queue(RabbitQueue(queue))

with pytest.raises(SetupError):
await declarer.declare_queue(RabbitQueue(queue, durable=False))

declarer.disconnect()
await declarer.declare_queue(RabbitQueue(queue, durable=False))

assert async_mock.declare_queue.await_count == 2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What is the purpose of the test?

Comment on lines +353 to +356
arguments["custom"].append("second")

with pytest.raises(SetupError, match=r"RabbitExchange .*arguments"):
await declarer.declare_exchange(schema)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It’s better to create a new RabbitExchange object instead of mutating schema.

Comment on lines +331 to +337
schema = RabbitQueue(queue, arguments=arguments)
await declarer.declare_queue(schema)

arguments["custom"].append("second")

with pytest.raises(SetupError, match=r"RabbitQueue .*arguments"):
await declarer.declare_queue(schema)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It’s better to create a new RabbitQueue object instead of mutating schema.

@lxingy3
lxingy3 force-pushed the fix/2034-rabbit-declaration-cache branch from 99d490c to 8298145 Compare September 27, 2026 03:48
@lxingy3

lxingy3 commented Sep 27, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I removed both deep copies and changed the nested-argument tests to use separate RabbitQueue and RabbitExchange objects, as suggested. The disconnect test checks that cached declaration settings are cleared: after a disconnect, declaring the same name with different options should not raise a stale SetupError. The branch is now on current main; focused tests and local static checks passed, and the new CI run is in progress.

This branch has not been deployed

No deployments
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.

2 participants