From f0dd7efc158bfdd537364cf28a95aec239ba52d7 Mon Sep 17 00:00:00 2001 From: miker Date: Sun, 1 Feb 2009 04:42:59 +0000 Subject: [PATCH] adding event group support git-svn-id: svn://svn.open-ils.org/ILS/trunk@12028 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../src/perlmods/OpenILS/Application/Trigger.pm | 89 ++++---- .../perlmods/OpenILS/Application/Trigger/Event.pm | 25 ++- .../OpenILS/Application/Trigger/EventGroup.pm | 242 +++++++++++++++++++++ 3 files changed, 314 insertions(+), 42 deletions(-) create mode 100644 Open-ILS/src/perlmods/OpenILS/Application/Trigger/EventGroup.pm diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Trigger.pm b/Open-ILS/src/perlmods/OpenILS/Application/Trigger.pm index dd2beb65da..04d8dd3f9e 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Trigger.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Trigger.pm @@ -15,6 +15,7 @@ use DateTime::Format::ISO8601; use OpenILS::Utils::Fieldmapper; use OpenILS::Utils::CStoreEditor q/:funcs/; use OpenILS::Application::Trigger::Event; +use OpenILS::Application::Trigger::EventGroup; my $log = 'OpenSRF::Utils::Logger'; @@ -117,54 +118,31 @@ __PACKAGE__->register_method( argc => 1 ); -sub run_events { +sub fire_event_group { 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 $events = shift; - my @event_list; - for my $e ( @$events ) { - next unless ($e->valid); - push @event_list, $e; - } + my $e = OpenILS::Application::Trigger::EventGroup->new(@$events); - $event_list[0]->react( $env ); - $event_list[0]->cleanup( $env ); + if ($e->validate->valid) { + $e->react->cleanup; + } return { - reacted => $event_list[0]->reacted, - cleanedup => $event_list[0]->cleanedup, - events => @event_list == 1 ? $event_list[0] : \@event_list + valid => $e->valid, + reacted => $e->reacted, + cleanedup => $e->cleanedup, + events => $e->events }; } __PACKAGE__->register_method( - api_name => 'open-ils.trigger.event.run_validated', - method => 'fire_single_event', + api_name => 'open-ils.trigger.event_group.fire', + method => 'fire_event_group', api_level=> 1, argc => 1 ); - sub pending_events { my $self = shift; my $client = shift; @@ -209,10 +187,10 @@ sub grouped_events { # 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; + push @{ $groups{$e->event->event_def->id}{$ident_value} }, $e; } else { # it's a non-grouped event - push @{ $groups{'*'} }, $e_id; + push @{ $groups{'*'} }, $e; } } } @@ -220,10 +198,45 @@ sub grouped_events { return \%groups; } __PACKAGE__->register_method( - api_name => 'open-ils.trigger.event.found_by_group', + api_name => 'open-ils.trigger.event.find_pending_by_group', method => 'grouped_events', api_level=> 1 ); +sub run_all_events { + my $self = shift; + my $client = shift; + + my ($groups) = $self->method_lookup('open-ils.trigger.event.find_pending_by_group')->run(); + + for my $def ( %$groups ) { + if ($def eq '*') { + for my $event ( @{ $$groups{'*'} } ) { + $client->respond( + $self + ->method_lookup('open-ils.trigger.event.fire') + ->run($event) + ); + } + } else { + my $defgroup = $$groups{$def}; + for my $ident ( keys %$defgroup ) { + $client->respond( + $self + ->method_lookup('open-ils.trigger.event_group.fire') + ->run($$defgroup{$ident}) + ); + } + } + } + + +} +__PACKAGE__->register_method( + api_name => 'open-ils.trigger.event.run_all_pending', + method => 'run_all_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 5f037d8e45..e23475256c 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm @@ -12,9 +12,15 @@ my $log = 'OpenSRF::Utils::Logger'; sub new { my $class = shift; my $id = shift; + my $editor = shift; $class = ref($class) || $class; - my $self = bless { id => $id, editor => new_editor() } => $class; + return $id if (ref($id) && ref($id) == $class); + + my $standalone = $editor ? 0 : 1; + $editor ||= new_editor(); + + my $self = bless { id => $id, editor => $editor, standalone => $standalone } => $class; return $self->init() } @@ -266,6 +272,15 @@ sub target { return $self->{target}; } +sub standalone { + my $self = shift; + return undef unless (ref $self); + + my $t = shift; + $self->{standalone} = $t if (defined $t); + return $self->{standalone}; +} + sub update_state { my $self = shift; return undef unless ($self && ref $self); @@ -273,7 +288,9 @@ sub update_state { my $state = shift; return undef unless ($state); - $self->editor->xact_begin || return undef; + if ($self->standalone) { + $self->editor->xact_begin || return undef; + } my $e = $self->editor->retrieve_action_trigger_event( $self->id ); $e->start_time( 'now' ) unless $e->start_time; @@ -285,10 +302,10 @@ sub update_state { my $ok = $self->editor->update_action_trigger_event( $e ); if (!$ok) { - $self->editor->xact_rollback; + $self->editor->xact_rollback if ($self->standalone); return undef; } else { - $ok = $self->editor->xact_commit; + $ok = $self->editor->xact_commit if ($self->standalone); } if ($ok) { diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Trigger/EventGroup.pm b/Open-ILS/src/perlmods/OpenILS/Application/Trigger/EventGroup.pm new file mode 100644 index 0000000000..2c792e4bd2 --- /dev/null +++ b/Open-ILS/src/perlmods/OpenILS/Application/Trigger/EventGroup.pm @@ -0,0 +1,242 @@ +package OpenILS::Application::Trigger::EventGroup; +use OpenILS::Application::Trigger::Event; +use base 'OpenILS::Application::Trigger::Event'; +use OpenSRF::EX qw/:try/; + +use OpenSRF::Utils::Logger qw/:level/; + +use OpenILS::Utils::Fieldmapper; +use OpenILS::Utils::CStoreEditor q/:funcs/; +use OpenILS::Application::Trigger::ModRunner; + +my $log = 'OpenSRF::Utils::Logger'; + +sub new { + my $class = shift; + my @ids = @_; + $class = ref($class) || $class; + + my $editor = new_editor(xact=>1); + + my $self = bless { + environment => {}, + events => [ + map { + ref($_) ? + do { $_->standalone(0); $_->editor($editor); $_ } : + OpenILS::Application::Trigger::Event->new($_, $editor) + } @ids + ], + ids => \@ids, + editor => $editor + } => $class; + + + $self->editor->xact_commit; # flush out those updates + $self->editor->xact_begin; + + return $self; +} + +sub react { + my $self = shift; + + return $self if (defined $self->reacted); + + if ($self->valid) { + $self->update_state( 'reacting') || die 'Unable to update event group state'; + $self->build_environment; + + try { + $self->reacted( + OpenILS::Application::Trigger::ModRunner::Reactor + ->new( $self->event->event_def->reactor, $self->environment ) + ->run + ->final_result + ); + } otherwise { + $log->error( shift() ); + $self->update_state( 'error' ) || die 'Unable to update event group state'; + }; + + if (defined $self->reacted) { + $self->update_state( 'reacted' ) || die 'Unable to update event group state'; + } else { + $self->update_state( 'error' ) || die 'Unable to update event group state'; + } + } else { + $self->{reacted} = undef; + } + return $self; +} + +sub validate { + my $self = shift; + + return $self if (defined $self->valid); + + $self->update_state( 'validating') || die 'Unable to update event group state'; + $self->editor->xact_begin; + + my @valid_events; + try { + for my $event ( @{ $self->events } ) { + $event->validate; + push @valid_events, $event if ($event->valid); + } + $self->valid(1) if (@valid_events); + $self->{events} = \@valid_events; + $self->editor->xact_commit; + } otherwise { + $log->error( shift() ); + $self->editor->xact_rollback; + $self->update_state( 'error' ) || die 'Unable to update event group state'; + }; + + return $self; +} + +sub cleanedup { + my $self = shift; + return undef unless (ref $self); + + my $c = shift; + $self->{cleanedup} = $c if (defined $c); + return $self->{cleanedup}; +} + +sub reacted { + my $self = shift; + return undef unless (ref $self); + + my $r = shift; + $self->{reacted} = $r if (defined $r); + return $self->{reacted}; +} + +sub valid { + my $self = shift; + return undef unless (ref $self); + + my $v = shift; + $self->{valid} = $v if (defined $v); + return $self->{valid}; +} + +sub event { + my $self = shift; + return undef unless (ref $self); + + return $self->{events}[0]; +} + +sub events { + my $self = shift; + return undef unless (ref $self); + + return $self->{events}; +} + +sub ids { + my $self = shift; + return undef unless (ref $self); + + return $self->{ids}; +} + +sub environment { + my $self = shift; + return undef unless (ref $self); + + my $e = shift; + $self->{environment} = $e if (defined $e); + return $self->{environment}; +} + +sub editor { + my $self = shift; + return undef unless (ref $self); + + my $e = shift; + $self->{editor} = $e if (defined $e); + return $self->{editor}; +} + +sub unfind { + my $self = shift; + return undef unless (ref $self); + + die 'Cannot unfind a reacted event group' if (defined $self->reacted); + + $self->update_state( 'pending' ) || die 'Unable to update event group state'; + $self->{events} = undef; + return $self; +} + +sub update_state { + my $self = shift; + return undef unless ($self && ref $self); + + my $state = shift; + return undef unless ($state); + + $self->editor->xact_begin || return undef; + + my @oks; + for my $event ( @{ $self->events } ) { + my $e = $self->editor->retrieve_action_trigger_event( $event->id ); + $e->start_time( 'now' ) unless $e->start_time; + $e->update_time( 'now' ); + $e->update_process( $$ ); + $e->state( $state ); + + $e->clear_start_time() if ($e->state eq 'pending'); + + my $ok = $self->editor->update_action_trigger_event( $e ); + if ($ok) { + push @oks, $ok; + } + } + + if (scalar(@oks) < scalar(@{ $self->ids })) { + $self->editor->xact_rollback; + return undef; + } else { + $ok = $self->editor->xact_commit; + } + + if ($ok) { + for my $event ( @{ $self->events } ) { + my $updated = $self->editor->data; + $event->start_time( $updated->start_time ); + $event->update_time( $updated->update_time ); + $event->update_process( $updated->update_process ); + $event->state( $updated->state ); + } + } + + return $ok || undef; +} + +sub build_environment { + my $self = shift; + my $env = $self->environment; + + $$evn{target} = []; + $$evn{event} = []; + for my $e ( @{ $self->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 { + $$evn{$evn_part} = $e->environment->{$evn_part}; + } + } + } + + return $self; +} + +1; -- 2.11.0