/apps/erel_common/src/erel_endp_amqp.erl

http://github.com/spawngrid/erel · Erlang · 89 lines · 73 code · 15 blank · 1 comment · 1 complexity · b779a0342e4338190a18f1a346031565 MD5 · raw file

  1. -module(erel_endp_amqp).
  2. -behaviour(gen_bunny).
  3. -include_lib("erel_master/include/erel_master.hrl").
  4. -include_lib("gen_bunny/include/gen_bunny.hrl").
  5. -export([init/1,
  6. handle_message/2,
  7. handle_call/3,
  8. handle_cast/2,
  9. handle_info/2,
  10. terminate/2]).
  11. -export([start_link/2]).
  12. -record(state, { handler :: atom(),
  13. hstate :: term(),
  14. vsn :: binary() }).
  15. start_link(Handler, Arg) ->
  16. [Host, Port,
  17. Username, Password,
  18. VHost] = [ begin {ok, Value} = application:get_env(Config), Value end
  19. || Config <- [amqp_host, amqp_port, amqp_username, amqp_password, amqp_vhost]],
  20. ConnectInfo = {network, Host, Port, {list_to_binary(Username), list_to_binary(Password)}, list_to_binary(VHost)},
  21. Declare = binding_to_declare(Handler:binding(Arg)),
  22. gen_server:start_link(gen_bunny, [?MODULE, ConnectInfo,
  23. Declare, [Handler, Arg]], []).
  24. init([Handler, Arg]) ->
  25. {ok, HState} = Handler:init(self(), Arg),
  26. {ok, Vsn} = application:get_key(erel_common, vsn),
  27. {ok, #state{ handler = Handler, hstate = HState, vsn = list_to_binary(Vsn) }}.
  28. handle_message(#amqp_msg{ props = Props,
  29. payload = Message},
  30. #state{ vsn = Vsn,
  31. handler = Handler,
  32. hstate = HState } = State) ->
  33. case lists:keyfind(<<"erel_common_version">>, 1, Props#'P_basic'.headers) of
  34. {_, _, Vsn} ->
  35. {ok, HState1} = Handler:handle_message(binary_to_term(Message), HState),
  36. {noreply, State#state{ hstate = HState1 }};
  37. {_, _, OtherVsn} ->
  38. ?ERROR("Incompatible erl_commons version (~p) of the message received (message_id=~p), ignoring", [OtherVsn, Props#'P_basic'.message_id]),
  39. {noreply, State}
  40. end.
  41. handle_call(Call, From, #state{ handler = Handler, hstate = HState } = State) ->
  42. case Handler:handle_call(Call, From, HState) of
  43. {reply, Reply, HState1} ->
  44. {reply, Reply, State#state{ hstate = HState1 }};
  45. {noreply, HState1} ->
  46. {noreply, State#state{ hstate = HState1 }}
  47. end.
  48. handle_cast({cast, Exchange, Topic, Message}, #state{ vsn = Vsn } = State) ->
  49. BasicPublish = #'basic.publish'{
  50. exchange = atom_to_binary(Exchange, latin1),
  51. routing_key = list_to_binary(Topic)
  52. },
  53. Self = self(),
  54. #amqp_msg{} = Msg0 = bunny_util:new_message(term_to_binary(Message)),
  55. Msg = Msg0#amqp_msg{ props = #'P_basic'{ headers = [{<<"erel_common_version">>, longstr, Vsn}] }},
  56. spawn_link(fun () ->
  57. amqp_channel:cast(gen_bunny:get_channel(Self), BasicPublish,
  58. Msg) end),
  59. {noreply, State};
  60. handle_cast(Msg, #state{ handler = Handler, hstate = HState} = State) ->
  61. {noreply, HState1} = Handler:handle_cast(Msg, HState),
  62. {noreply, State#state{ hstate = HState1 }}.
  63. handle_info(Info, State) ->
  64. {noreply, State}.
  65. terminate(Reason, _State) ->
  66. ok.
  67. %%
  68. binding_to_declare(#endp_binding{ name = Name, type = Type, topic = Topic}) ->
  69. {#'exchange.declare'{exchange = atom_to_binary(Name, latin1), type =
  70. binding_type_to_type(Type), auto_delete = true }, #'queue.declare'{ queue = <<>>, auto_delete = true, exclusive = true}, list_to_binary(Topic)}.
  71. binding_type_to_type(topic) ->
  72. <<"topic">>;
  73. binding_type_to_type(direct) ->
  74. <<"direct">>.