We have a library that uses AnyEvent already. It uses AnyEvent internally and in the end it returns a value (synchronously - not with a callback). Is there any way I can use this library with Mojolicious?
It does something like:
#!/usr/bin/perl
use strict;
use warnings;
use AnyEvent;
use Mojolicious::Lite;
# To the caller, getData is a synchronous sub that returns a value.
# The fact that it uses AnyEvent is an internal implementation detail of
# getData
sub getData {
my $cv = AnyEvent->condvar;
my $w = AnyEvent->timer (after => 5, cb => sub {
# Perform many async operations, represented here by a single timer,
# calculating a final result that is sent:
$cv->send(42);
});
my $result = $cv->recv;
# postProcess($result);
return $result;
}
get '/' => sub {
my ($c) = @_;
$c->render(text => "Data is: " . getData());
};
app->start;
When I run morbo app.pl
and try to get '/'
from two browser tabs at the same time I get this error:
AnyEvent::CondVar: recursive blocking wait attempted at /bla/bla/app.pl line 16.
What I think is going on is that morbo uses EV internally and so when it dispatches to handle the first get '/'
, $cv->recv
ends up getting called, returning to the EV event loop. EV now tries to handle the second get '/'
and $cv->resv
is called again, triggering the error.
I know I can refactor the $cv
out of getData()
to make an asynchronous version, but in reality the real "getData" is called in many places and turning all calls to "getData" into async code is not feasible.
So my question is: Is there any way I can call the exact getData()
above reliably while using morbo
/Mojolicious? I'd like get '/'
to block until it is done.
Edit: The AnyEvent's WHAT TO DO IN A MODULE section explicity says:
Never call ->recv on a condition variable unless you know that the ->send method has been called on it already. This is because it will stall the whole program, and the whole point of using events is to stay interactive.
getData()
above violates that. Now I understand the reason for that part of the AnyEvent documentation :-)