Wednesday, May 5, 2010

Integrating F# and Erlang Using OTP.NET

Recently, I ran across a post that talked about a .NET library named OTP.NET.  OTP.NET is a port of a Java library named JInterface that allows a .NET application to act as an Erlang node.  OTP.NET hasn't been updated in a while and the API is a bit clunky, but the provided functionality is very cool.  Note: A forked version of OTP.NET that has been migrated to VS2010 can be found at http://github.com/dmohl/OTP.NET-2010.

I decided to give OTP.NET a test drive by adding a simple command-line interface to an Erlang project that I have been playing with called Querly.

Querly is a simple query engine that allows T-SQL style queries against a CouchDB database.  You can read more about Querly in the following posts:

- Querly - A Query Engine for CouchDB
- Setting Up Querly
- Getting Started with Querly: A Simple CouchDB Query Engine

Getting Setup


To make this work, we first need to do the following:

1. Setup Querly by following the instructions provided in the blog post entitled Setting Up Querly.
2. If you want to load up a database for testing, follow the instructions provided in the blog post entitled Getting Started with Querly: A Simple CouchDB Query Engine.
3. Make sure that RabbitMQ and CouchDB are running.
4. Launch Querly by navigating to the Querly directory and running a command such as:
"C:\Program Files\erl5.7.5\bin\werl.exe" -sname querly -setcookie supersecretcookie -pa ./ebin -pa ./src
5. Finally, in the Erlang interactive shell, run the following command:
querly:start().

If everything worked as expected, you should see something like this:

Building the F# Application

Now that we have the Erlang application up and running, it's time to put together the F# code that will allow us to join the Erlang node cluster and interact with Querly.  Note: You'll need to replace the value assigned to peerNode with the name of your querly node. The full solution can be found at http://github.com/dmohl/Ferly.
module Ferly

open System
open Otp

Console.Write ":>"  
let mutable input = Console.ReadLine()  

let erlangCookie = "supersecretcookie"
let peerNode = "querly@dmohl-PC" // Replace with querly node name

let connection =
    let cNode = new OtpSelf("querlyclientnode", erlangCookie)
    let sNode = new OtpPeer(peerNode)
    cNode.connect(sNode)

let RemoteCall (sql:string) = 
    let arguments = [|new Erlang.String(sql)|] : Erlang.Object[]
    do connection.sendRPC("querly_client", "sql_query", arguments) 
    connection.receiveRPC().ToString()

while input <> "quit" do 
    Console.Write(RemoteCall input)
    Console.Write "\n\n:>"   
    input <- Console.ReadLine()


We should now be able to run the F# application and write queries against a couch database.  An example of the running application after a few processed queries is shown below:


Wrapping Up


We have only touched the surface of the functionality provided by OTP.NET.  Hopefully this post has shown how OTP.NET can be used to quickly integrate F# with Erlang.  Unfortunately, there is not a lot of documentation out there for OTP.NET, so if you want to learn more, your best bet is to pull down the code and start thumbing through it.  Happy polyglot programming!


3 comments:

  1. There is an interesting exercise implicit in all this, which is more than just tidying up the C# OTP.net code from jungerl (which I'd been doing a while back as a separate exercise), but to actually port it into F# wholesale (using async workflows for all the socket handling that's done as explicit threads).

    ReplyDelete
  2. Great point Steve! I was thinking the same thing.

    ReplyDelete
  3. There is an interesting exercise implicit in all this, which is more than just tidying up the C# OTP.net code from jungerl (which I'd been doing a while back as a separate exercise), but to actually port it into F# wholesale (using async workflows for all the socket handling that's done as explicit threads).

    ReplyDelete