Wednesday, January 04, 2012

A Concurrency Programming Kata in Erlang


Write an Erlang program that spawns two processes. Each process should:
  1. Send a unique (pseudo-random) key/value pair to the CouchDB database. Remember the value in-process so it can be confirmed later (see Step 6.) Don't use process dictionaries for this.
  2. Send the Id of the created CouchDB record to the other process.
  3. Listen for Ids being sent to it by the other process.
  4. On receiving an Id, retrieve the Id from CouchDB.
  5. Send the retrieved value back to the other process to confirm the retrieval is correct.
  6. Confirm any values sent to it by the other process. Don't re-fetch the record from CouchDB. Don't use process dictionaries.
  7. Sleep for an interval.
  8. Goto (1).
This kata helps us to explore Erlang's concurrency primitives, which are Erlang's best, most distinctive feature.

If you're using Homebrew on OS X:


~$ brew install erlang
~$ brew install couchdb
~$ couchdb # Will run in the foreground, switch to a new Terminal for the rest
To get started using Erlang to communicate with CouchDB you'll need a couple modules, installed like this:


~$ git clone git://github.com/ngerakines/erlang_couchdb.git ; cd erlang_couchdb ; make
~$ svn checkout http://mochiweb.googlecode.com/svn/trunk/ mochiweb ; cd mochiweb ; make
Here's some sample code to load the module paths, demonstrate the CouchDB API, and verify all of those pieces are working:


-module(kata_couch).
-compile(export_all).

% Path to your erlang_couchdb clone + "/ebin"
-define(ERLANG_COUCHDB_PATH, "/Users/alh/src/erlang_couchdb/ebin").
% Path to your mochiweb checkout + "/ebin"
-define(MOCHIWEB_PATH, "/Users/alh/src/mochiweb/ebin").
-define(DBSERVER, {"localhost", 5984}).

main() ->
    setup_paths(),
    db_demo(),
    init:stop().

db_demo() ->
    erlang_couchdb:create_database(?DBSERVER, "test1"),
    {json, {struct, [{_,_}, {<<"id">>,Cid}, {_,_}]}} =
        erlang_couchdb:create_document(?DBSERVER, "test1", [{<<"keyA">>, <<"valA">>}]),
    Retr1 = erlang_couchdb:retrieve_document(?DBSERVER, "test1", binary_to_list(Cid)),
    {json, {struct, [{_,_}, {_,_}, {K,V}]}} = Retr1,
    io:format("~p : ~p~n", [K, V]).

setup_paths() ->
    code:add_patha(?ERLANG_COUCHDB_PATH),
    code:add_patha(?MOCHIWEB_PATH).
And an idiomatic sleep/1 function, taken from the Armstrong book:


sleep(T) ->
    receive
        after T ->
            true
    end.

No comments: