bc-bd.org

Not a blog

Mojolicious and Linux::Inotify2

This is a tiny example on how to use Linux::Inotify2 from within a Mojolicious application to watch a file for modification. Note: this will not work with morbo, as no inotify will be delivered to the app. Update: it works with morbo if you use our $io = … instead of my $io = …. The reason for that is, my $io goes out of scope as app->start() does not block.

You will need these modules:

  • Linux::Inotify2 - scalable directory/file change notification

  • EV - perl interface to libev, a high performance full-featured event loop

  • AnyEvent - the DBI of event loop programming

  • And of course Mojolicious

Steps to see the magic happen:

  1. Save the code below to /tmp/i.pl

  2. Create file to be watched: touch /tmp/foo

  3. Run your app (again, morbo will not work): /tmp/i.pl daemon

  4. In another shell, update the watched file: touch /tmp/foo

This is what Mojolicious should log:

[Tue Feb 26 21:22:09 2013] [info] Listening at “http://*:3000”. Server available at http://127.0.0.1:3000. [Tue Feb 26 21:22:13 2013] [debug] file changed [Tue Feb 26 21:22:13 2013] [debug] file changed [Tue Feb 26 21:22:13 2013] [debug] file changed

Code:

#!/usr/bin/perl

use Mojolicious::Lite;

use Linux::Inotify2;
use EV;
use AnyEvent;

sub file_changed {
        app->log->debug("file changed");
}

sub setup_notify {
        my $inotify = new Linux::Inotify2;
        $inotify->watch('/tmp/foo', IN_ALL_EVENTS, 
                \&file_changed);

        my $io = AnyEvent->io(
                fh => $inotify->{fd},
                poll => 'r',
                cb => sub { $inotify->poll }
        );

        return $io;
}

get '/' => sub { shift->render_text('index') };

our $io = setup_notify();

app->start();