IPC with Erlang
Previous status: I’ve shown Erlang code that sends a Jabber message. I’ve shown Erlang code that parses a planet Venus generated Mememes feed. Now, lets consider the problem of sending notifications for new items.
Typically, solutions for problems like these require some level of persistence: a database, serialized results, or the like. But each of these options require additional maintenance commitments, and I’m looking for something with zero footprint and “just works”.
The memes feed is produced by a script invoked by a cron job. Ideally, we would be looking for commands that could be added to that script. In order to do so, we would need a command that is inserted near the beginning of the bash script, and a second command inserted near the end, and a way for these processes to communicate. And, as it turns out, this is something that Erlang excels at.
In Erlang you can name the server, the process, and the thread, you can send a message to it. A rough design for the server would be to register the thread under a given name, scan the atom feed retaining the Title
s and Link
s found, and wait up to ten minutes for a message that simply says resume
. Once that message is received, perform a second scan, this time issuing alerts on all new entries. The Erlang code for this is as follows:
start() -> register(meme_thread, self()), scan(mark), receive resume -> scan(alert) after 10 * 60 * 1000 -> xmppclient:send("meme", ["Timed out."]) end, init:stop().
This code is invoked thus:
erl -noshell -sname meme_server -s newmemes start &
The code for the client is even simpler. It simply needs to send a resume message to the named thread on a given Node, and exit. The code for this is as follows:
resume([Node]) -> {meme_thread, Node} ! resume, init:stop().
This code is invoked thus:
erl -noshell -sname meme_client -s newmemes resume meme_server@localhost
Everything else is straightforward. scan
now accepts a Mode
parameter, and passes it to format_entries
, which uses it in a case
statement, thus:
case Mode of mark -> put(Link, Title); alert -> case get(Link) of Title -> nop; _Else -> xmppclient:send("meme", [{a,[{href,Link}],[Title]}]) end end,
Additionally xmppclient accepts the Resource and Message as parameters. Given that the machine running this code has the feed on disk, I’ve also updated the code to parse the file directly, eliminating an http request.
The completed code: newmemes.erl, xmppclient.erl.
Notes:
- one alternate approach would be to have the cron job call the process which does the diff, and have that process shell out to, and wait for the Venus script to complete. Frankly, this is greater coupling that I am comfortable with.
- another alternate would be to simply copy the memes feed and then read both versions at the end of the job. In this specific case, that approach would be simpler, but it is undeniable that at times it is handy to have active agents that one can readily communicate with.