summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Fedotov <hairyhum@gmail.com>2019-02-14 15:48:07 -0500
committerDaniil Fedotov <hairyhum@gmail.com>2019-02-14 15:51:29 -0500
commit13985a751795184c75b150a9dfbca48becdcdfd6 (patch)
tree5d29d95f912d6213bdc803059ad3971ee3f29dd5
parentbdf3cfb76205fef2b6208b17cc81f3b86d8b1db6 (diff)
downloadrabbitmq-server-git-13985a751795184c75b150a9dfbca48becdcdfd6.tar.gz
Do not fail on bind/unbind operations if the binding records are inconsistent.
If there is a record for the rabbit_durable_route table but no record for rabbit_route table, the binding operations should still proceed to create/remove bindings. This will allow the clients to fix data inconsistency that server did not fix during recovery. [#163952284]
-rw-r--r--src/rabbit_binding.erl28
-rw-r--r--src/rabbit_channel.erl5
2 files changed, 13 insertions, 20 deletions
diff --git a/src/rabbit_binding.erl b/src/rabbit_binding.erl
index ab3bc6c819..daa0d1b817 100644
--- a/src/rabbit_binding.erl
+++ b/src/rabbit_binding.erl
@@ -49,7 +49,6 @@
-type bind_ok_or_error() :: 'ok' | bind_errors() |
rabbit_types:error(
- 'binding_not_found' |
{'binding_invalid', string(), [any()]}).
-type bind_res() :: bind_ok_or_error() | rabbit_misc:thunk(bind_ok_or_error()).
-type inner_fun() ::
@@ -178,19 +177,15 @@ add(Src, Dst, B, ActingUser) ->
lock_resource(Src),
lock_resource(Dst),
[SrcDurable, DstDurable] = [durable(E) || E <- [Src, Dst]],
- case (SrcDurable andalso DstDurable andalso
- mnesia:read({rabbit_durable_route, B}) =/= []) of
- false -> ok = sync_route(#route{binding = B}, SrcDurable, DstDurable,
- fun mnesia:write/3),
- x_callback(transaction, Src, add_binding, B),
- Serial = rabbit_exchange:serial(Src),
- fun () ->
- x_callback(Serial, Src, add_binding, B),
- ok = rabbit_event:notify(
- binding_created,
- info(B) ++ [{user_who_performed_action, ActingUser}])
- end;
- true -> rabbit_misc:const({error, binding_not_found})
+ ok = sync_route(#route{binding = B}, SrcDurable, DstDurable,
+ fun mnesia:write/3),
+ x_callback(transaction, Src, add_binding, B),
+ Serial = rabbit_exchange:serial(Src),
+ fun () ->
+ x_callback(Serial, Src, add_binding, B),
+ ok = rabbit_event:notify(
+ binding_created,
+ info(B) ++ [{user_who_performed_action, ActingUser}])
end.
-spec remove(rabbit_types:binding()) -> bind_res().
@@ -208,7 +203,10 @@ remove(Binding, InnerFun, ActingUser) ->
case mnesia:read(rabbit_route, B, write) of
[] -> case mnesia:read(rabbit_durable_route, B, write) of
[] -> rabbit_misc:const(ok);
- _ -> rabbit_misc:const({error, binding_not_found})
+ %% We still delete the binding and run
+ %% all post-delete functions if there is only
+ %% a durable route in the database
+ _ -> remove(Src, Dst, B, ActingUser)
end;
_ -> case InnerFun(Src, Dst) of
ok -> remove(Src, Dst, B, ActingUser);
diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl
index 036aa9a60c..ada037925b 100644
--- a/src/rabbit_channel.erl
+++ b/src/rabbit_channel.erl
@@ -1845,11 +1845,6 @@ binding_action(Fun, SourceNameBin0, DestinationType, DestinationNameBin0,
rabbit_amqqueue:not_found(Name);
{error, {resources_missing, [{absent, Q, Reason} | _]}} ->
rabbit_amqqueue:absent(Q, Reason);
- {error, binding_not_found} ->
- rabbit_misc:protocol_error(
- not_found, "no binding ~s between ~s and ~s",
- [RoutingKey, rabbit_misc:rs(ExchangeName),
- rabbit_misc:rs(DestinationName)]);
{error, {binding_invalid, Fmt, Args}} ->
rabbit_misc:protocol_error(precondition_failed, Fmt, Args);
{error, #amqp_error{} = Error} ->