Skip to content

Conversation

@mergify
Copy link

@mergify mergify bot commented Aug 20, 2025

Why

Topic permissions depend on an exchange, in addition to a user and a vhost like other permissions.

This fixes a bug where an exchange imported after a topic permission that depends on it caused the following crash when Khepri is used:

{case_clause,{error,{khepri,mismatching_node, #{node_name => <<"exchange_name">>, node_props => #{payload_version => 1}, node_path => [rabbitmq,vhosts,<<"/">>,exchanges, <<"exchange_name">>], condition => {if_node_exists,false}, node_is_target => true}}}}

The crash comes from the fact that the exchange code expect to either create the tree node in Khepri for that exchange, or there is an existing tree node holding an exchange tree node. Here, there was a tree node created implicitly when the topic permission was stored, but that tree node didn't have an exchange record (because the exchange was not imported yet).

How

We simply swap the import of topic permissions and exchanges.

In addition to that, we also relax the conditions used to write a new exchange record in Khepri. This is not strictly required, but this makes the code more robust (see the second commit in the branch).


This is an automatic backport of pull request #14407 done by Mergify.

[Why] Topic permissions depend on an exchange, in addition to a user and a vhost like other permissions. This fixes a bug where an exchange imported after a topic permission that depends on it caused the following crash when Khepri is used: {case_clause,{error,{khepri,mismatching_node, #{node_name => <<"exchange_name">>, node_props => #{payload_version => 1}, node_path => [rabbitmq,vhosts,<<"/">>,exchanges, <<"exchange_name">>], condition => {if_node_exists,false}, node_is_target => true}}}} The crash comes from the fact that the exchange code expect to either create the tree node in Khepri for that exchange, or there is an existing tree node holding an exchange tree node. Here, there was a tree node created implicitly when the topic permission was stored, but that tree node didn't have an exchange record (because the exchange was not imported yet). [How] We simply swap the import of topic permissions and exchanges. (cherry picked from commit 92c572e)
…hepri [Why] When the module wanted to create an exchange in Khepri, it used `rabbit_khepri:create/2` which ensures that the tree node doesn't exist before. If the tree node exists, it expects it to contain an exchange record which is returned to the caller, indicating an exchange with that name already exists. However, there are several other resources stored under an exchange tree node, like bindings and topic permissions. In particular, during a definitions import, topic permissions used to be imported before exchanges. This caused a crash because the write of the topic permission automatically created a parent tree node for the exchange it dpends on, but without an exchange record obviously (see previous commit). [How] As an addition improvement to the previous commit, we change the conditions: instead of matching on the fact the tree node doesn't exist, the module also accepts that the tree node exists but has no payload. Under any of these conditions, the exchange is considered to be new and written to Khepri. (cherry picked from commit 5bcbfad)
@dumbbell dumbbell marked this pull request as draft August 20, 2025 12:13
@dumbbell dumbbell added this to the 4.1.4 milestone Aug 20, 2025
@dumbbell dumbbell marked this pull request as ready for review August 20, 2025 12:44
@dumbbell dumbbell merged commit 31733d8 into v4.1.x Aug 20, 2025
546 of 547 checks passed
@dumbbell dumbbell deleted the mergify/bp/v4.1.x/pr-14407 branch August 20, 2025 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant