code7 interactive

Intro to Celluloid

A framework used for concurrent object oriented programming in Ruby.

I’ve been using the wonderful Sidekiq project for a while now, and I thought it would be a good time to take a closer look at Celluloid.

What is it?

Celluloid is a concurrent object oriented programming framework for Ruby which lets you build multithreaded programs out of concurrent objects just as easily as you build sequential programs out of regular objects

In other words, Celluloid is the concurrency framework that allows Sidekiq to do its magic. The (not so) secret sauce, if you will.

Installation

We just need to install the gem:

$ gem install celluloid

*There is an issue when using JRuby 1.7.3, so you are better off with 1.7.2 or MRI 1.9.3/2.0.0*

So how does it work then?

The most popular library for concurrency in Ruby is (or used to be at least) EventMachine which is designed according to the Reactor pattern, much like Node.js and Twisted.

Celluloid on the other hand is built on the Actor model as seen in Erlang and Akka (on the JVM). The choosen design allows for some pretty nice features:

No deadlocks

Each actor is running in its own thread, and each method call is wrapped in a fiber that can be paused when calling out to other actors and than started again when the response becomes available.

Have you tried turning it off and on again?

Celluloid takes care of restarting parts of your application if/when they crash. Each actor will be rebooted to a clean state. There is Erlang-esque support for linking, supervisors, and supervision groups.

Futures

You’ll find it trivial to call methods on actors “in the background” and then retrieve the results at a later time. It is also possible to send the computation of any block to the background:

require 'celluloid'

future = Celluloid::Future.new {
  (sleep 5) * 2
}

# Do something else for a while…

puts future.value

Note: The call to future.value will block until those initial 5 seconds are up.

Supporting cast

You need to require 'celluloid/autostart' in order to automatically start support actors and configure the at_exit handler to automatically terminate all actors when halting the program.

Note: This is quite important since actors won’t be garbage collected unless you call actor.terminate (Generally not needed for test scripts though, since they tend to be short lived anyway) You can also automate this with Linking.

The ecosystem

Celluloid also has a number of subprojects that solve a few (specific) problems:

  • Celluloid::IO

    Evented I/O for Celluloid actors. (It tries to give you the best of two worlds)

  • DCell

    Distributed systems with Celluloid that talk over the 0MQ protocol.

  • Reel

    Reel is a fast, non-blocking evented web server.

Learn more about Celluloid

The project has a very good README and a Wiki where you will find the answer to most of your questions. There is also #celluloid on freenode if you want to talk to other developers using Celluloid.