Permalink
Fetching contributors…
Cannot retrieve contributors at this time
117 lines (92 sloc) 3.1 KB
package Convos::Controller::Events;
use Mojo::Base 'Mojolicious::Controller';
use Convos::Util qw(DEBUG E);
use Mojo::JSON 'encode_json';
use Mojo::Util;
use constant INACTIVE_TIMEOUT => $ENV{CONVOS_INACTIVE_TIMEOUT} || 30;
sub start {
my $self = shift;
my $user = $self->backend->user or return $self->_err('Need to log in first.', {})->finish;
Scalar::Util::weaken($self);
my $uid = $user->id;
my $backend = $self->app->core->backend;
my $cb = $backend->on(
"user:$uid" => sub {
my ($backend, $event, $data) = @_;
my $ts = Mojo::Date->new($data->{ts} || time)->to_datetime;
warn "[Convos::Controller::Events] >>> @{[encode_json $data]}\n" if DEBUG == 2;
$self->send({json => {%$data, ts => $ts, event => $event}});
}
);
$self->inactivity_timeout(INACTIVE_TIMEOUT);
$self->on(
finish => sub {
warn "[Convos::Controller::Events] !!! Finish\n" if DEBUG == 2;
$backend->unsubscribe("user:$uid" => $cb);
}
);
$self->on(
json => sub {
my ($self, $data) = @_;
my $method = sprintf '_event_%s', $data->{method} || 'ping';
$data->{id} //= Mojo::Util::steady_time();
warn "[Convos::Controller::Events] <<< @{[Mojo::JSON::encode_json($data)]}\n" if DEBUG == 2;
$self->can($method) ? $self->$method($data) : $self->_err('Invalid method.', $data);
}
);
}
sub _err {
my ($self, $err, $data) = @_;
my $res = E $err;
$res->{$_} = $data->{$_} for grep { $data->{$_} } qw(connection_id message id);
$res->{event} = 'sent';
$self->send({json => $res});
}
sub _event_get_user {
my ($self, $data) = @_;
my $user = $self->backend->user
or return $self->_err('Need to log in. Session reset?', {})->finish;
$self->delay(
sub { $user->get($data, shift->begin); },
sub {
my ($delay, $err, $res) = @_;
return $self->_err($err, {})->finish if $err;
return $self->send({json => $res});
}
);
}
sub _event_send {
my ($self, $data) = @_;
my $connection = $self->backend->user->get_connection($data->{connection_id})
or return $self->_err('Connection not found.', $data);
$self->delay(
sub { $connection->send($data->{dialog_id}, $data->{message}, shift->begin); },
sub {
my ($delay, $err, $res) = @_;
$res = $res->TO_JSON if UNIVERSAL::can($res, 'TO_JSON');
$res ||= {};
$res->{errors} = E($err)->{errors} if $err;
$res->{event} = 'sent';
$res->{$_} ||= $data->{$_} for keys %$data;
$self->send({json => $res});
},
);
}
sub _event_ping {
$_[0]->send({json => {event => 'pong', ts => Mojo::Util::steady_time()}});
}
1;
=encoding utf8
=head1 NAME
Convos::Controller::Events - Stream events from Convos::Core to web
=head1 DESCRIPTION
L<Convos::Controller::Stream> is a L<Mojolicious::Controller> which
can stream events from the backend to frontend, and also act on
input from web, if websocket is supported by the browser.
=head1 METHODS
=head2 start
Will push L<Convos::Core::User> and L<Convos::Core::Connection> events as JSON
objects over a WebSocket connection and receive messages from the frontend.
=head1 SEE ALSO
L<Convos>:
=cut