blog.absurd:li - press play on tape
April 21th 2011
Tagged zeromq, cod, ruby, beanstalk, pipes, zack, rpc, unix

Introducing Cod

Cod is a library for interprocess communication that I am working on in the wee hours these days. My goal is to make things really simple and to overlay sockets, pipes and other means of communication with an interface that is easy to remember.

Cod is open source software and will be released sometime this year. In the meantime, please look at github.com/kschiess/cod to get an idea. Try it out and send me feedback!

UPDATE (2012-03-31): I’ve since rewritten cod from scratch. Some of the stuff talked about here will not work anymore.

Building on small elements

One of the main ideas of parslet was to build on small elements and to construct larger ideas from them. This style of construction pervades my work and never gets old for me. In Cod, I am trying to achieve much the same. All work you do with it will be based on the concept of a unidirectional communication channel:


  channel = Cod.pipe

This is a channel based on IO.pipe. It abstracts all the nitty gritty for you. Here’s how you communicate with child processes:


  control = Cod.pipe
  
  pid = fork do
    loop do
      # do something important & interesting
      break if control.waiting? && control.get == :shutdown
    end
  end
  
  # eventually, deciding that we want to shut down the child: 
  control.put :shutdown
  
  Process.waitall

As you can see in the above sample, Cod defaults to serializing Ruby objects through channels. This will be open for customization later on, but is mostly what you’ll want anyway.

For now, you are forced to ask if messages are queued up (control.waiting?) – however I will be working on allowing a Cod.select as well, implementing mixed #select calls on real FDs and Cod channels. This is real important for the style of process design I am aiming for.

Channels in channels

Cod channels try to be serializable. This sounds trivial, but has really profound implications. Let’s say you want to create a client/server type of interaction: You will have a common server address and open up a channel to it. But to be able to get a response back, you will need two things:

  • A channel to receive answers in
  • and to be able to communicate the channel to the server.

Here’s how you would probably do this in Cod:


  server = Cod.beanstalk('somehost:11300', 'server')
  client = Cod.beanstalk('somehost:11300')
  
  server.put ['heiho server!', client]
  answer = client.get

And on the server side of this:


  comm = Cod.beanstalk('somehost:11300', 'server')
  
  message, client = comm.get
  answer = act_on(message)
  client.put answer

But of course, in real life this is slightly more complex. You will want to use Cod::Client and Cod::Service for this kind of interaction; it bundles this functionality and delivers a debugged and robust implementation.

Bleeding edge

The above code will not even work. I am illustrating the idea, see. But it might very soon. Have a look at ./examples – those typically work. For now, assume that nothing else does.

Patterns of distributed computing

Cod will: Capture and encode patterns of distributed computation/communication in a library that allows the programmer to focus on the level above. To allow communication (even cross-communication?) with the newest fad queue server X, you’ll write a channel implementation for X and then profit of all higher order primitives directly.

Nifty. Been chuckling about the simplicity of it for days now. (Insert thunder & lightning)