I previously made a little proof-of-concept web chat using MochiWeb (the MochiMedia toolkit to build HTTP servers). The conclusion was; I still had to explore different fields like:
- the management of multiple rooms;
- the informations about who joined and left;
- and the history.
And it’s what I did recently, there is a screencast (but no source code this time because there is too much work in progress in it). The big task was to enrich the data format with nick names, informational messages (rename, join and leave) and multiple rooms. That was only adding more complexity to the backend and front end site a little step forward.
The major thing I did is offering a history of the messages. To go that way, there is obviously a need of having, somewhere, a storage infrastructure. Erlang has Mnesia (which is used by Erlycomet and Twoorl (for handling sessions)). Mnesia is a distributed storage system either in memory or on disk with 4 different way of managing datas (as key/value pairs). One of them is exactly how Memcached works, unsurprisingly.
But I didn’t choose Mnesia because I wan’t my data to be accessed from outside the Erlang world and having a query interface avoids a lot of extra work. My work comet chat was built using web.py and memcached and it quickly became over complicated. So, CouchDB, the rising star, which according to this video presentation by Jan Lehnardt solves the replication limitations MySQL have (yes, the slave-master thing) by saying that everyone is a gentlemen that knows how to deal with conflicts.
The other thing I really heart about CouchDB is that you put in it whatever you want and have only to deal with that when you query them: store and don’t care.
To access CouchDB data from MochiWeb server, I used the very fresh eCouch library (formerly OTP application) released as an Open Source project by the tarpipe team. Grab it and test, it’s very simple.
$ curl http://localhost:5984/ {"couchdb":"Welcome","version":"0.7.3a"} $ erl -pa ebin/ Erlang (BEAM) emulator version 5.6.2 [source] [async-threads:0] Eshell V5.6.2 (abort with ^G) 1> inets:start(). ok 2> application:start(ecouch). ok 3> ecouch:db_list(). {ok,[<<"test_suite_db">>,<<"test_suite_db_a">>, <<"test_suite_db_b">>,<<"chat">>]} 4> ecouch:db_info("test_suite_db"). {ok,{obj,[{"db_name",<<"test_suite_db">>}, {"doc_count",0}, {"doc_del_count",0}, {"update_seq",21}, {"compact_running",false}, {"disk_size",14830}]}} 5> ecouch:view_access("chat", "messages", "all", [{count, 1}]). {ok,{obj,[{"total_rows",18}, {"offset",0}, {"rows", [{obj,[{"id",<<"08ae6beaeca9a0509ef838dce9d4303d">>}, {"key",<<"2008-06-10T07:30:44.0781Z">>}, {"value", {obj,[{"_id",<<"08ae6beaeca9a0509ef838dce9d4"...>>}, {"_rev",<<"3175880002">>}, {"type",<<"info">>}, {"posted_at",<<"2008-06-10T07:30"...>>}, {"message",<<"Guest joined">>}, {"room",<<"Welcome">>}]}}]}]}]}} 6> q(). ok
So inside MochiWeb, make sure inets:start()
is ran somewhere in your application (near mochiweb:start
appears to be a good idea and working for me) and ecouch
has to be added to the applications that yours relies on (yours.app
.
CouchDB also introduced a complete map/reduce API. If you tried it a while ago, it’s worth a second look. I.e. map
is know called emit
, so any examples using map
are outdated.
I don’t know if MochiWeb alone is enough to fit all the development needs a normal project has. I’ll investigate the creation of less Ajaxy pages like browseable and searchable chat archives, user profiles, OpenID authentication and so on. Many people are discussing about creating combinaison of different languages, but if I look at Twoorl (powered by ErlyWeb) it doesn’t seem to need any other languages/framework to rock.