package CF::Controller::Websockets; use Mojo::Base 'Mojolicious::Controller'; use Mojo::Pg::PubSub; use JSON; use feature 'signatures'; no warnings qw{ experimental::signatures }; use constant SOCKET_INACTIVITY_TIMEOUT => 300; use constant USER_ALIVE_TIMEOUT => 100; sub main { my $c = shift; $c->inactivity_timeout(SOCKET_INACTIVITY_TIMEOUT); my $user; if ( my $key = $c->req->headers->authorization ) { if ( $key =~ s/Bearer\s+//i ) { $c->oauth_token($key); if ( $c->user ) { $user = $c->schema->resultset('User')->find_or_create( $c->user, { key => 'uuid'} ); } } } my $pubsub = Mojo::Pg::PubSub->new(pg => $c->pg); $pubsub->listen(notify => sub($pubsub, $payload) { $c->send($payload); }); $c->on(message => sub( $c, $message ) { $user->update({keepalive => \'now()'}) if $user; my $min_alive_time = "now() - '" . USER_ALIVE_TIMEOUT. " s'::interval"; my $alive = $c->schema->resultset('User')->count( { keepalive => { '>' => \$min_alive_time }, } ); $c->send(to_json({ online_users => $alive })); }); $c->on(finish => sub ($c, $code, $reason = undef) { $pubsub->unlisten('notify'); $c->app->log->debug("WebSocket closed with status $code"); }); } 1;