Erlectricity: Hi Ruby, I’m Erlang.
update: this pre-release is up and running on rubyforge:
sudo gem install erlectricity
As I said in my previous article, I’m very stoked about working with Erlang. Usually most forays into new languages mean new projects and new explorations: Erlang has been no different. I usually end up in some middle ground where I try to improve the current language I’m working in with the new language: With C# -> Ruby it was a code generator written in Ruby that produced the cookie cutter DALs that I was plagued with, and this time around I immediately started to gravitate towards interoperation between erlang and ruby.
I’m not the only one with this idea (I’ve never claimed to be original), with several others working on using JSON to bridge the gap. That is all well and good, but considering how good erlang is at expressing itself across networks, I’d rather see something closer to the erlang-way. And that is why I set about creating what I call Erlectricity.
Before I go further, a code sample is in order. The following code is a passthrough daemon to Tinder, (the Campfire API gem) that lets you post to campfire from erlang. Even more before I show you the code, here is the google code site: http://code.google.com/p/erlectricity/, with the source being: http://erlectricity.googlecode.com/svn/trunk/. And now…
The Ruby:
require 'rubygems' require 'erlectricity' require 'tinder'And some erlang to call it (i’m omitting some code, please see the tinderl.erl example in the source to see the code that enables the calls below):domain, email, password, roomname = *ARGV campfire = Tinder::Campfire.new domain campfire.login email, password room = campfire.findroombyname room_name
receive do match(:speak, string(:comment)) do room.speak comment receive_loop end
match(:paste, string(:comment)) do room.paste comment receive_loop end end
room.leave if room
tinder:start("thedomain", "myemail@gmail.com", "mypassword", "theroom"),
tinder:speak("hey, hey kids!"),
tinder:paste("Im Krusty the Klown!").
At first, this was going to be a JRuby layer over JInterface, the Java -> Erlang bridge. That was all well and good, and worked fine, but it had a major flaw: It was tied to JRuby, leaving out the majority of Rubyists. JRuby is super exciting, and I was super stoked the first time I got ruby running inside a prototype game using The JMonkey Engine, but I didn’t want to be the person to exclude. I decided at this initial stage to use the Erlang port system, a means of starting and communicating with a separate process. As a consequence, I implemented most of the Erlang distribution format. Why re-invent the wheel when erlang has termtobinary and binarytoterm? Plus, it’s fun investigating the Erlang distribution format, even though only a subset is used for termtobinary.
As an aside, one reason to re-implement termtobinary and its sibling is because of the limited nature of Erlang’s type system.
You’ll also notice in the example directory ‘gruff’: 2 hours of hacking invested into rendering Gruff graphs through Erlectricity. Below is a graph generated using the stat_writer example to graph memory usage while running ab against webtool:
This was as a response to Yariv, and his desire for a graphing library in erlang like gruff. The example isn’t by any means a real solution, merely a demostration that this could be a viable solution.
The goal of Erlectricity is two-fold: expose ruby code to erlang, such that erlang applications can take advantage of the breadth of ruby libraries, and secondly, expose the OTP to ruby such that fault-tolerant distributed systems will be easier to develop. Neither of those goals are realized in Erlectricity’s current form, but it is a good base to work from towards those goals. Also, the two examples included demonstrate the former, and I’m playing around with something meaningful to demonstrate the latter.
This post is already about 3-times too long, but let me real quickly describe the structure of an erlectric app on the ruby side. The programming model follows the concurrency model of erlang, so read up on how erlang processes messages if you get confused. I’ll also describe it in further detail in an additional post. So, the core of an app using erlectricity is the receive loop, which looks like:
receive do
match(:hello, string(:yourname)) do
send! :helloreceived, "You stink, #{yourname}"
receiveloop
end
match(:goodbye){ }
end
The receive block says “get a message, blocking if there are none on the wire”. When a message is received in this state it is compared with each of the match blocks in turn. The match block in the example says “If the message looks like the symbol :hello, and a string, bind the string object to the variable yourname and run the block.” Normally, when receiving a message, the code would then jump out of the receive block, but since the return value of the match block is receiveloop, the program tries to process another message against the same supplied match blocks. You’ll also notice that if the process receives a message that is just the symbol :goodbye, the app will simply fall out of the receive loop.
Here are some tips if you would like to play around with Erlectricity:
- Email me if you have any trouble: nullstyle@gmail.com
- Pass strings as binaries to ruby. “haha” will come out as [104, 97, 104, 97] in ruby, but <<”haha”>> will come out as “haha” in ruby. See my comment above about the limited type system in erlang. I’ll make a separate post about this issue, because I want to talk more fully about why I made this choice.
- Make sure your port is created with the
{packet, 4}andbinaryoptions. Creating a port with{packet, 2}will have your ruby process never receiving any messages. Not havingbinaryresponses enabled will cause trouble when you trybinarytotermto get the response. This is an area for further improvement. - Its a good idea to include catch-all clauses while you are working out the interaction issues. It greatly sped up my debugging time when I had the program yell at me when I sent an improper message
You can install erlectricity with:
sudo gem install erlectricity --source http://gems.nullstyle.com/I’m in process of opening up the rubyforge project, so you’ll be able to drop the –source in a couple days. Stay tuned for more info, examples, and improvements as time marches forward.
May 30th, 2008 at 9:55 pm
Hi there!
You may or may not be aware that some of us have started a github network. If you visit http://github.com/mojombo/erlectricity and http://github.com/halorgium/erlectricity, you'll see some of the changes we've made.
I'm not sure if you're into git, but it sure works well for random projects like this one!