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/;