Задержка ответа на команду косой черты с Mojolicious в Perl
Я пытаюсь создать слабое приложение на Perl с mojolicious, и у меня есть следующий вариант использования:
Slack отправляет запрос в мой API из команды слэша, и ему требуется ответ в течение 3 секунд. Тем не менее, Slack также дает мне возможность отправить до 5 дополнительных ответов в течение 30-минутного периода, но все еще нуждается в первоначальном ответе в течение 3 секунд (он просто отправляет "late_response_url" при первоначальном обратном вызове, чтобы я мог что-то POST к этому URL позже). В моем случае я хотел бы отправить начальный ответ slack, чтобы сообщить пользователю, что операция "выполняется", и через некоторое время отправить фактический результат моей медленной функции в Slack.
В настоящее время я могу сделать это, порождая второй процесс с использованием fork() и используя один процесс для немедленного ответа, как того требует Slack, а второй - для выполнения остальной части работы и ответа позже.
Я пытаюсь сделать это с подпроцессами Mojolicious, чтобы избежать использования fork(). Однако я не могу найти способ заставить это работать....
пример кода того, что я уже делаю с форком, выглядит так:
sub withpath
{
my $c = shift;
my $user = $c->param('user_name');
my $response_body = {
response_type => "ephemeral",
text => "Running for $user:",
attachments => [
{ text => 'analyze' },
],
};
my $pid = fork();
if($pid != 0){
$c->render( json => $response_body );
}else{
$output = do_time_consuming_things()
$response_body = {
response_type => "in-channel",
text => "Result for $user:",
attachments => [
{ text => $output },
],
};
my $ua = Mojo::UserAgent->new;
my $tx = $ua->post(
$response_url,
{ Accept => '*/*' },
json => $response_body,
);
if( my $res = $tx->success )
{
print "\n success \n";
}
else
{
my $err = $tx->error;
print "$err->{code} response: $err->{message}\n" if $err->{code};
print "Connection error: $err->{message}\n";
}
}
}
Так что проблема в том, что, как бы я ни пытался, я не мог воспроизвести точно такой же код с подпроцессами Mojolicious. Есть идеи?
Заранее спасибо!
1 ответ
На самом деле я только что нашел решение своей проблемы!
Итак, вот мое решение:
my $c = shift; #receive request
my $user = $c->param('user_name'); #get parameters
my $response_url = $c->param('response_url');
my $text = $c->param('text');
my $response_body = { #create the imidiate response that Slack is waiting for
response_type => "ephemeral",
text => "Running for $user:",
attachments => [
{ text => 'analyze' },
],
};
my $subprocess = Mojo::IOLoop::Subprocess->new; #create the subprocesses
$subprocess->run(
sub {do_time_consuming_things($user,$response_url,$text)}, #this callback is the
#actuall subprocess that will run in background and contains the POST request
#from my "fork" code (with the output) that should send a late response to Slack
sub {# this is a dummy subprocess doing nothing as this is needed by Mojo.
my ($subprocess, $err, @results) = @_;
say $err if $err;
say "\n\nok\n\n";
}
);
#and here is the actual imidiate response outside of the subprocesses in order
#to avoid making the server wait for the subprocess to finish before responding!
$c->render( json => $response_body );
Так что мне просто пришлось поместить свой код do_time_consuming_things в первый обратный вызов (для того, чтобы он выполнялся как подпроцесс) и использовать второй обратный вызов (который на самом деле связан с родительским процессом) в качестве фиктивного и оставить мой "непосредственный" "ответ в основной части всей функции вместо помещения ее в один из подпроцессов. Смотрите комментарии к коду для получения дополнительной информации!