Вы должны использовать FCGI
реализацию, которая обрабатывает FCGI_ABORT_REQUEST
.
Вы не можете использовать следующее, потому что они игнорируют FCGI_ABORT_REQUEST
:
Вы могли бы использовать следующее, которое обрабатывает FCGI_ABORT_REQUEST
:
При использовании AnyEvent-FCGI
проверка прерванного запроса так же проста, как и вызов $request->is_active()
, но имейте в виду, что is_active()
не будет отражать истинное состояние запроса, пока не вернется обработчик on_request
, что означает вы должны вернуться из on_request
как можно скорее и как-то выполнить реальную работу "параллельно" (вы, вероятно, не хотите использовать потоки Perl , но что-то более похожее на продолжения ), чтобы дать циклу AnyEvent
возможность обрабатывать любые дальнейшие запросы (включая FCGI_ABORT_REQUEST
с), пока вы выполняете длительные операции.
Я недостаточно знаком с AnyEvent
, чтобы точно знать, есть ли лучший способ сделать это, но вот мой пример, ниже, для начала:
use AnyEvent;
use AnyEvent::FCGI;
my @jobs;
my $process_jobs_watcher;
sub process_jobs {
# cancel aborted jobs
@jobs = grep {
if ($_->[0]->is_active) {
true
} else {
# perform any job cleanup
false
}
} @jobs;
# any jobs left?
if (scalar(@jobs)) {
my $job = $jobs[0];
my ( $job_request, $job_state ) = @$job;
# process another chunk of $job
# if job is done, remove (shift) from @jobs
} else {
# all jobs done; go to sleep until next job request
undef $process_jobs_watcher;
}
}
my $fcgi = new AnyEvent::FCGI(
port => 9000,
on_request => sub {
my $request = shift;
if (scalar(@jobs) < 5) { # set your own limit
# accept request and send back headers, HTTP status etc.
$request.print_stdout("Content-Type: text/plain\nStatus: 200 OK\n\n");
# This will hold your job state; can also use Continutiy
# http://continuity.tlt42.org/
my $job_state = ...;
# Enqueue job for parallel processing:
push @jobs, [ $request, $job_state ];
if (!$process_jobs_watcher) {
# If and only if AnyEvent->idle() does not work,
# use AnyEvent->timer() and renew from process_jobs
$process_jobs_watcher = AnyEvent->idle(cb => \&process_jobs);
}
} else {
# refuse request
$request.print_stdout("Content-Type: text/plain\nStatus: 503 Service Unavailable\n\nBusy!");
}
}
);
AnyEvent->loop;