Skip to content
Snippets Groups Projects
Verified Commit 87e5cfc0 authored by Andrej Ramašeuski's avatar Andrej Ramašeuski
Browse files

Nova logika pocitani pritomnych

parent 3d4b3522
No related branches found
No related tags found
No related merge requests found
Pipeline #6907 passed
...@@ -22,6 +22,7 @@ RUN cpanm \ ...@@ -22,6 +22,7 @@ RUN cpanm \
Mojo::Redis \ Mojo::Redis \
Mojo::JWT \ Mojo::JWT \
Mojolicious::Plugin::OpenAPI \ Mojolicious::Plugin::OpenAPI \
Mojolicious::Plugin::SentrySDK \
Mojolicious::Plugin::SwaggerUI Mojolicious::Plugin::SwaggerUI
ADD . /opt/cf ADD . /opt/cf
......
...@@ -3,128 +3,71 @@ package CF::Controller::Websockets; ...@@ -3,128 +3,71 @@ package CF::Controller::Websockets;
use Mojo::Base 'Mojolicious::Controller'; use Mojo::Base 'Mojolicious::Controller';
use Mojo::Pg::PubSub; use Mojo::Pg::PubSub;
use Digest::SHA qw(hmac_sha1_hex); use Digest::SHA qw(hmac_sha1_hex);
use POSIX qw(ceil);
use Encode qw(encode decode); use Encode qw(encode decode);
use feature 'signatures'; use feature 'signatures';
no warnings qw{ experimental::signatures }; no warnings qw{ experimental::signatures };
use constant SOCKET_INACTIVITY_TIMEOUT => 180; use constant SOCKET_INACTIVITY_TIMEOUT => 180;
use constant ALIVE_TIME => 60;
sub main { sub main {
my $c = shift; my $c = shift;
my $ip = $c->tx->remote_address; $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');
$c->inactivity_timeout(SOCKET_INACTIVITY_TIMEOUT); my $pubsub = $c->redis->pubsub;
if ($c->req->headers->header('Sec-WebSocket-Extensions') =~ /permessage-deflate/) { my $listener = $pubsub->listen(notify => sub($pubsub, $payload) {
$c->tx->compressed(1); $c->send(decode("UTF-8", $payload));
$c->res->headers->add('Sec-WebSocket-Extensions' => 'permessage-deflate'); });
}
my $pubsub;
if ($c->cfg->{message_broker} eq 'redis') {
$pubsub = $c->redis->pubsub;
$pubsub->listen(notify => sub($pubsub, $payload) {
$c->send(decode("UTF-8", $payload));
});
}
else {
$pubsub = Mojo::Pg::PubSub->new(pg => $c->pg);
$pubsub->listen(notify => sub($pubsub, $payload) {
$c->send($payload);
});
}
$c->on(json => sub( $c, $message ) { $c->on(json => sub( $c, $message ) {
if ( $message->{event} eq 'KEEPALIVE' ) { if ( $message->{event} eq 'KEEPALIVE' ) {
my $user; my $user;
my $is_member;
if ($message->{payload} =~ /^\d+$/) { if ($message->{payload} =~ /^\d+$/) {
$user = $c->schema->resultset('User')->find({
$user = $c->pg->db->select('users', id => $message->{payload},
[qw(id username secret jitsi_allowed roles banned_until)], });
{ id => $message->{payload}}
)->hash;
} }
if ( $user ) { if ( $user ) {
my $sig = hmac_sha1_hex($message->{payload}, $user->{secret} ); my $sig = hmac_sha1_hex($message->{payload}, $user->secret );
if ( $sig ne $message->{sig} ) { if ( $sig ne $message->{sig} ) {
$c->app->log->warn( $c->app->log->warn(
"Invalid signature for " . $user->{username} "Invalid signature for " . $user->username
); );
$user = undef;
} }
} else {
$user->update({ keepalive => \'now()' });
eval { $is_member = ( $user && $user->roles =~ /member/) ? 1:0;
my $tx = $c->pg->db->begin;
$c->pg->db->delete('sockets', [
{id => $key},
$user ? {user_id => $user->{id}}:{}
]);
$c->pg->db->insert('sockets', {
id => $key,
ip => $ip,
keepalive => \'now()',
user_id => $user ? $user->{id} : undef,
});
$tx->commit; my $jitsi = $user->jitsi_allowed || $user->roles =~ /chairman|jitsi/;
};
my $all = $c->pg->db->query( $c->send({json => { event => 'user_status', payload => {
'select count(*) from sockets_view' jitsi_allowed => $jitsi ? \1:\0,
)->hash->{count}; is_banned => $user->banned_until ? \1:\0,
}}});
my $members = $c->pg->db->query( }
'select count(*) from sockets_view where is_member' }
)->hash->{count};
my $group_size = $c->_member_group_size($members);
$c->send({json => { event => 'online_users_updated', payload => {
all => $all,
members => $members,
group_size_full => $group_size->{full},
group_size_half => $group_size->{half},
}}});
if ( $user ) { $c->redis->db->set(
my $jitsi = $user->{jitsi_allowed} || $user->{roles} =~ /chairman|jitsi/; join (':', ('live', 0, $is_member, $is_member ? $user->id : $key)), #TODO: event_id
'live', 'EX', ALIVE_TIME
);
$c->send({json => { event => 'user_status', payload => {
jitsi_allowed => $jitsi ? \1:\0,
is_banned => $user->{banned_until} ? \1:\0,
}}});
}
} }
}); });
$c->on(finish => sub ($c, $code, $reason = undef) { $c->on(finish => sub ($c, $code, $reason = undef) {
$pubsub->unlisten('notify'); $pubsub->unlisten('notify', $listener);
$c->app->log->debug("WebSocket closed with status $code"); $c->app->log->debug("WebSocket closed with status $code");
}); });
} }
sub _member_group_size ($c, $total = 0){
my $group = 2 * sqrt($total);
my $min = $total / 100;
my $max = $total / 5;
$group = $min if $group < $min;
$group = $max if $group > $max;
return {
full => ceil( $group ),
half => ceil( $group/2 ),
};
}
1; 1;
openapi: 3.0.3 openapi: 3.0.3
info: info:
version: "2.6.1" version: "2.7.0"
title: CF Online title: CF Online
description: CF Online description: CF Online
license: license:
......
#!/usr/bin/perl
use Mojo::IOLoop;
use Mojo::Redis;
use Mojo::JSON qw(encode_json);
use POSIX qw(ceil);
use feature 'signatures';
no warnings qw{ experimental::signatures };
my $tick = 0;
my $redis = Mojo::Redis->new($ENV{CFG_REDIS});
my $id = Mojo::IOLoop->recurring(1 => \&counter);
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
sub counter {
my $counts = {};
$redis->db->keys( 'live:*', sub {
my ($db, $err, $res) = @_;
KEYS:
foreach my $key ( @{ $res} ) {
my (undef, $event_id, $role) = split /:/, $key;
$counts->{$event_id}{all}++;
$counts->{$event_id}{members}++ if $role;
}
EVENT:
foreach my $event_id ( keys %{ $counts } ) {
my $all = $counts->{$event_id}{all};
# zpomalovac
next EVENT if $tick > 9000/$all;
my $group_size = member_group_size($all); #TEST
$redis->pubsub->notify( notify => encode_json({
event => 'online_users_updated',
payload => {
all => $all,
members => $counts->{$event_id}{members},
# group_size_full => $group_size->{full},
group_size_half => $group_size->{half},
tick => $tick,
}
}));
}
});
$tick = 0 if ++$tick > 9;
}
sub member_group_size ($total = 0){
my $group = 2 * sqrt($total);
my $min = $total / 100;
my $max = $total / 5;
$group = $min if $group < $min;
$group = $max if $group > $max;
return {
full => ceil( $group ),
half => ceil( $group/2 ),
};
}
1;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment