Perl POE:警报/延迟排队

时间:2016-12-16 23:02:19

标签: perl poe

这是我第一次尝试Perl Object Environment(POE)。我正在尝试创建一个程序,它将作为一个服务运行,通过couchdb获取设备列表,生成子进程以60秒的间隔ping它们,同时将最大并发子进程数限制为3。

我能够在延迟(1分钟)后成功重新排队子进程,但是,我不知道如何管理调用同一事件的多个警报/延迟。我试图将它们存储在$_[HEAP]->{timers}->{$_} $_是给定主机的位置。

#!/usr/bin/perl

use warnings;
use strict;
use POE qw(Wheel::Run Filter::Reference);
use CouchDB::Client;
use Data::Dumper;

use constant MAX_CONCURRENT_TASKS => 3;

our $couch      = CouchDB::Client->new(uri => 'http://192.168.1.100:5984/')->newDB('devices');

POE::Session->create(
        inline_states => {
                _start      => sub {
                        push (@{$_[HEAP]->{devices}}, $couch->newDoc($_->id)->retrieve->id) for @{$couch->listDocs};
                        $_[KERNEL]->delay_set('refresh', 60);
                        $_[HEAP]->{timers}->{$_} = $_[KERNEL]->delay_set('spawn', 1, $_) for @{$_[HEAP]->{devices}};
                }, 
                refresh => sub { 
                        undef @{$_[HEAP]->{devices}};
                        $_[KERNEL]->delay_set('refresh', 60); 
                        push (@{$_[HEAP]->{devices}}, $couch->newDoc($_->id)->retrieve->id) for @{$couch->listDocs};
                        print "\nRefreshing device list.\n\n";
                }, 
                spawn   => sub { 
                        if (keys(%{$_[HEAP]->{task}}) < MAX_CONCURRENT_TASKS) { 
                                print "Starting $_[ARG0].\t # of tasks running: ". keys(%{$_[HEAP]->{task}}),$/;
                                my $host = $_[ARG0];
                                my $task = POE::Wheel::Run->new(        
                                        Program      => sub { \&do_stuff($host) },
                                        StdoutFilter => POE::Filter::Reference->new(),
                                        StdoutEvent  => "task_result",
                                        StderrEvent  => "task_debug",
                                        CloseEvent   => "task_done"
                                );
                                $_[HEAP]->{task}->{$task->ID} = $task;
                                $_[KERNEL]->sig_child($task->PID, "sig_child", $_[ARG0]) 
                        } else { 
                                $_[KERNEL]->delay_adjust($_[HEAP]->{timers}->{$_[ARG0]}, 5);
                        }
                        print Dumper 'spawn', sort $_[HEAP]->{timers};
                },
                task_result => sub { 
                        print "Result for $_[ARG0]->{task}: $_[ARG0]->{status}\n";
                },
                task_done   => sub { 
                        delete $_[HEAP]->{task}->{$_[ARG0]};
                },
                task_debug  => sub { 
                        print "Debug: $_[ARG0]\n";
                },
                sig_child   => sub { 
                        delete $_[HEAP]->{$_[ARG1]};
                        $_[HEAP]->{timers}->{$_[ARG3]} = $_[KERNEL]->delay_set('spawn', 60, $_[ARG3]) if $_[ARG3] ~~ $_[HEAP]->{devices};  
                        $_[KERNEL]->alarm_remove($_[HEAP]->{timers}->{$_[ARG0]});
                }
        }
);
sub do_stuff {
        binmode(STDOUT);
        my $filter = POE::Filter::Reference->new();

        sleep(rand 5);

        my %result = (
                task   => shift,
                status => "complete.",
        );

        my $output = $filter->put([\%result]);
        print @$output;
}
POE::Kernel->run();
exit 0;

欢迎任何建议/策略。

编辑1:我发现$_[KERNEL]->delay没有按每个孩子设置计时器。我可以使用$_[KERNEL]->delay_set来实现此功能。我现在无法拼凑的是如何限制程序在给定时间运行3个以上的进程。

我正在_start创建初始计时器。如果子进程计数为3或更高,则spawn被调用$_[KERNEL]->delay_adjust时应将延迟延长5秒。

为回答问题所花费的时间道歉,这存在于我的工作PC上,而这个编辑是在星期一,也就是我的第一天回来。

0 个答案:

没有答案