Using Mojo::Pg::Pubsub under hypnotoad

236 Views Asked by At

I have a table with tokens in Pg database and to not to overload DB with permanent SELECTs I decided to cache tokens in RAM using few simple mojo helpers(for checking is token valid, deleting and adding tokens to such cache) in my app.

I'm using Mojo::Pg::Pubsub and Pg notification system(I have a trigger that notifies about token insertion/deletion) to catch events of deletion/creation tokens in DB. All workers have scheduled sub in their ioloops to make SQL DELETE on tokens which invalidated in DB. With mechanism of Pg notifications I need to get a situation when all hypnotoad workers will have the same pool of tokens in memory because all of them notified about any change.

But there is a problem that only 1 hypnotoad worker(random one from the pool, each time different one) catches this event. I understand that Mojo::Pg object probably becomes duplicative while workers are forks. I also found that Mojo::Server::Prefork which included somewhere under the hood of mojo app has and emits event called 'spawn' that noted in docs like

'Emitted when a worker process is spawned.'

The solution that I guess acceptable for me is to subscribe to this event and recreate Mojo::Pg object for each new forked worker but I can't find the way I can access server object to subscribe this event.

How can I do it? Or maybe I just doing something wrong and there are other ways to solve abovementioned problem?

Here is the code in my mojo app for working with DB:

my $pg = connect_mojo($app->config, $app->mode);
$app->helper(pg => sub {
    return $pg;
});

$app->helper(db => sub {
    return $app->pg->db;
});

And here is the code that responsible to catch notifications from Pg:

# Postgres notifies about token deletion through it's notification system
$app->pg->pubsub->listen(token_deleted => sub {
    my ($this, $token) = @_;
    $app->log->info("Notification for deleting token from Pg received: $token");
    $app->token_mem->invalidate($token);
});

# Postgres notifies about token creation through it's notification system
$app->pg->pubsub->listen(token_created => sub {
    my ($this, $token) = @_;
    $app->log->info("Notification for adding token from Pg received: $token");
    $app->token_mem->add($token);
});
0

There are 0 best solutions below