From f13a4da5b72c866871172c60b95d3636abd522c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrej=20Rama=C5=A1euski?= <andrej@x2.cz> Date: Tue, 22 Feb 2022 00:20:37 +0100 Subject: [PATCH] Podrobna evidence pritomnosti --- lib/CF/Controller/Websockets.pm | 52 ++++++++++++++++++--------------- lib/CF/Helpers/Core.pm | 2 +- lib/CF/Schema/Result/Alive.pm | 44 ++++++++++++++++++++++++++++ lib/CF/Schema/Result/User.pm | 6 +++- sql/11/up.sql | 11 +++++++ 5 files changed, 89 insertions(+), 26 deletions(-) create mode 100644 lib/CF/Schema/Result/Alive.pm create mode 100644 sql/11/up.sql diff --git a/lib/CF/Controller/Websockets.pm b/lib/CF/Controller/Websockets.pm index cbabd5d..bb8afc1 100644 --- a/lib/CF/Controller/Websockets.pm +++ b/lib/CF/Controller/Websockets.pm @@ -16,35 +16,39 @@ sub main { $c->inactivity_timeout(SOCKET_INACTIVITY_TIMEOUT); $c->tx->with_compression; - my $key = $c->req->headers->header('Sec-WebSocket-Key'); - + my $key = $c->req->headers->header('Sec-WebSocket-Key'); my $pubsub = $c->redis->pubsub; + my $user; + my $event_id = 0; #TODO - parametr! - my $listener = $pubsub->listen(notify => sub($pubsub, $payload) { - $c->send(decode("UTF-8", $payload)); - }); - - my $listener_online = $pubsub->listen('online:0' => sub($pubsub, $payload) { #TODO: event_id - my @counts = split ' ', $payload; - $c->send({json => { - event => 'online_users_updated', - payload => { - all => $counts[0]+0, - members => $counts[1]+0, - group_size_full => $counts[2]+0, - group_size_half => $counts[3]+0, - } - }}); - }); + my $listener = $pubsub->listen( + "notify:$event_id" => sub($pubsub, $payload) { + $c->send(decode("UTF-8", $payload)); + } + ); + + my $listener_online = $pubsub->listen( + "online:$event_id" => sub($pubsub, $payload) { + my @counts = split ' ', $payload; + $c->send({json => { + event => 'online_users_updated', + payload => { + all => $counts[0]+0, + members => $counts[1]+0, + group_size_full => $counts[2]+0, + group_size_half => $counts[3]+0, + } + }}); + } + ); $c->on(json => sub( $c, $message ) { if ( $message->{event} eq 'KEEPALIVE' ) { - my $user; my $is_member = 0; if ($message->{payload} =~ /^\d+$/) { - $user = $c->schema->resultset('User')->find({ + $user ||= $c->schema->resultset('User')->find({ id => $message->{payload}, }); } @@ -57,7 +61,7 @@ sub main { ); } else { - $user->update({ keepalive => \'now()' }); + $user->add_to_alive({ event_id => $event_id }); $is_member = 1 if $user && $user->roles =~ /member/; my $jitsi = $user->jitsi_allowed || $user->roles =~ /chairman|jitsi/; @@ -70,7 +74,7 @@ sub main { } $c->redis->db->set( - join (':', ('live', 0, $is_member, $is_member ? $user->id : $key)), #TODO: event_id + join (':', ('live', $event_id, $is_member, $is_member ? $user->id : $key)), 'live', 'EX', ALIVE_TIME ); @@ -78,8 +82,8 @@ sub main { }); $c->on(finish => sub ($c, $code, $reason = undef) { - $pubsub->unlisten('notify', $listener); - $pubsub->unlisten('online:0', $listener_online); #TODO: event_id + $pubsub->unlisten("notify:$event_id", $listener); + $pubsub->unlisten("online:$event_id", $listener_online); $c->app->log->debug("WebSocket closed with status $code"); }); } diff --git a/lib/CF/Helpers/Core.pm b/lib/CF/Helpers/Core.pm index 999e8f5..46c05f1 100644 --- a/lib/CF/Helpers/Core.pm +++ b/lib/CF/Helpers/Core.pm @@ -201,7 +201,7 @@ sub register ($class, $self, $conf) { }); - $self->helper( notify => sub ( $c, $event, $payload ) { + $self->helper( "notify:0" => sub ( $c, $event, $payload ) { #TODO: event_id my $content = { event => $event, diff --git a/lib/CF/Schema/Result/Alive.pm b/lib/CF/Schema/Result/Alive.pm new file mode 100644 index 0000000..94dba03 --- /dev/null +++ b/lib/CF/Schema/Result/Alive.pm @@ -0,0 +1,44 @@ +package CF::Schema::Result::Alive; + +use strict; +use warnings; +use feature 'signatures'; +no warnings qw{ experimental::signatures }; + +use base 'DBIx::Class::Core'; + +our $VERSION = 1; + +__PACKAGE__->table('alive'); + +__PACKAGE__->add_columns( + id => { + data_type => 'integer', + is_auto_increment => 1, + is_nullable => 0, + sequence => 'uid_seq' + }, + qw( + event_id + user_id + timestamp + ), +); + +__PACKAGE__->set_primary_key('id'); + +__PACKAGE__->belongs_to( + event => 'CF::Schema::Result::Event', + { + 'foreign.id' => 'self.user_id', + }, +); + +__PACKAGE__->belongs_to( + user => 'CF::Schema::Result::User', + { + 'foreign.id' => 'self.user_id', + }, +); + +1; diff --git a/lib/CF/Schema/Result/User.pm b/lib/CF/Schema/Result/User.pm index aa043cd..9fea904 100644 --- a/lib/CF/Schema/Result/User.pm +++ b/lib/CF/Schema/Result/User.pm @@ -28,7 +28,6 @@ __PACKAGE__->add_columns( name roles main_group_name - keepalive banned_until jitsi_allowed ), @@ -45,6 +44,11 @@ __PACKAGE__->has_many( { 'foreign.user_id' => 'self.id', }, ); +__PACKAGE__->has_many( + alive => 'CF::Schema::Result::Alive', + { 'foreign.user_id' => 'self.id', }, +); + sub formatted($self) { my $user = { diff --git a/sql/11/up.sql b/sql/11/up.sql new file mode 100644 index 0000000..dc9b497 --- /dev/null +++ b/sql/11/up.sql @@ -0,0 +1,11 @@ +create table "alive" ( + "id" integer not null default nextval('uid_seq'), + "event_id" integer not null, + "user_id" integer not null, + "timestamp" timestamp(0) not null default now(), + foreign key ("event_id") references "events" ("id") on update cascade on delete cascade, + foreign key ("user_id") references "users" ("id") on update cascade on delete cascade +); +create index "alive_timestamp_idx" on "alive" ("timestamp"); + +alter table "users" drop column "keepalive"; -- GitLab