File Coverage

blib/lib/POE/Component/Sequence/Nested.pm
Criterion Covered Total %
statement 30 31 96.7
branch 8 10 80.0
condition 9 15 60.0
subroutine 5 5 100.0
pod n/a
total 52 61 85.2


line stmt bran cond sub pod time code
1             package POE::Component::Sequence::Nested;
2              
3             =head1 NAME
4              
5             POE::Component::Sequence::Nested - Adds special features to nested sequences
6              
7             =head1 SYNOPSIS
8              
9             use POE qw(Component::Sequence::Nested);
10              
11             POE::Component::Sequence
12             ->new(
13             {
14             auto_pause => 1,
15             auto_resume => 1,
16             merge_heap => 1,
17             },
18             sub {
19             POE::Component::Sequence
20             ->new(
21             sub {
22             my $subseq = shift;
23             $subseq->heap_set(
24             a => 5,
25             b => 19,
26             op => '+',
27             );
28             },
29             )->run;
30             },
31             sub {
32             my $sequence = shift;
33             my $math = join ' ', map { $sequence->heap_index($_) } qw(a op b);
34             $sequence->heap_set(result => eval $math);
35             }
36             )
37             ->add_callback(sub {
38             my ($sequence, $result) = @_;
39             print "Answer was " . $sequence->heap_index('result') . "\n";
40             })
41             ->run();
42              
43             =head1 DESCRIPTION
44              
45             A nested sequence is one in which the return value of an action is another Sequence. When this is the case, we can perform some automated tasks which save each action from redundant calls.
46              
47             By itself it does nothing, but given any of the following actions, it will do it's magic:
48              
49             =head2 auto_resume
50              
51             =over 4
52              
53             The parent sequence remains paused, but the child sequence has a callback added onto it which will resume the parent sequence:
54              
55             $child_sequence->add_callback(sub {
56             $parent_sequence->resume;
57             });
58              
59             =back
60              
61             =head2 auto_error
62              
63             =over 4
64              
65             This propogates a child sequence failure to the parent via $child->add_error_callback(). This would happen anyway if the child sequence throws an exception, but if the child sequence is already catching errors via another callback
66              
67             =back
68              
69             =head2 merge_heap
70              
71             =over 4
72              
73             The heap of the child sequence will be merged with the parent when it's complete:
74              
75             $child_sequence->add_finally_callback(sub {
76             $parent_sequence->heap_set( $child_sequence->heap );
77             });
78              
79             This allows for shared heap access.
80              
81             =back
82              
83             =cut
84              
85 1     1   866 use strict;
  1         3  
  1         48  
86 1     1   7 use warnings;
  1         2  
  1         37  
87 1     1   7 use POE::Component::Sequence;
  1         2  
  1         25  
88 1     1   6 use Scalar::Util qw(blessed);
  1         12  
  1         517  
89              
90             BEGIN {
91             unshift @POE::Component::Sequence::_plugin_handlers,
92             sub {
93 12         16 my ($self, $request) = @_;
94              
95 12         25 my $action = $request->{action};
96 12         16 my $opt = $request->{options};
97              
98 12 50 33     96 if (! defined $action || ! ref $action || ref $action ne 'CODE') {
      33        
99 0         0 return { deferred => 1 };
100             }
101              
102 12         44 my $return = $action->(@_);
103              
104 11 50 100     259 if ($return && ref $return && blessed $return
      66        
      66        
105             && $return->isa('POE::Component::Sequence')) {
106 6 100       19 if (delete $opt->{auto_resume}) {
107             $return->add_finally_callback(sub {
108 2         8 $self->resume;
109 2         16 });
110             }
111 6 100       18 if (delete $opt->{auto_error}) {
112             $return->add_error_callback(sub {
113 1         5 $self->failed($_[1]);
114 1         9 });
115             }
116 6 100       15 if (delete $opt->{merge_heap}) {
117             $return->add_finally_callback(sub {
118 1         31 my %transaction_heap = $_[1]->heap;
119 1         42 $self->heap_set(%transaction_heap);
120 1         7 });
121             }
122             }
123              
124 11         53 return { value => $return };
125 1     1   31 };
126             }
127              
128             1;
129              
130             __END__