I am using Mojolicious with a plugin called pgAsync in order to listen for NOTIFY
events that are being emitted from a Postgres database. The code I currently have is working fine, but I am seeing that the number of database connections is only ever increasing.
Back-end
#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojo::IOLoop;
use Mojolicious::Plugin::PgAsync;
app->secret('awdawdawdawd');
plugin PgAsync => {dbi => ['dbi:Pg:dbname=;host=;port=;', '', '', {AutoCommit => 0, RaiseError => 1}]};
any '/api/listen' => sub {
my $self = shift;
my $saved_tx = $self->tx;
Mojo::IOLoop->stream($self->tx->connection)->timeout(300);
$self->res->headers->add('Content-Type' => 'text/event-stream');
$self->res->headers->add('Cache-Control' => 'no-cache');
$self->res->headers->add('Access-Control-Allow-Origin' => '*');
# required for IE
$self->write(" " x 2048);
$self->write("\nretry: 2000\n\n");
my $drain_cb;
$drain_cb = sub {
my $c = shift;
$c->render_later;
$c->tx($saved_tx);
$c->pg_listen('foo', sub {
my $notify = shift;
my $payload = $notify->{payload};
$c->write("id:1\ndata:$payload\n\n", $drain_cb);
});
};
$self->pg_listen('foo', sub {
my $notify = shift;
my $payload = $notify->{payload};
$self->tx($saved_tx);
$self->write("id:1\ndata:$payload\n\n", $drain_cb);
});
};
app->start;
As you can see, I needed to do a bit of hackery to get this to work as I wanted it to. pg_listen
seemed to be undefining the callback after every call. This was causing an error when I called pg_listen
again (since it was undefined), and I had to modify line 34 of PgAsync::Db.pm to add a check for this:
$self->callback->($notify_hash, $notify_hash);
->to->
$self->callback->($notify_hash, $notify_hash) if defined $self->callback
Front-end
I am using JavaScript with an EventSource object to listen for the push notifications from the Mojolicious script:
var es = new EventSource("/api/listen");
var listener = function (event) {
console.log(event.data);
};
es.addEventListener("open", listener);
es.addEventListener("message", listener);
es.addEventListener("error", listener);
The Problem
Looking closer, it appears that this system is continuously creating more database connections:
Starting from nothing, there is 1 database connection, which is me looking at how many database connections there are with
select count(*) from pg_stat_activity;
I start morbo and the Mojolicious script with
DEBUG_PG=1 morbo mojopush.pl
. There are now 2 database connections (the 1st is me in psql, the 2nd is morbo)I open up the webpage with the EventSource object. It correctly sets the
GET
request with the content-type oftext/event-stream
and holds the connection open. There are now 3 db connectionsI go into psql and send
NOTIFY foo, 'test'
, the Mojo script detects it, and the webpage displays 'test. There are still 3 db connections.I refresh the page, and there are now 4 db connections. I wait for the 300 second inactivity timeout, and yet another database connection is created resulting in 5 connections.
If anyone could help point me in the right direction, that would be extremely appreciated!