madbombX has asked for the wisdom of the Perl Monks concerning the following question:

I have a POE job server that I wrote using POE's POE::Filter::Reference and POE::Wheel::Run. (Note: This is my first attempt with POE). Everything runs just fine with regard to grabbing the next task from the MySQL server and starting the task, running the task, and so on.

The issue I am having is that every hour (or even after X processes), I want to run some cleanup methods. I am currently running them as cronjobs through the shell. This method works well enough, but I want some of the information from the parent process to be accessible to the cleanup code.

How can I create a session that runs off the parent that will either inject itself every X processes and run the cleanup code OR create a separate session that runs the cleanup code, sleeps, repeat OR create a separate session off the parent that runs every hour. All of this needs to happen in a non-blocking state of the other jobs.

Here is some relevant code (everything below works):

sub handle_task_result { my ($result) = $_[ARG0]; $LOG->debug("Result: $result"); } sub handle_task_debug { my ($result) = $_[ARG0]; $LOG->debug("Debug: $result"); } sub handle_task_done { my ($kernel, $heap, $task_id) = @_[ KERNEL, HEAP, ARG0 ]; delete $heap->{task}->{$task_id}; $kernel->yield("next_task"); } sub Run_Job { my ($task) = shift; my ($filter) = POE::Filter::Reference->new(); # ... stuff ... return; } sub start_tasks { my ($heap) = $_[HEAP]; while ( keys( %{ $heap->{task} } ) < MAX_CONCURRENT_TASKS ) { # Returns an array_ref from the select call to the job table my $next_task = Get_Next_Task(); # If we don't have a task, sleep and one will come do { sleep 10; next; } unless exists $next_task->{'id'}; $LOG->debug("Starting task for $next_task->{'url'}...\n"); my ($task) = POE::Wheel::Run->new( Program => sub { Run_Job($next_task) }, StdoutFilter => POE::Filter::Reference->new(), StdoutEvent => "task_result", StderrEvent => "task_debug", CloseEvent => "task_done", ); $heap->{task}->{ $task->ID } = $task; } } # Setup the POE session if we are in daemon mode POE::Session->create( inline_states => { _start => \&start_tasks, next_task => \&start_tasks, task_result => \&handle_task_result, task_done => \&handle_task_done, task_debug => \&handle_task_debug, } ); POE::Kernel->run();

Replies are listed 'Best First'.
Re: POE Sleep Process
by shmem (Chancellor) on Dec 15, 2007 at 23:25 UTC
    How can I create a session that runs off the parent that will either inject itself every X processes and run the cleanup code OR create a separate session that runs the cleanup code, sleeps, repeat OR create a separate session off the parent that runs every hour. All of this needs to happen in a non-blocking state of the other jobs.

    With regard to the title of your post, in the Cookbook, there's an entry /Waiting.

    For setting up a cron(8)-like session, have a look into the OSCON 2004 Example programs folder.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: POE Sleep Process
by glide (Pilgrim) on Dec 17, 2007 at 18:14 UTC
    Hi,

    If you don't need a new fork, with the POE::Wheel::Run, you can try this ..

    Create a new inline_states in the POE::Session->create
    clean_db => \&clean_db_h,
    and in the method, call the delay method like this
    sub clean_db_h { # do all the clean needed in the db # # next clean in 3600 sec $_[KERNEL]->delay( clean_db => 3600); };
    With this, your clean_db method will be called every hour.