Reputation: 354
I'm trying to build a timeout scenario in my Catalyst, AnyEvent, Websocket app. For that I'm using
AnyEvent->timer
which should be called after let's say a few seconds of inactivity (no more WS frames coming in).
The problem is, that my timer is never executed:
my $w = AnyEvent->timer (after => 3,
cb => sub {
warn "TIMEOUT!";
});
$self->{server} = Protocol::WebSocket::Handshake::Server->new_from_psgi(
$c->req->env) or die $c->log->fatal($!);
$self->{handle} = AnyEvent::Handle->new(
fh => $c->req->io_fh,
on_error => sub {
my ($hd, $fatal, $msg) = @_;
$clean_up->();
}
);
die $c->log->fatal("WS Server error: '$_'")
if $self->{server}->error;
$self->{server}->parse($self->{handle}->fh);
$self->{handle}->push_write($self->{server}->to_string);
$self->{handle}->on_read(sub {
(my $frame = $self->{server}->build_frame)->append($_[0]->rbuf);
while (my $frame_msg = $frame->next) {
...
}
The timer callback is never executed. My guess would be, that the timer doesn't work inside another Event loop (AnyEvent::Handle)?
Upvotes: 4
Views: 620
Reputation: 464
Are you actually getting into the event loop for the timer to be processed? Your code snippet does not indicate this.
Also, AnyEvent::Handle has inactivity timeouts built-in:
timeout => $fractional_seconds If non-zero, then this enables an "inactivity" timeout: whenever this many seconds pass without a successful read or write on the underlying file handle, the "on_timeout" callback will be invoked (and if that one is missing, a non-fatal "ETIMEDOUT" error will be raised). Note that timeout processing is also active when you currently do not have any outstanding read or write requests: If you plan to keep the connection idle then you should disable the timout temporarily or ignore the timeout in the "on_timeout" callback, in which case AnyEvent::Handle will simply restart the timeout. Zero (the default) disables this timeout. on_timeout => $cb->($handle) Called whenever the inactivity timeout passes. If you return from this callback, then the timeout will be reset as if some activity had happened, so this condition is not fatal in any way.
Upvotes: 3