【发布时间】:2019-02-22 21:20:16
【问题描述】:
我正在使用 Mojolicious 非阻塞方法 (Promises) 从外部系统请求数据。 1)我想立即通知用户该过程已经开始; 2) 我想扩展这个程序。
下面的代码适用于一小部分数字(几百个),如果数字更多,我会收到错误[error] Can't create pipe: Too many open files at /path/lib/perl5/Mojo/IOLoop.pm line 156.问题 1)我如何限制我生成的 Promise 的数量( map 在我下面的代码中):
#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojolicious::Plugin::TtRenderer;
sub isPrime
{
my ($n) = @_;
my $e = sqrt($n);
for (my $i=2; $i<$e; $i++) {
return 0 if $n%$i==0;
}
return 1;
}
sub makeApromise
{
my ($number) = @_;
my $promise = Mojo::Promise->new;
Mojo::IOLoop->subprocess(
sub { # first callback is executed in subprocess
my %response;
# Simulate a long computational process
$response{'number'} = $number;
$response{'isPrime'} = isPrime($number);
return \%response;
},
sub { # second callback resolves promise with subprocess result
my ($self, $err, @result) = @_;
return $promise->reject($err) if $err;
$promise->resolve(@result);
},
);
return $promise;
}
plugin 'tt_renderer'; # automatically render *.html.tt templates
any '/' => sub {
my ($self) = @_;
my $lines = $self->param( 'textarea' );
if ($lines) {
my @numbers;
foreach my $number (split(/\r?\n/, $lines)) {
push(@numbers, $number) if $number =~ /^\d+$/;
}
if (@numbers) {
####################################
### This is the problem below... ###
my @promises = map { makeApromise($_) } @numbers;
####################################
# MojoPromise Wait
Mojo::Promise->all(@promises)
->then(sub {
my @values = map { $_->[0] } @_;
foreach my $response (@values) {
#print STDERR $response->{'number'}, " => ", $response->{'isPrime'}, "\n";
# Prepare email...
}
# Send an email...
})
#->wait # Don't wait? I want to tell the user to wait for an email as quickly as possible...
if @promises;
}
$self->stash(done => "1",);
}
$self->render(template => 'index', format => 'html', handler => 'tt');
};
app->start;
__DATA__
@@ index.html.tt
<!DOCTYPE html>
<html lang="en">
<head>
<title>Make A Promise</title>
</head>
<body>
[% IF done %]
<h3>Thank you! You will receive an email shortly with the results.</h3>
[% ELSE %]
<h3>Enter numbers...</h3>
<form role="form" action="/" method="post">
<textarea name="textarea" rows="5" autofocus required></textarea>
<button type="submit">Submit</button>
</form>
[% END %]
</body>
</html>
我注释掉了wait;但是,代码似乎仍然处于阻塞状态。 问题 2) 我怎样才能立即通知用户该过程已经开始? (即当我stash done 变量时)
【问题讨论】:
-
我可能不明白这里的一些东西——为什么你不能通过限制
@numbers提交到map来限制它(管理它们的提交方式)?另外,你究竟是如何运行这一切的?它让我崩溃了。 -
@zdim,你需要像
[02:54:26 abhasker@wsl -> temp$ morbo bug.plOUTPUT:Server available at http://127.0.0.1:3000this 一样运行它。 -
@h-q,我用大约 5000 个输入数字运行了这个,花了一些时间,但没有发现问题,用户收到以下消息:谢谢!您将很快收到一封包含结果的电子邮件。
-
@AbhiNickz,我如何才能立即收到“谢谢!您将收到一封电子邮件...”消息,而不是在一段时间后?另外为了测试,我使用了 11 位数字,例如使用 '99999999977' 10,000 次。
-
@zdim,你能提供一个如何限制
@numbers提交给map的例子吗?
标签: multithreading perl promise subprocess mojolicious