Also on twitter ( twitter.com/nutrun )

Distributed programming with Jabber and EventMachine

Jabber and its underlying protocol XMPP are typically associated with instant messaging applications, although the breadth and flexibility of the technology allows for implementations that can span further from traditional online chatting.

ejabberd is a fault tolerant and clusterable Jabber/XMPP server written in Erlang and presents an interesting option as a simple, lightweight and scalable message transport for distributed applications.

EventMachine is a simple and fast library for lightweight concurrency in Ruby. Its use mainly involves, but is not limited to, spawning lightweight processes whose execution can be programatically scheduled, easy and fast socket abstractions and an implementation of the Deferrable pattern as introduced by the Twisted event-driven Python networking engine.

When a Ruby class includes the EventMachine::Deferrable module, it is provided with the ability to accept arbitrary callbacks and errbacks that will get executed when its deferred status changes, in particular when it is set to either :succeeded or :failed. Let’s look at a deferrable Worker class which performs a potentially long running operation.

class Worker
  include EM::Deferrable

  def heavy_lifting
    30.times do |i|
      puts "Lifted #{i}"
      sleep 0.1
    end
    set_deferred_status :succeeded
  end
end

Inside an EventMachine loop, we can add callbacks to a Worker instance and dispatch the expensive operation to a separate thread, or an evented process. The program’s execution will continue, with any callbacks attached to Worker executed once its deferred status is set.

EM.run do
  worker = Worker.new
  worker.callback {p "done!"}
  Thread.new {worker.heavy_lifting; EM.stop}
  puts "resuming remaining program operations"
end

Now, let’s look at combining Worker with Jabber to trigger long running jobs. For Jabber server duties, I am using ejabberd on an old laptop running Debian, but there’s no reason why a mass online Jabber service like Google Talk could not be used for playing around with the example. Also, I’m using the xmpp4r-simple Ruby library, which is a wrapper around xmpp4r.

jabber = Jabber::Simple.new("bot@thrash", "password")
at_exit{jabber.status(:away, "jabot down")}

EM.run do
  EM::PeriodicTimer.new(1) do
    jabber.received_messages do |message|
      case message.body
      when "exit" : EM.stop
      when "lift" :
        EM.spawn do
          worker = Worker.new
          worker.callback {jabber.deliver(message.from, "Done lifting")}
          worker.heavy_lifting
        end.notify
        jabber.deliver(message.from, "Scheduled heavy job...")
      else jabber.deliver(message.from, "Dunno how to #{message.body}")
      end
    end
  end
end

Inside an EventMachine loop, we check for new messages every second. The program understands two commands, exit and lift. The first quits the EventMachine loop and ultimately terminates the program’s execution. When lift is received, we instantiate a new Worker inside a spawned process and add a callback so that the Worker will notify the command issuer when the job has completed. Worth noting is the use of notify to schedule the spawned process. notify returns immediately making work dispatch non-blocking – upon issuing a lift command twice, a “Scheduled heavy job…” message will be sent to the job issuer twice before the first job completes.

I use Adium to send commands to the program – an interesting way of remote controlling or interacting with applications. Of course, the real interest lies in using the setup under discussion for inter-app communication. With multicast options, presence discovery, node status updates and more, there is lot to explore in terms of distributed application development, if simple and lightweight are two keywords to be found on the highest ranks of your list.

21 Responses to “Distributed programming with Jabber and EventMachine”

  1. Pages tagged "online" Says:

    [...] tagged onlineOwn a Wordpress blog? Make monetization easier with the WP Affiliate Pro plugin. Distributed programming with Jabber and EventMachi… saved by 1 others     PEACendwarWORLDpeace bookmarked on 05/04/08 | [...]

  2. roScripts - Webmaster resources and websites Says:

    nutrun » Blog Archive » Distributed programming with Jabber and EventMachine…

    nutrun » Blog Archive » Distributed programming with Jabber and EventMachine…

  3. Kit Plummer Says:

    Great thinking.

    I’ve spent some time looking at a similar solution using ActiveMQ/STOMP and the Ruby STOMP library. I also have working a similar solution using XMPP from within a Rails-based suite of applications using BackgroundRB. My thought is that Rails could serve as a service container mechanism with XMPP as an Enterprise Service Bus mechanism. However, I never really got around to the idea of a registry and discovery model. But, after reading your post I can see how the Presence capability could work.

    We’d done our work using OpenFire, an Open Source Jabber server written in Java. Not the lightest weight server for sure, but very easy to use and has a sweet plugin architecture.

  4. dude Says:

    The code here is very bothersome to read.

  5. Kit Plummer Says:

    Ha. Strangely, I just ended up on another one of your blog posts: http://nutrun.com/weblog/jms-with-jruby-and-activemq/

    So, it looks like you and I are thinking about many of the same things. Curious, have you added OSGi to your list?

    Something I starting to look at is the potential for packaging up Ruby “services” within JRuby/OSGi for deployment to servers like ServiceMix, OpenESB or just GlassFish and Tomcat

  6. links for 2008-05-06 « Bloggitation Says:

    [...] Distributed programming with Jabber and EventMachine (tags: ruby jabber programming) [...]

  7. links for 2008-05-06 Says:

    [...] nutrun » Blog Archive » Distributed programming with Jabber and EventMachine (tags: distributed erlang jabber performance programming ruby xmpp) [...]

  8. Joe Says:

    I do hope XMPP doesn’t become the event system of distributed storage. I wrote an instant messenger on it once and the protocol is just plain bad. Lots of elements called ‘a’ and ‘x’ all with different namespaces.
    It’s about time we had a new IM protocol, maybe based around ATOM.

  9. links for 2008-05-06 | Libin Pan Says:

    [...] nutrun » Blog Archive » Distributed programming with Jabber and EventMachine Distributed programming with Jabber and EventMachine (tags: development distributed events jabber ruby xmpp) [...]

  10. Web 2.0 Announcer Says:

    Distributed programming with Jabber and EventMachine…

    [...]Jabber and its underlying protocol XMPP are typically associated with instant messaging applications, although the breadth and flexibility of the technology allows for implementations that can span further from traditional online chatting.[...]…

  11. Web 2.0 Announcer Says:

    nutrun » Blog Archive » Distributed programming with Jabber and EventMachine…

    [...][...]…

  12. The Punch Barrel / Distributed programming with Jabber and EventMachine Says:

    [...] nutrun » Blog Archive » Distributed programming with Jabber and EventMachine [...]

  13. links for 2008-05-07 at Topper’s Blog Says:

    [...] nutrun » Blog Archive » Distributed programming with Jabber and EventMachine (tags: jabber eventmachine delayed processing method rails) [...]

  14. Nome do Jogo » Artigo » Rails Podcast Brasil - Epis Says:

    [...] Distributed programming with Jabber and EventMachine [...]

  15. An EventMachine Tutorial | 20bits Says:

    [...] also an article about using EventMachine with Jabber to create a Jabber Bot that’s worth [...]

  16. Eric Allam Says:

    I like the idea, and I think this could be a good fit for the Jabber PubSub spec (http://www.xmpp.org/extensions/xep-0060.html). This way multiple application could “subscribe” to a node where other applications can pass events, and those applications can process those events however they need to. This event model could be easily distributed, and if you used ejabberd as your jabber server, you could have a pretty powerful and fault tolerant way to perform distributed programming tasks. Very very interesting.

  17. Dan Says:

    I haven’t used the Jabber protocol as a message queue before like this, but my only concern is does it allow some sort of way to ensure that each message has guaranteed one-time delivery? If I sent out a message to the “cloud” I would want to make sure every message is either processed by a worker or held in the queue until a worker is available. My concern is that if workers were backed up, or (worst case) completely down, I would want to ensure no messages were lost.

  18. Messaging and Ruby (Part 1) - The Big Picture | Open Sourcery Says:

    [...] since I’ve read Distributed programming with Jabber and EventMachine I’ve been baffled by the almost endless possibilities this offers. I’ve shared this [...]

  19. Preston Lee Says:

    Journeta (http://journeta.rubyforge.org/) is also very useful for ad-hoc networks where there may not be a central server, as is required with a Jabber-based solution.

  20. Stevie Clifton Says:

    Thanks for posting this, George. I used some of your ideas here for a simple jabber broadcast daemon.
    http://dev.animoto.com/articles/jabbercaster-broadcast-jabber-and-xmpp-messages

  21. Markus Jais on software development » 9 websites about Ruby/EventMachine Says:

    [...] Distributed programming with Jabber and EventMachine. A short example using EventMachine and Jabber. [...]

Leave a Reply