From ce35e7f988700e4858aa25814a185fea9e4281b6 Mon Sep 17 00:00:00 2001 From: miker Date: Sat, 31 Jan 2009 22:04:33 +0000 Subject: [PATCH] non-grouped event firing, event locating and grouping git-svn-id: svn://svn.open-ils.org/ILS/trunk@12025 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../src/perlmods/OpenILS/Application/Trigger.pm | 208 +++++++++++++++++++++ .../perlmods/OpenILS/Application/Trigger/Event.pm | 88 +++++++-- 2 files changed, 284 insertions(+), 12 deletions(-) diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Trigger.pm b/Open-ILS/src/perlmods/OpenILS/Application/Trigger.pm index b2f47d9d07..dd2beb65da 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Trigger.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Trigger.pm @@ -7,6 +7,10 @@ use OpenSRF::EX qw/:try/; use OpenSRF::AppSession; use OpenSRF::Utils::SettingsClient; use OpenSRF::Utils::Logger qw/:level/; +use OpenSRF::Utils qw/:datetime/; + +use DateTime; +use DateTime::Format::ISO8601; use OpenILS::Utils::Fieldmapper; use OpenILS::Utils::CStoreEditor q/:funcs/; @@ -18,4 +22,208 @@ my $log = 'OpenSRF::Utils::Logger'; sub initialize {} sub child_init {} +sub create_events_for_object { + my $self = shift; + my $client = shift; + my $key = shift; + my $target = shift; + my $location = shift; + + my $ident = $target->Identity; + my $ident_value = $target->$ident(); + + my $editor = new_editor(xact=>1); + + my $hooks = $editor->search_action_trigger_hook([ + { key => $key, + core_type => $target->json_hint + }, + { idlist => 1 } + ]); + + my %hook_hash = map { ($_->id, $_) } @$hooks; + + my $orgs = $editor->json_query({ from => [ 'actor.org_unit_ancestors' => $location ] }); + my $defs = $editor->search_action_trigger_event_definition([ + { hook => $hooks, + owner => [ map { $_->{id} } @$orgs ], + active => 't' + }, + { idlist => 1 } + ]); + + for my $def ( @$defs ) { + + my $date = DateTime->now; + + if ($hook_hash{$def->hook}->passive eq 'f') { + + if (my $dfield = $def->delay_field) { + if ($target->$dfield()) { + $date = DateTime::Format::ISO8601->new->parse_datetime( clense_ISO8601($target->$dfield) ); + } else { + next; + } + } + + $date->add( seconds => interval_to_seconds($def->delay) ); + } + + my $event = Fieldmapper::action_trigger::event->new(); + $event->target( $ident_value ); + $event->event_def( $def->id ); + $event->run_time( $date->strftime( '%G %T%z' ) ); + + $event = $editor->create_action_trigger_event( $event ); + + $client->respond( $event->id ); + } + + $editor->commit; + + return undef; +} +__PACKAGE__->register_method( + api_name => 'open-ils.trigger.event.autocreate', + method => 'create_events_for_object', + api_level=> 1, + stream => 1, + argc => 3 +); + + +sub fire_single_event { + my $self = shift; + my $client = shift; + my $event_id = shift; + + my $e = OpenILS::Application::Trigger::Event->new($event_id); + + if ($e->validate->valid) { + $e->react->cleanup; + } + + return { + valid => $e->valid, + reacted => $e->reacted, + cleanedup => $e->cleanedup, + event => $e->event + }; +} +__PACKAGE__->register_method( + api_name => 'open-ils.trigger.event.fire', + method => 'fire_single_event', + api_level=> 1, + argc => 1 +); + +sub run_events { + my $self = shift; + my $client = shift; + my $events = shift; # expects events ready for reaction + + my $env = {}; + if (ref($events) eq 'ARRAY') { + $$evn{target} = []; + $$evn{event} = []; + for my $e ( @$events ) { + for my $evn_part ( keys %{ $e->environment } ) { + if ($env_part eq 'target') { + push @{ $$evn{target} }, $e->environment->{target}; + } elsif ($env_part eq 'event') { + push @{ $$evn{event} }, $e->environment->{event}; + } else { + push @{ $$evn{$evn_part} }, $e->environment->{$evn_part}; + } + } + } + } else { + $env = $events->environment; + $events = [$events]; + } + + my @event_list; + for my $e ( @$events ) { + next unless ($e->valid); + push @event_list, $e; + } + + $event_list[0]->react( $env ); + $event_list[0]->cleanup( $env ); + + return { + reacted => $event_list[0]->reacted, + cleanedup => $event_list[0]->cleanedup, + events => @event_list == 1 ? $event_list[0] : \@event_list + }; +} +__PACKAGE__->register_method( + api_name => 'open-ils.trigger.event.run_validated', + method => 'fire_single_event', + api_level=> 1, + argc => 1 +); + + +sub pending_events { + my $self = shift; + my $client = shift; + + my $editor = new_editor(); + + return $editor->search_action_trigger_event([ + { state => 'pending', run_time => {'<' => 'now'} }, + { idlist=> 1 } + ]); +} +__PACKAGE__->register_method( + api_name => 'open-ils.trigger.event.find_pending', + method => 'pending_events', + api_level=> 1 +); + + +sub grouped_events { + my $self = shift; + my $client = shift; + + my ($events) = $self->method_lookup('open-ils.trigger.event.find_pending')->run(); + + my %groups = ( '*' => [] ); + + for my $e_id ( @$events ) { + my $e = OpenILS::Application::Trigger::Event->new($e_id); + if ($e->validate->valid) { + if (my $group = $event->event->event_def->group_field) { + + # split the grouping link steps + my @steps = split '.', $group; + + # find the grouping object + my $node = $event->target; + $node = $node->$_() for ( @steps ); + + # get the pkey value for the grouping object on this event + my $node_ident = $node->Identity; + my $ident_value = $node->$node_ident(); + + # push this event onto the event+grouping_pkey_value stack + $groups{$e->event->event_def->id}{$ident_value} ||= []; + push @{ $groups{$e->event->event_def->id}{$ident_value} }, $e_id; + } else { + # it's a non-grouped event + push @{ $groups{'*'} }, $e_id; + } + } + } + + return \%groups; +} +__PACKAGE__->register_method( + api_name => 'open-ils.trigger.event.found_by_group', + method => 'grouped_events', + api_level=> 1 +); + + 1; diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm b/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm index c2df13232f..5f037d8e45 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm @@ -35,13 +35,38 @@ sub init { $self->id, { flesh => 2, flesh_fields => { - atev => [ 'event_def' ], - atevdef => [ 'hook' ] + atev => [ qw/event_def/ ], + atevdef => [ qw/hook env params/ ] } } ]) ); + if ($self->event->state eq 'valid') { + $self->valid(1); + } elsif ($self->event->state eq 'invalid') { + $self->valid(0); + } elsif ($self->event->state eq 'reacting') { + $self->valid(1); + } elsif ($self->event->state eq 'reacted') { + $self->valid(1); + $self->reacted(1); + } elsif ($self->event->state eq 'cleaning') { + $self->valid(1); + $self->reacted(1); + } elsif ($self->event->state eq 'complete') { + $self->valid(1); + $self->reacted(1); + $self->cleanedup(1); + } elsif ($self->event->state eq 'error') { + $self->valid(0); + $self->reacted(0); + $self->cleanedup(0); + } + + + $self->update_state('found') || die 'Unable to update event state'; + my $class = $self->_fm_class_by_hint( $self->event->event_def->hook->core_type ); my $meth = "retreive_" . $class; @@ -55,6 +80,9 @@ sub init { sub cleanup { my $self = shift; + my $env = shift || $self->environment; + + return $self if (defined $self->cleanedup); if (defined $self->reacted) { $self->update_state( 'cleaning') || die 'Unable to update event state'; @@ -62,7 +90,7 @@ sub cleanup { my $cleanup = $self->reacted ? $self->event->event_def->cleanup_success : $self->event->event_def->cleanup_failure; $self->cleanedup( OpenILS::Application::Trigger::ModRunner::Cleanup - ->new( $cleanup, $self->environment ) + ->new( $cleanup, $env) ->run ->final_result ); @@ -85,6 +113,9 @@ sub cleanup { sub react { my $self = shift; + my $env = shift || $self->environment; + + return $self if (defined $self->reacted); if ($self->valid) { if ($self->event->event_def->group_field) { # can't react individually to a grouped definition @@ -94,7 +125,7 @@ sub react { try { $self->reacted( OpenILS::Application::Trigger::ModRunner::Reactor - ->new( $self->event->event_def->reactor, $self->environment ) + ->new( $self->event->event_def->reactor, $env ) ->run ->final_result ); @@ -213,6 +244,19 @@ sub editor { return $self->{editor}; } +sub unfind { + my $self = shift; + return undef unless (ref $self); + + die 'Cannot unfind a reacted event' if (defined $self->reacted); + + $self->update_state( 'pending' ) || die 'Unable to update event state'; + $self->{id} = undef; + $self->{event} = undef; + $self->{environment} = undef; + return $self; +} + sub target { my $self = shift; return undef unless (ref $self); @@ -232,12 +276,30 @@ sub update_state { $self->editor->xact_begin || return undef; my $e = $self->editor->retrieve_action_trigger_event( $self->id ); + $e->start_time( 'now' ) unless $e->start_time; $e->update_time( 'now' ); $e->update_process( $$ ); $e->state( $state ); - $self->editor->update_action_trigger_event( $e ); - return $self->editor->xact_commit || undef; + $e->clear_start_time() if ($e->state eq 'pending'); + + my $ok = $self->editor->update_action_trigger_event( $e ); + if (!$ok) { + $self->editor->xact_rollback; + return undef; + } else { + $ok = $self->editor->xact_commit; + } + + if ($ok) { + $e = $self->editor->data; + $self->event->start_time( $e->start_time ); + $self->event->update_time( $e->update_time ); + $self->event->update_process( $e->update_process ); + $self->event->state( $e->state ); + } + + return $ok || undef; } sub build_environment { @@ -251,19 +313,21 @@ sub build_environment { $self->environment->{target} = $self->target; $self->environment->{event} = $self->event; $self->environment->{template} = $self->event->event_def->template; + + $self->environment->{params}{ $_->param } = eval $_->value for ( @{$self->event->event_def->params} ); - my @env_list = $self->editor->search_action_trigger_environment( { event_def => $self->event->event_def } ); - my @param_list = $self->editor->search_action_trigger_params( { event_def => $self->event->event_def } ); - - $self->environment->{params}{ $_->param } = eval $_->value for ( @param_list ); - - for my $e ( @env_list ) { + for my $e ( @{$self->event->event_def->env} ) { my (@label, @path); @path = split('.', $e->path) if ($e->path); @label = split('.', $e->label) if ($e->label); $self->_object_by_path( $self->event->target, $e->collector, \@label, \@path ); } + + if ($self->event->event_def->group_field) { + my @group_path = split('.', $self->event->event_def->group_field); + my $group_object = $self->_object_by_path( $self->event->target, undef, [], \@group_path ); + } $self->environment->{complete} = 1; } otherwise { -- 2.11.0