在Perl中使用Mojolicious延迟响应斜线命令

时间:2018-09-13 11:59:15

标签: perl slack-api mojolicious mojolicious-lite

我正在尝试使用mojolicious在Perl中创建一个松弛应用程序,并且具有以下用例:

Slack从斜杠命令向我的API发送请求,并需要3秒钟的响应时间。但是,Slack还使我有机会在30分钟的时间内发送多达5个响应,但仍需要3秒的初始响应(它只是在初始回调中发送“ late_response_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 :(得分:3)

实际上我只是找到了解决问题的方法!

这是我的解决方法:

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_using_things的代码放在第一个回调中(以使其作为子进程运行),然后将第二个回调(实际上链接到父进程)用作虚拟回调并保留我的“模仿”响应位于整个函数的主体中,而不是将其放入子过程之一中。有关更多信息,请参见代码注释!