PApp
view release on metacpan or search on metacpan
PApp/Event.pm view on Meta::CPAN
This module allows you to broadcast asynchroneous events to all other papp
applications.
Why is this useful? A common scenario is this: Often you want to implement
some internal data caching. PApp itself caches it's translation files,
content management systems often cache frequently-used content objects.
Whenever these caches are invalidated, one papp application (or an
external program) needs to signal all running application instances (maybe
even on multiple machines) to delete all or some specific cache entry.
This is what this module is for.
=over 4
=cut
package PApp::Event;
require 5.006;
use PApp::SQL;
use PApp::Config qw(DBH $DBH); DBH;
use PApp::Exception ();
use Compress::LZF ':freeze';
$VERSION = 2.4;
our $event_count;
=item on "event_type" => \&coderef
Register a handler that is called on the named event. The handler will
receive the C<event_type> as first argument. The remaining arguments
consist of all the scalars that have been broadcasted (i.e. multiple
events of the same type get "bundled" into one call), sorted in the order
of submittal, i.e. the newest event data comes last.
When called in a scalar context (as opposed to void context), it returns
an a handler id. When this handler id is destroyed (e.g. by going out of
scope), the handler itself will be removed.
The current contents of $PApp::SQL::Database/DBH will be saved and
restored while the handler runs.
=cut
sub PApp::Event::handler::DESTROY {
my $handlers = $handler{$_[0][0]};
for (0 .. $#handlers) {
if ($handlers[$_] == $_[0][1]) {
splice @$handlers, $_, 1;
return;
}
}
}
sub on($&) {
my $handler = [$_[1], $PApp::SQL::Database];
push @{$handler{$_[0]}}, $handler;
no warnings;
return bless [ $_[0], $handler ], PApp::Event::handler:: if defined wantarray;
}
=item broadcast "event_type" => $data[, $data...]
Broadcast an event of the named type, together with any number of scalars
(each representing a single event!). The event handlers registered in
the current process for the given type will be executed before this call
returns, other events might or might not be processed. If you want to
force processing of events, call C<PApp::Event::check>.
=cut
sub broadcast($;@) {
my $event = shift;
my $id;
sql_exec $DBH, "lock tables event write, event_count write";
for (@_) {
#use PApp::Util; print STDERR "broadcast $event: ", PApp::Util::dumpval $_, "\n";#d#
$id = sql_insertid sql_exec $DBH,
"insert into event (id, ctime, event, data) values (NULL,NULL,?,?)",
$event, sfreeze_cr $_;
}
sql_exec $DBH, "update event_count set count = ? where count < ?", $id, $id;
sql_exec $DBH, "unlock table";
if (@_) {
$id > $event_count
or die "FATAL: event table corrupted; new id $id <= current event_count $event_count";
handle_events ($id) if @_;
}
}
sub skip_all_events {
$event_count = eval { sql_fetch $DBH, "select count from event_count" };
}
skip_all_events;
=item check
Check for any outstanding events and execute them, if any.
=cut
sub check() {
handle_events (sql_fetch $DBH, "select count from event_count");
}
sub handle_event {
( run in 2.861 seconds using v1.01-cache-2.11-cpan-b16cb0d3907 )