[rabbitmq-discuss] Does erlang client tip work with server tip?

Keith Irwin keith.irwin at gmail.com
Mon May 18 18:44:39 BST 2009


On Sun, May 17, 2009 at 11:54 PM, Matthias Radestock
<matthias at lshift.net> wrote:
> Keith,
>
> Keith Irwin wrote:
>>
>> (I'm wishing you didn't have to have rabbitmq_server even installed to
>> get an erlang_client)
>
> The Erlang client is still experimental and we have done no release
> packaging. Hence the need to work from the source repos. If there were
> packaged versions they would include the necessary parts of / dependency on
> the server code.

Yes, that makes sense.

> Regarding the repo structure, we could have both the server and the client
> depend on a rabbitmq-common source repo, but that doesn't really make any
> material difference to the effort required in building & running the Erlang
> client since we'd simply be switching one dependency - on the
> rabbitmq-server repo - for another. It would also complicate the server
> build & packaging.

How about this? Why not merge the client with the server, and bundle
it all up together (at least for release)? I think ActiveMQ works this
way. If you check out the source, it's a bunch of related projects
(and HUGE), but the release contains, among other things, a JAR file
which contains all the code, including dependent libs, the broker, the
client code, and so on.

This is great because you can just drop it into your project, use an
embedded broker for unit testing (if you want).

I could see a case for that with rabbitmq, especially if the idea of
loading code from archives ever gets more accepted in the Erlang
community. (The advantage of the archive is that you don't notice
there's a lot of code you're not using.... ;))

BTW, after I wrote my little frustrated comment, I found the long
discussion with Ed Fine in the mailing list archives. Good stuff. I
really appreciate your team's patience with us.

I'm pasting in the "test" code I wrote to experiment with the client
and server. I think it's slightly more understandable for my way of
thinking than the example at:

    http://github.com/careo/rabbitmq-erlang-client-examples/tree/master

which did not have the benefit of lib_amqp.

My example doesn't really illustrate everything (for instance I seem
to have forgotten to explicitly set the realm), but it's a nice
template for exploration.

I'm looking forward to seeing more work on lib_amqp.

Regards,

Keith

-----
-module(test).

-compile(export_all).
-include("../lib/rabbitmq-client/include/amqp_client.hrl").
-include_lib("../lib/rabbitmq-server/include/rabbit.hrl").
-include_lib("../lib/rabbitmq-server/include/rabbit_framing.hrl").

-record(conn, {conn, channel}).

-define(USER, "guest").
-define(PASS, "guest").
-define(HOST, "localhost").
-define(REALM, <<"/">>).

-define(QUEUE,         <<"app.queue">>).
-define(EXCHANGE,      <<"app.exchange">>).
-define(EXCHANGE_TYPE, <<"direct">>).
-define(ROUTING_KEY,   <<"app.route">>).

start_all() ->
    start_consumer(),
    start_producer().

stop_all() ->
    stop_producer(),
    stop_consumer().

send(Msg) ->
    case whereis(producer) of
        undefined ->
            producer_not_started;
        Pid ->
            Pid ! Msg
    end.

start_consumer() ->
    spawn(fun() -> consumer() end).

stop_consumer() ->
    case whereis(consumer) of
        undefined ->
            consumer_not_started;
        Pid ->
            Pid ! stop
    end.

start_producer() ->
    Pid = spawn(fun() -> producer() end),
    register(producer, Pid).

stop_producer() ->
    case whereis(producer) of
        undefined ->
            producer_not_started;
        Pid ->
            Pid ! stop
    end.

consumer() ->
    process_flag(trap_exit, true),
    register(consumer, self()),
    Conn = connect(?USER, ?PASS, ?HOST),
    #conn{channel=Channel} = Conn,
    lib_amqp:declare_queue(Channel, ?QUEUE),
    lib_amqp:declare_exchange(Channel, ?EXCHANGE, ?EXCHANGE_TYPE),
    lib_amqp:bind_queue(Channel, ?EXCHANGE, ?QUEUE, ?ROUTING_KEY),
    lib_amqp:subscribe(Channel, ?QUEUE, self(), ?ROUTING_KEY),

    consumer_loop(),

    lib_amqp:unsubscribe(Channel, ?ROUTING_KEY),
    lib_amqp:unbind_queue(Channel, ?EXCHANGE, ?QUEUE, ?ROUTING_KEY),
    lib_amqp:delete_queue(Channel, ?QUEUE),
    disconnect(Conn),
    consumer_stopped.

consumer_loop() ->
    receive
        {'EXIT', _Pid, Reason} ->
            io:format("consumer: exiting ~p~n", [Reason]),
            void;

        stop ->
            void;

        {Delivery, Content} ->
            io:format("consumer: delivery = ~p~n", [Delivery]),
            io:format("consumer: content = ~p~n", [Content]),
            consumer_loop();

        Msg ->
            io:format("consumer: msg = ~p~n", [Msg]),
            consumer_loop()
    end,
    ok.

producer() ->
    process_flag(trap_exit, true),
    Conn = connect(?USER, ?PASS, ?HOST),
    #conn{channel=Channel} = Conn,
    producer_loop(Channel),
    disconnect(Conn),
    producer_stopped.

producer_loop(Channel) ->
    receive
        stop ->
            void;
        Msg ->
            io:format("publisher: sending <<~p>>~n", [Msg]),
            lib_amqp:publish(Channel, ?EXCHANGE, ?ROUTING_KEY,
list_to_binary(Msg)),
            io:format("publisher: msg sent~n"),
            producer_loop(Channel)
    end.

connect(User, Pass, Host) ->
    Connection = amqp_connection:start(User, Pass, Host),
    Channel = amqp_connection:open_channel(Connection),
    #conn{conn=Connection, channel=Channel}.

disconnect(Conn) ->
    #conn{conn=Connection, channel=Channel} = Conn,
    lib_amqp:close_channel(Channel),
    lib_amqp:close_connection(Connection).


-----


>
>
> Regards,
>
> Matthias.
>




More information about the rabbitmq-discuss mailing list