package Connector::Iterator; use strict; use warnings; use English; use Moose; use DateTime; use Data::Dumper; extends 'Connector'; has 'BASECONNECTOR' => ( is => 'ro', required => 1 ); # Location must not be used has '+LOCATION' => ( required => 0, 'isa' => 'Undef' ); has target => ( is => 'rw', isa => 'Undef|ArrayRef', lazy => 1, builder => '_init_target', ); has skip_on_error => ( is => 'rw', isa => 'Bool', default => 0, ); sub _init_target { my $self = shift; # the connectors prefix points to the root node of the target list my @target_node = $self->_build_path_with_prefix(); if (!$self->BASECONNECTOR()->exists( \@target_node )) { $self->log()->warn( 'Target node does not exists ' . join(".", \@target_node) ); return; } $self->log()->debug( 'Node with targets' . Dumper \@target_node ); my @targets = $self->BASECONNECTOR()->get_keys( \@target_node ); if (!scalar @targets) { $self->log()->warn( 'No targets found!' ); return; } $self->log()->debug( 'Targets ' . Dumper \@targets ); return \@targets; } sub set { my $self = shift; my $item = shift; my $data = shift; my $targets = $self->target(); if (!$targets) { $self->log()->error( 'No targets found!' ); return $self->_node_not_exists(); } my @item_path = $self->_build_path( $item ); $self->log()->debug( 'Item path' . Dumper \@item_path); # Initialize the base connector my $baseconn = $self->BASECONNECTOR(); my $result; foreach my $target (@{$targets}) { $self->log()->debug( 'Publication to ' . $target . ' with item ' . Dumper $item ); my @publication_target = $self->_build_path_with_prefix( [ $target, @item_path ] ); $result->{$target} = ''; my $res; if ($self->skip_on_error()) { eval{ $res = $baseconn->set( \@publication_target , $data ); }; if ($EVAL_ERROR) { $EVAL_ERROR =~ /\A(.{1,200})/; $result->{$target} = $1; } } else { $res = $baseconn->set( \@publication_target , $data ); } $self->log()->debug('Publication result: ' . Dumper $res ); } return $result; } 1; __END__; =head1 Name Connector::Iterator =head1 Description Helper to perform a I operation over a list of connector endpoints while handing errors individually for each connector. The return value is a hashref with the processed target names as key and an empty value if no errors occured and the exception message if the target failed. You must set I to enable handling of expcetions, otherwise they just bubble up and terminate execution of the loop. Intended use case: write the same data to multiple targets by using multiple connectors. Failed write attemps can be skipped or queued and redone =head2 Supported methods set =head1 Configuration Example my $target = OpenXPKI::Connector::Iterator->new({ BASECONNECTOR => $config, PREFIX => $prefix }); $target->set( [ $data->{issuer}{CN}[0] ], $data ); =head1 OPTIONS =over =item BASECONNECTOR Reference to the connector for the underlying config. =item PREFIX The full path to the node above the targets. =item target List of targets to iterate thru, must be single path elements! =item skip_on_error By default, exceptions from the called connectors bubble up, the loop over the targets terminate. If set, all connectors are processed and any exceptions are returned in the result. =back