I have a slow HTTP service I'm writing a proxy for. If I hit the service 
directly using curl, it looks like this:

$ time curl http://localhost:3333/?timer=10
{"message":"waited 10 seconds"}
real 0m10.018s
user 0m0.005s
sys 0m0.005s


I can hit it at 14s:

$ time curl http://localhost:3333/?timer=14
{"message":"waited 14 seconds"}
real 0m14.019s
user 0m0.005s
sys 0m0.005s


And at 16s:

$ time curl http://localhost:3333/?timer=16
{"message":"waited 16 seconds"}
real 0m16.018s
user 0m0.005s
sys 0m0.005s


I wrote a Mojolicious proxy for the slow service:

use Mojolicious::Lite;

get '/slow' => sub {
    my $c = shift;
    my $timer = $c->param('timer') // 10;
    $c->render_later;

    my $url = Mojo::URL->new('http://localhost:3333');
    $url->query(timer => $timer);

    app->log->debug("Invoking " . $url->to_string);
    
$c->ua->inactivity_timeout(60)->connect_timeout(60)->request_timeout(60)->get($url,
 
sub {
        my $tx = pop;
        $c->render(json => $tx->res->json);
    });
};

app->start;


You can see my various *_timeout() invocations on the user agent. If I hit 
the proxy, I get what I expect at 14s:

$ curl --include http://localhost:3000/slow?timer=14
HTTP/1.1 200 OK
Content-Length: 31
Server: Mojolicious (Perl)
Date: Tue, 05 Sep 2017 20:00:04 GMT
Content-Type: application/json;charset=UTF-8

{"message":"waited 14 seconds"}


But at 16s I get a timeout error:

$ curl --include http://localhost:3000/slow?timer=16
curl: (52) Empty reply from server


Indeed, the proxy's log shows the request and then a timeout 15s after the 
request:

[Tue Sep  5 14:00:45 2017] [debug] Invoking http://localhost:3333?timer=16
[Tue Sep  5 14:01:00 2017] [debug] Inactivity timeout
Mojo::Reactor::Poll: I/O watcher failed: Connection already closed at 
utils/slow-wrap line 15.


There's something magic about 15s.  I added the various timeouts on the 
user agent, so something else is timing out. I suspect it may be the 
default timeout in the Mojo::IOLoop::Stream constructor:

sub new { shift->SUPER::new(handle => shift, buffer => '', timeout => 15) }


If I start my proxy with MOJO_INACTIVITY_TIMOUT=60, then the proxy does 
*not* timeout:

$ curl --include http://localhost:3000/slow?timer=16
HTTP/1.1 200 OK
Content-Length: 31
Server: Mojolicious (Perl)
Content-Type: application/json;charset=UTF-8
Date: Tue, 05 Sep 2017 20:04:50 GMT

{"message":"waited 16 seconds"}


And the proxy logs are clean:

$ MOJO_INACTIVITY_TIMEOUT=60 ct utils/slow-wrap daemon
[Tue Sep  5 14:04:28 2017] [info] Listening at "http://*:3000";
Server available at http://127.0.0.1:3000
[Tue Sep  5 14:04:34 2017] [debug] GET "/slow"
[Tue Sep  5 14:04:34 2017] [debug] Routing to a callback
[Tue Sep  5 14:04:34 2017] [debug] Invoking http://localhost:3333?timer=16
[Tue Sep  5 14:04:50 2017] [debug] 200 OK (16.012817s, 0.062/s)


My question is: how can I determine what timeout is being triggered at 15s, 
and how can I change it on a per-request basis? I don't want to set that 
timeout for the entire proxy (I do want other slow calls to timeout)—just 
this particular controller. Is that possible? I've seen various email 
threads that recommend adding something like to the controller (before 
invoking the user-agent):

Mojo::IOLoop->stream($c->tx->connection)->timeout(60);


which seems to work in this situation, but I'm unsure this is the right 
approach. Is there a better mechanism for this? Will this hold up for many 
requests in the event loop at once?

Scott

-- 
You received this message because you are subscribed to the Google Groups 
"Mojolicious" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

Reply via email to