Задержка ответа на команду косой черты с Mojolicious в Perl - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь создать слабое приложение на Perl с mojolicious, и у меня следующий сценарий использования:

Slack отправляет запрос в мой API из команды слэша и требует ответа в течение 3 секунд. Тем не менее, Slack также дает мне возможность отправить до 5 дополнительных ответов в течение 30-минутного периода, но все еще нуждается в первоначальном ответе через 3 секунды (он просто отправляет "late_response_url" при первоначальном обратном вызове, чтобы я мог что-то POST к этому URL позже). В моем случае я хотел бы отправить начальный ответ Slack, чтобы сообщить пользователю, что операция «выполняется», и через некоторое время отправить фактический результат моей медленной функции в Slack.

В настоящее время я могу сделать это, порождая второй процесс с использованием fork () и используя один процесс для немедленного ответа, как того требует Slack, а второй - для выполнения остальной части работы и ответа позже.

Я пытаюсь сделать это с помощью подпроцессов Mojolicious, чтобы избежать использования fork (). Однако я не могу найти способ заставить это работать ....

пример кода того, что я уже делаю с 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 Ответ

0 голосов
/ 13 сентября 2018

На самом деле я только что нашел решение своей проблемы!

Итак, вот мое решение:

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 в первый обратный вызов (для того, чтобы он выполнялся как подпроцесс), а второй обратный вызов (который на самом деле связан с родительским процессом) используется в качестве фиктивного, и я оставляю мой «немедленный» ответ в основной части всей функции вместо того, чтобы помещать его в одинподпроцессов.См. Комментарии к коду для получения дополнительной информации!

...