Question

I want a request to a Mojolicious application to be able to trigger a long running job. The client doesn't need to wait for that long job to finish, so I'd like the app to send back a quick response and start the job. Here's what I have in mind:

use Mojolicious::Lite;
get '/foo' => sub {
    my $self = shift;
    $self->render( text => 'Thanks for requesting /foo. I will get started on that.' );
    # ... force Mojolicious to send response now ...
    do_long_running_job();
};

But when I write the code like this, the client doesn't receive the response until after the long running job is finished (which may trigger inactivity timeouts, etc.). Is there any way to send the response more quickly? Is there another way to structure my code/app to achieve this?

Things from the docs that looked promising but didn't work:

$self->rendered(200);
$self->res->finish;
Was it helpful?

Solution

Randal Schwartz's Watching long processes through CGI should help:

The child goes on, but it must first close STDOUT, because otherwise Apache will think there might still be some output coming for the browser, and won't respond to the browser or release the connection until this is all resolved. Next, we have to launch a child process of the child to execute …

We'll do this with a pipe-open which includes an implicit fork, in line 37. The grandchild process merges STDERR to STDOUT, and then executes …

The child (that is, the parent of the traceroute) reads from the filehandle opened from the STDOUT (and STDERR) …

In short, the child process scurries off to execute the command. …

Given that you are only interested in kicking off a process rather than watching it, you should be able to prune most of the code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top