I'm interested in POE developers' comments about state management.  Possibly
my ideas about implementation are on a different track than others', but I
found that in order to make my app 'POE-ized', I took what was essentially a
set of related (by concept) actions, and put two states for each in my
session:

start_get_hits() {

    # already loading... ignore
    return if $heap->{loading_due};

    # set up a state marker in $heap
    DEBUG && print "$object received get_hits\n";

    # do something interesting here.
    $heap->{loading_due} = 1;
    $heap->{due_start} = time;

    # in my case, this is a database query:
    $heap->{current_query}->execute();

    print "$object start_get_hits execute complete in ",
      time - $heap->{due_start}  ," seconds\n" if DEBUG_TIME;

    # queue up reading rows
    $kernel->yield('get_row');
}

and then, get_row does a few fetches off of the DBH handle, and re-queues
itself.  When the handle is out of rows, it deletes the state marker in the
$heap, and calls:

        $kernel->yield('get_row') if exists $heap->{loading_due};

So, this is the general methodology I use for long-running tasks, to
timeslice them.

What do *YOU* do?

My other state management issue is on the concept of deferral... for some
states, we want to delay and re-issue the SAME STATE as we were JUST
INVOKED, if the session is busy with another task that we depend on.  My app
is a daemon that pre-fetches info from my database so that each web hit
doesn't have to fire off another dbi session, and if the database goes down
for 2 minutes for maintenance, I don't lock my entire service.

SO, while the app is still loading (see above code!), requests will probably
already be coming in, but I don't yet have the data to deal with them.  My
idea was to re-queue the state w/ the same data:

sub mark_exposure {

    my ($object, $kernel, $heap, $acctid, $cat) =
      @_[OBJECT, KERNEL, HEAP, ARG0, ARG1];

    if ( $heap->{loading_due} &&
         not exists $hits{$acctid}
       ) {

        DEBUG && print "Delaying mark_exposure\n";
        $kernel->delay_add( mark_exposure => 1, $acctid );
        return;
    }
...
}

This approach leaves me with a bunch of queued mark_exposure() states that
never seem to clear.

In a different function, I tried this one:

sub fetch {
    my ($object, $kernel, $heap, $sender, $postback, $acctid, @list) =
      @_[OBJECT, KERNEL, HEAP, SENDER, ARG0, ARG1..$#_];

    if ($heap->{loading_due} and not exists $hits{$acctid}) {
        $kernel->post( fetch => @_[ARG0..$#_] );
          return;
    }

    ...
}

this seems to work, but I worry that I'm slowing down my init a LOT by
having all of these "pending" states to service (read, context switch back
and forth, constantly re-posting) while simultaneously trying to run
get_row() repeatedly.  Since these deferred calls are blocking my webserver
until they return, I'm a bit worried about performance.

Suggestions?  Am I worried too much about it?  What are some other
approaches people have used?

TIA!!!

L8r,
Rob

#!/usr/bin/perl -w
use Disclaimer qw/:standard/;


Reply via email to