在 Perl 中使用 Mojolicious 对斜杠命令的延迟响应
Delayed response to slash command with Mojolicious in Perl
我正在尝试使用 mojolicious 在 Perl 中创建一个 slack 应用程序,我有以下用例:
Slack 通过斜杠命令向我的 API 发送了一个请求,需要在 3 秒内得到响应。然而,Slack 也让我有机会在 30 分钟的时间范围内发送最多 5 个响应,但仍然需要 3 秒内的初始响应(它只是在初始回叫中发送 "late_response_url" 这样我就可以 POST 稍后 url 的内容)。在我的例子中,我想向 slack 发送一个初始响应,以通知用户该操作是 "running" 并在一段时间后将我的慢速函数的实际结果发送给 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 的子进程复制完全相同的代码。有什么想法吗?
提前致谢!
实际上我刚刚找到了解决问题的方法!
所以这是我的解决方案:
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 代码放在第一个回调中(以便它 运行 作为子进程)并使用第二个回调(实际上链接到父进程)作为一个虚拟进程,并将我的 "imidiate" 响应保留在整个函数的主体中,而不是将其放在子进程之一中。请参阅代码注释以获取更多信息!
我正在尝试使用 mojolicious 在 Perl 中创建一个 slack 应用程序,我有以下用例:
Slack 通过斜杠命令向我的 API 发送了一个请求,需要在 3 秒内得到响应。然而,Slack 也让我有机会在 30 分钟的时间范围内发送最多 5 个响应,但仍然需要 3 秒内的初始响应(它只是在初始回叫中发送 "late_response_url" 这样我就可以 POST 稍后 url 的内容)。在我的例子中,我想向 slack 发送一个初始响应,以通知用户该操作是 "running" 并在一段时间后将我的慢速函数的实际结果发送给 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 的子进程复制完全相同的代码。有什么想法吗?
提前致谢!
实际上我刚刚找到了解决问题的方法!
所以这是我的解决方案:
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 代码放在第一个回调中(以便它 运行 作为子进程)并使用第二个回调(实际上链接到父进程)作为一个虚拟进程,并将我的 "imidiate" 响应保留在整个函数的主体中,而不是将其放在子进程之一中。请参阅代码注释以获取更多信息!