问候,
我正在学习Moose,而我正在尝试用Moose 编写一个CGI :: Application子类,由于CGI-App不是基于Moose而变得困难.
在我的其他CGI-App子类中,我喜欢让父类使用一个setup方法来查看子类的符号表并自动设置runmodes.我想我可以使用Moose的元类设施以更清洁的方式实现同样的目的.所以这是我在父类中的内容:
use MooseX::Declare;
class MyApp::CGI
extends Moose::Object
extends CGI::Application {
method setup {
$self->start_mode( 'main' );
my @methods = map { $_->name } $self->meta->get_all_methods;
$self->run_modes( map { /^rm_(.+)$/ => $_ }
grep { /^rm_/ }
@methods
);
}
}
Run Code Online (Sandbox Code Playgroud)
......在我的孩子班上:
use MooseX::Declare;
class MyApp::CGI::Login
extends MyApp::CGI {
method rm_main {
return "it works";
}
}
Run Code Online (Sandbox Code Playgroud)
我意识到我的runmodes没有正确设置的原因是因为setupCGI-App构造函数调用了Moose::Object它,并且在我的类中坚持自己的构造函数.我尝试用方法修饰符解决这个问题:
around new {
$self = $orig->( @_ );
$self->CGI::Application::new( …Run Code Online (Sandbox Code Playgroud) 我读过关于fork的内容,根据我的理解,该过程是克隆的但是哪个过程?脚本本身或启动脚本的进程?
例如:
我正在我的机器上运行rTorrent,当一个torrent完成时,我有一个脚本运行它.此脚本从Web获取数据,因此需要几秒钟才能完成.在此期间,我的rtorrent进程被冻结.所以我使用以下内容编写了脚本fork
my $pid = fork();
if ($pid == 0) { blah blah blah; exit 0; }
Run Code Online (Sandbox Code Playgroud)
如果我从CLI运行这个脚本,它会在一秒钟内回到shell,而它在后台运行,正如我想要的那样.但是,当我从rTorrent运行时,它似乎比以前更慢.究竟是什么分叉了?rtorrent进程是否克隆了自己并且我的脚本在那里运行,或者我的脚本是否克隆了自己?我希望这是有道理的.
有时我需要一个有用的实用函数,就像List::Util::max在大型程序中间做很多事情一样.所以,如果我这样做
use List::Util 'max';
Run Code Online (Sandbox Code Playgroud)
在我的程序的顶部,我坚持使用该符号,污染我的整个命名空间,即使我只需要在一个子程序中.
所以我一直在考虑尝试不同的模式,而是:
use List::Util ();
# a whole bunch of stuff later...
sub blah {
List::Util->import( 'max' );
$blah = max @foobar;
...
}
Run Code Online (Sandbox Code Playgroud)
但是,这有两个问题.首先,它不会在块结束时自动不进行操作(drat.)我将不得不撤消所有内容unimport.
另一个问题是,显然原型没有得到正确应用,所以我不得不说,max( @foobar )而不是更漂亮的无括号版本.
是否有一种简单的方法来临时导入块的符号,这将自动使它们在块的末尾消失,哪些也可以正确处理原型?
我想要除了阵列的前五个元素之外的所有元素,所以我愚蠢地做了:
@foo = @foo[ 0 .. 4 ];
Run Code Online (Sandbox Code Playgroud)
并衷心地称赞我自己的聪明才智.但是那次爆发@foo只有三个元素结束了,因为那时我最终得到了两个undefs,而不是一个三元素数组.所以我改成了:
@foo = @foo > 5 ? @foo[ 0 .. 4 ] : @foo;
Run Code Online (Sandbox Code Playgroud)
这有效,但有点难看.有没有更好的成语说"给我一切到阵列的前五个元素?"
我有一个非常长的字符串,其中包含许多新行(这是一个非常长的SQL语句).
当我用换行符分解它时,SQL更容易阅读.但有时,我需要从代码中复制sql语句以粘贴到sql developer中.
在Perl中,我总是喜欢qq运算符,您可以使用它来代替双引号:
你用它是这样的:
$myString = qq{
SELECT *
FROM table_a a
JOIN table_b b ON a.id = b.id ... etc
};
Run Code Online (Sandbox Code Playgroud)
JAVA中是否有等价物?我发现必须像这样分解字符串中的字符串很尴尬:
String myString = " SELECT * " +
" FROM table_a a " +
" JOIN table_b b ON a.id = b.id ... etc ";
Run Code Online (Sandbox Code Playgroud)
并且很难从代码中复制SQL语句.我最终不得不删除所有引号和+
是否有Java等价物?或者是否有更好的技巧将可读的,可复制的SQL语句放在Java代码中?
我有一个作业队列(使用Amazon SQS),它将作业交给许多机器,用于通过HTTP获取和处理各种文档.有数百个不同的主机被访问,并且没有可预测的作业顺序.
为了礼貌,我不希望我的系统在一台主机上反复敲击.因此,如果我得到一份工作#123从example.com获取某些内容,但我发现我在过去的X秒内刚刚从example.com获取了另一件事,我应该转向其他内容并保存作业#123 for后来.
问题是,实现这种模式的好方法是什么?
似乎第一步是让作业运行者在所有域的某个位置保留一个列表,并且最后一次访问该域上的某些内容.我想这可能是一个简单的数据库表.
如果消息处理器获得必须延迟的作业,则有许多可能的选项可用于执行操作.
只需将消息的副本推送到队列的末尾,然后将其丢弃而不执行它.希望在下一次出现时,足够的时间过去了.这可能会导致大量冗余SQS消息,尤其是在同一域的大型作业集群同时通过的情况下.
在礼貌要求可以执行工作之前,需要休息几秒钟.这可能导致许多队列处理器同时无所事事.
接受作业,但将其保存在每个队列处理器上的某个本地队列中.我想每个处理器都可以通过这种方式"声称"一些工作,然后选择以任何顺序处理它们以达到最大程度的礼貌.这仍然是不可预测的,因为每个队列处理器需要知道被其他所有域击中的域.
为每个域建立单独的队列,并为每个队列分配一个进程.每个进程都必须在执行每个作业之间暂停X秒,因此会有很多睡眠进程开销,但这可能不是一件坏事.
你有设计这种东西的经验吗?你会推荐什么策略?
parallel-processing perl design-patterns job-queue amazon-sqs
我有一些看起来像这样的东西:
my $report = new ReportGenerator; #custom object
my $dbh = $dbc->prepare('SELECT * FROM some_table WHERE some_condition'); #DBI handle
$dbh->execute();
while(my $href = $dbh->fetchrow_hashref){
$report->process_record($href);
}
$dbh->finish();
print $report->printReport();
Run Code Online (Sandbox Code Playgroud)
我的问题是循环的每次迭代都很慢.问题是MySQL.我想知道是否有可能在while循环中放置某种包装器以使其一次获取多个记录,同时将所有记录提取到内存中也是不实际的.我并不担心代码的效率(hashref vs arrayref等).相反,我有兴趣获取让我们一次说10000条记录.
该数据库有大约500万条记录.我无法更改/升级服务器.
谢谢
考虑以下:
package MyApp::CGI;
use Moose;
use MooseX::NonMoose;
use Data::Dumper;
extends 'CGI::Application';
BEGIN {
print "begin isa = " . Dumper \@MyApp::CGI::ISA;
};
print "runtime isa = " . Dumper \@MyApp::CGI::ISA;
...
Run Code Online (Sandbox Code Playgroud)
编译时的输出是:
begin isa = $VAR1 = [
'Moose::Object'
];
runtime isa = $VAR1 = [
'CGI::Application',
'Moose::Object'
];
Run Code Online (Sandbox Code Playgroud)
我为什么在意?因为当我尝试useCGI :: Application :: Plugin ::*类时,它希望我CGI::Application已经在编译时继承.插件类试图add_callback在我的类上调用类方法,但不能,因为我@ISA还没有设置.
解决这个问题的最佳方法是什么?@ISA在BEGIN块中手动调整是否会干扰MooseX::NonMoose?
编辑
以下似乎有效,但我发现它令人反感:
package MyApp::CGI;
use Moose;
use MooseX::NonMoose;
use base …Run Code Online (Sandbox Code Playgroud) 我有一个lazy_build属性的Moose类.该属性的值是另一个(非惰性)属性的函数.
假设某人为所需属性实例化了值为42的类.然后他们请求延迟属性,该属性计算为42的函数.然后,他们有勇气改变第一个属性!
懒惰的已经构建,因此不会再次调用构建器,并且lazy属性现在已过时.
我现在有一个解决方案,我在必需的属性上维护一个"脏"标志,懒惰的访问器检查脏标志并在需要时重建它.
但是,这似乎很多工作.有没有办法在Moose中处理这个问题,例如使用特征?
我最近看到一些代码提醒我提出这个问题.最近,我看到了很多这样的事情:
use Scalar::Util 'reftype';
if ( reftype $some_ref eq reftype { } ) { ... }
Run Code Online (Sandbox Code Playgroud)
调用reftype匿名hashref 的目的是什么?为什么不说呢eq 'HASH'?