Я играю с Mojolicious и веб-сокетами. Я хочу отправить вывод нескольких внешних команд на сервере на веб-страницу. У меня нет проблем с подключением и получением сообщений, но я также хочу отправить сообщение на сервер, чтобы остановить внешнюю команду, позволяя другим продолжать отправлять сообщения обратно клиенту. Я также хочу прекратить проверку внешней команды после ее выхода.
Внешняя команда - это просто однострочная строка, которая выводит целое число каждые несколько секунд. У меня есть два веб-узла, которые отображают числа в отдельных div
. Нажатие любой из кнопок остановки отправляет сообщение, но именно здесь мне нужно выяснить, как закрыть этот веб-сокет (и только этот веб-сокет) и закрыть внешнюю команду.
Когда я подключаю веб-сокет, я запускаю внешнюю команду и настраиваю Mojo::IOLoop->recurring
, чтобы проверить, есть ли вывод.
Когда я хочу остановиться, я полагаю, что мне следует позвонить Mojo::IOLoop->remove($id)
, но это, похоже, не устраняет его полностью, и я получаю сообщения об ошибках типа Mojo::Reactor::Poll: Timer failed: Can't call method "is_websocket" on an undefined value
.
Если я вызываю finish
на объекте контроллера, чтобы закрыть веб-сокет, кажется, что все останавливается.
У меня есть все приложение Mojolicious :: Lite как суть, но здесь я
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;
}
Другие вопросы, на которые может быть полезен этот ответ: