Showing posts with label RabbitMQ. Show all posts
Showing posts with label RabbitMQ. Show all posts

Sunday, April 18, 2010

Interacting with RabbitMQ via F# and Symbiote

Last week, I showed how easy it is to talk to CouchDB with F# and Symbiote.  In this post, I'll show how you can start interacting with RabbitMQ by adding an additional dozen or so lines of code.

RabbitMQ:
RabbitMQ is a complete and highly reliable enterprise messaging system based on the emerging AMQP standard. It is licensed under the open source Mozilla Public License and has a platform-neutral distribution, plus platform-specific packages and bundles for easy installation. (http://www.rabbitmq.com/)
Symbiote:

Symbiote is a set of libraries that reduce the radius of comprehension by providing simplified APIs "...to some of the better open source libraries available" as well as "...a way to centralize the configuration [and] dependency injection..." of said libraries (Robson, A., Symbiote).   

For those of you who haven't played with RabbitMQ and/or Symbiote, I strongly recommend checking them out!

Code:

Here's the code with the CouchDB interaction functionality as well as the RabbitMQ publish/subscribe functionality.

A couple of things to note about this sample:
1. CouchDB and RabbitMQ must be installed and running on the local machine.
2. Since Symbiote is under heavy development, the CouchDB related code has changed slightly from the example provided last week.
module Progam

open System
open Symbiote.Core
open Symbiote.Relax
open Symbiote.Daemon
open Symbiote.Jackalope
open Symbiote.Jackalope.Impl

type PersonCouchDocument =
    val id : string
    val mutable name : string
    val mutable address : string
    inherit DefaultCouchDocument 
        new (id, name, address) = 
            {id = id; name = name; address = address} then base.DocumentId <- id
        member x.Name
            with get () = x.name
        member x.Address
            with get () = x.address

type HandleMessage() =
    interface IMessageHandler<PersonCouchDocument> with
        member x.Process (message:PersonCouchDocument, messageDelivery:IMessageDelivery) =
            Console.WriteLine("Processing message for person {0}.", message.name)
            messageDelivery.Acknowledge()

type DemoService = 
    val couchServer : ICouchServer
    val bus : IBus
    new(couchServer, bus) as this = 
        {couchServer = couchServer; bus = bus} then this.Initialize()
    member public x.Initialize () =
        x.bus.AddEndPoint(fun x -> 
            x.Exchange("SymbioteDemo", ExchangeType.fanout).QueueName("SymbioteDemo")
                .Durable().PersistentDelivery() |> ignore)
    interface IDaemon with
        member x.Start () =
            do Console.WriteLine("The service has started")
            x.bus.Subscribe("SymbioteDemo", null)
            let document = new PersonCouchDocument("123456", "John Doe", "123 Main")
            x.couchServer.Repository.Save(document)
            x.bus.Send("SymbioteDemo", document)
            let documentRetrieved = 
                x.couchServer.Repository.Get<PersonCouchDocument>(document.DocumentId);
            do Console.WriteLine(
                "The document with name {0} and address {1} was retrieved successfully", 
                documentRetrieved.Name, documentRetrieved.Address)
            do x.couchServer.DeleteDatabase<PersonCouchDocument>()
        member x.Stop () =
            do Console.WriteLine("The service has stopped")

do Assimilate
    .Core()
    .Daemon(fun x -> (x.Name("FSharpDemoService")
                                    .DisplayName("An FSharp Demo Service")
                                    .Description("An FSharp Demo Service")
                                    .Arguments([||]) |> ignore))
    .Relax(fun x -> x.Server("localhost") |> ignore) 
    .Jackalope(fun x -> x.AddServer(fun s -> s.Address("localhost").AMQP08() |> ignore) |> ignore)
    .RunDaemon() 


Conclusion:

As mentioned previously, with the help of Symbiote it only takes a dozen or so additional lines of code to add support for RabbitMQ to our previous example.  The complete source for this solution can be found at http://github.com/dmohl/Symbiote-Jackalope-Example.


Wednesday, March 31, 2010

Setting Up Querly

In my last post, I introduced Querly (a simple CouchDB query engine).  In this post, I provide the steps for setting up Querly.

1. Start by installing CouchDB.  A windows installer is available on the couchdb wiki.
2. Next, install Erlang.  I'm using version R13B04.
3. Now, install RabbitMQ, available at http://www.rabbitmq.com/download.html.  Note: Querly has built in support for subscription to a RabbitMQ queue.  This allows updates to be received without having to reload an entire database from CouchDB.  This is not required for utilization of the basic functionality of Querly; however, it is required for auto update support and for all of the tests to run successfully.
4. Launch CouchDB and RabbitMQ.
5. Retrieve Querly from http://github.com/dmohl/Querly.
6. Edit make.bat in the Querly directory and change the Erlang directories appropriately.
7. Launch Querly by executing the batch file in the main directory.  This will run all of the tests.

In a future post, I'll talk about how to get started with Querly.

 

Sunday, February 21, 2010

Setting Up Alice and Wonderland on Windows

At Sommet, we have been exploring several interesting technologies, some of which include Erlang and RabbitMQ.  RabbitMQ (An open source enterprise messaging system, built in Erlang, and based on the AMQP standard) has thus far turned out to be most of what we could ask for in a messaging solution.  One small concern with using RabbitMQ in the enterprise is that it does not come out of the box with a user interface.  While this is not a complete deal breaker, it makes the case for RabbitMQ a little bit harder to accept.  Luckily, others have also seen this need and have been working on solutions.  One such solution is called Alice (A monitoring and REST interface for RabbitMQ) and Wonderland  (The front-end for Alice).

This week, Jim Cowart (@ifandelse) and I set out to get Alice and Wonderland up and running on our development machines/environments.  While there is documentation on the Alice GitHub site for getting started on Linux, we were unable to find anything on getting things going on windows (we have a need for both).  After several rounds of trial and error, we came up with a Windows batch file that takes you from start to finish.  Enjoy.     

Setting Up Alice and Wonderland on Windows

Installation Prerequisites:

- Erlang
- Git
- RabbitMQ

Setup Prerequisites:

- RabbitMQ must be running

An End-To-End Batch File:

The following lines can be placed in a Windows batch file such as emake.bat. It will retrieve Alice and Wonderland from GitHub, make/configure the projects, and finally launch Alice. A few notes: A compressed copy of the complete batch file is available here.  ERLANG_HOME and GIT_HOME can be set directly in this batch file or setup as environment variables. Once everything has been built/setup for the first time, Alice can be started with the following line:

"C:\Program Files\erl5.7.4\bin\erl.exe" -pa ./ebin -pa ./deps/*/ebin -sname alice -s reloader -boot alice

Finally, once this original batch file runs and Alice starts successfully, navigate to http://127.0.0.1:9999 to see the Wonderland UI.


REM Make sure that this batch file is in the desired parent directory for Alice

if "%ERLANG_HOME%"=="" (
    set ERLANG_HOME=C:\Program Files\erl5.7.4
)

if "%GIT_HOME%"=="" (
    set GIT_HOME=C:\Program Files\Git
)

REM Git Alice GitHub
"%GIT_HOME%\bin\git.exe" clone git://github.com/auser/alice.git
REM Move to the Alice directory
cd alice
REM copy the Emakefile file from the alice directory to the mochiweb directory
copy .\emakefile deps\mochiweb
REM Make Alice
"%ERLANG_HOME%\bin\erl.exe" -make
REM Create the boot file.
"%ERLANG_HOME%\bin\erl.exe" -pa ebin -noshell -run make_boot write_scripts alice
REM Move to the deps\mochiweb directory
cd .\deps\mochiweb
REM Make Mochiweb
"%ERLANG_HOME%\bin\erl.exe" -make
REM Copy the Mochiweb beams to the alice ebin directory
copy .\ebin\*.* ..\..\ebin
REM Move back to the alice directory
cd ..\..
REM Make the alice\web directory
mkdir web
REM Move to the web directory
cd web
REM Git Wonderland
"%GIT_HOME%\bin\git.exe" clone git://github.com/auser/wonderland.git
REM Move back to the alice directory
cd ..
REM Start Alice
"%ERLANG_HOME%\bin\erl.exe" -pa ./ebin -pa ./deps/*/ebin -sname alice -s reloader -boot alice
pause