Fixing an example in Mojolicious

TL;DR

Another drop in the open source sea.

I think many of us have the same feeling: our (software) contribution to the world is just a drop in an sea.

Instead of being discouraged, though, I feel reassured: there’s a lot to do, and even minor fixes can help improve things (e.g. by letting the next person to avoid spending 5 minutes to figure out why an error popped out). Also, there’s a lot of people doing this.

It happened to me while reading the Cookbook guide for Mojolicious, in particular the section about the Eventsource web service which has the following example:

use Mojolicious::Lite -signatures;

# Template with browser-side code
get '/' => 'index';

# EventSource for log messages
get '/events' => sub ($c) {

  # Increase inactivity timeout for connection a bit
  $c->inactivity_timeout(300);

  # Change content type and finalize response headers
  $c->res->headers->content_type('text/event-stream');
  $c->write;

  # Subscribe to "message" event and forward "log" events to browser
  my $cb = $c->app->log->on(message => sub ($log, $level, @lines) {
    $c->write("event:log\ndata: [$level] @lines\n\n");
  });

  # Unsubscribe from "message" event again once we are done
  $c->on(finish => sub ($c, $code, $reason = undef) {
    $c->app->log->unsubscribe(message => $cb);
  });
};

app->start;
__DATA__

@@ index.html.ep
<!DOCTYPE html>
<html>
  <head><title>LiveLog</title></head>
  <body>
    <script>
      var events = new EventSource('<%= url_for 'events' %>');

      // Subscribe to "log" event
      events.addEventListener('log', function (event) {
        document.body.innerHTML += event.data + '<br/>';
      }, false);
    </script>
  </body>
</html>

I tried it and I got one error upon closing one of the listener browser tabs:

Mojo::Reactor::Poll: I/O watcher failed: Too few arguments for subroutine at ...

It turns out that when Mojo::Transaction fires the finish event, it does not pass any argument (beyond the instance object), which makes the following subroutine signature pretty unhappy because it expects $code to be passed:

  # Unsubscribe from "message" event again once we are done
  $c->on(finish => sub ($c, $code, $reason = undef) {
    $c->app->log->unsubscribe(message => $cb);
  });

So presto! Let’s file a pull request!


Comments? Octodon, , GitHub, Reddit, or drop me a line!