Я играю с Mojolicious и websockets. Я хочу отправить вывод нескольких внешних команд на сервер на веб-страницу. У меня нет проблем с подключением и получением сообщений, но я также хочу отправить сообщение на сервер, чтобы остановить внешнюю команду, позволяя другим отправлять сообщения обратно клиенту. Я также хочу остановить проверку внешней команды после ее выхода.Выключение Mojo :: Повторное событие IOLoop, связанное с websocket Mojo
Внешняя команда - это просто один лайнер, который выплескивает целое число каждые несколько секунд. У меня есть два websockets, которые отображают числа в отдельных div
s. Нажатие одной из кнопок останова отправляет сообщение, но мне нужно выяснить, как закрыть этот веб-узел (и только этот веб-узел) и отключить внешнюю команду.
При подключении WebSocket, я запускаю внешнюю команду и настроить Mojo::IOLoop->recurring
, чтобы проверить, есть ли выход.
Когда я хочу остановиться, я полагаю, что я должен позвонить Mojo::IOLoop->remove($id)
, но это, похоже, не полностью удаляет его, и я получаю сообщения об ошибках, такие как Mojo::Reactor::Poll: Timer failed: Can't call method "is_websocket" on an undefined value
.
Если я вызываю finish
на объект контроллера, чтобы закрыть websocket, он, кажется, остановит все.
У меня есть весь Mojolicious::Lite app as a gist, но вот детали, где я
use feature qw(signatures);
no warnings qw(experimental::signatures);
## other boilerplate redacted
websocket '/find' => sub ($c) {
state $loop = Mojo::IOLoop->singleton;
app->log->debug("websocket for find");
$c->inactivity_timeout(50);
my $id;
$c->on(message => sub ($ws, $message) {
my $json = decode_json($message);
my $command = $json->{c};
my $name = $json->{n};
app->log->debug("Got $command command for $name");
if($command eq "start") {
$id = run_command($ws);
app->log->debug("run_command for $name returned [$id]");
}
elsif($command eq "stop") {
app->log->debug("stopping loop for $name [$id]");
# XXX What should I do here?
# $ws->finish;
# $loop->remove($id);
}
elsif($command eq "open") {
app->log->debug("opening websocket for $name");
}
}
);
$c->on(
finish => sub ($c, $code) {
app->log->debug("WebSocket closed with status $code");
}
);
};
app->start;
sub run_command ($ws) {
app->log->debug("In run_command: $ws");
open my $fh, "$^X -le '\$|++; while(1) { print int rand(100); sleep 3 }' |";
$fh->autoflush;
my $id;
$id = Mojo::IOLoop->recurring(1 => sub ($loop) {
my $m = <$fh>;
unless(defined $m) {
app->log->debug("Closing down recurring loop from the inside [$id]");
# XXX: what should I do here?
close $fh;
return;
};
chomp $m;
app->log->debug("Input [$m] for [$id] from $fh");
$ws->send(encode_json({ 'm' => $m }));
});
return $id;
}
Другие вопросы, которые могут извлечь выгоду из этого ответа:
Включает ли Mojolicious объявление подзаголовка в стиле Perl6? – Zaid
Perl v5.20 имеет подпрограммы в качестве экспериментальной функции: http: //www.effectiveperlprogramming.com/2015/04/use-v5-20-subroutine-signatures/ –