File Coverage

blib/lib/POE/Component/Supervisor/Supervised.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package POE::Component::Supervisor::Supervised;
4 1     1   1856 use Moose::Role;
  0            
  0            
5              
6             use Moose::Util::TypeConstraints;
7              
8             use namespace::clean -except => 'meta';
9              
10             with qw(POE::Component::Supervisor::Supervised::Interface);
11              
12             has handle_class => (
13             isa => "ClassName",
14             is => "rw",
15             required => 1,
16             # handles => {
17             # create_handle => "new",
18             # },
19             );
20              
21             sub spawn {
22             my ( $self, @args ) = @_;
23             $self->create_handle( @args );
24             }
25              
26             sub _get_handle_attributes {
27             my ( $class, $handle_class ) = @_;
28              
29             my $meta = $class->meta;
30              
31             $handle_class ||= $meta->get_attribute("handle_class")->default || die "no default handle_class for $class";
32              
33             my $handle_meta = $handle_class->meta;
34              
35             my @handle_attrs =
36             map { $_->clone }
37             grep { not $meta->has_attribute($_->name) }
38             grep { defined $_->init_arg } grep { $_->name !~ /^(?: child | supervisor | logger )$/x }
39             $handle_meta->get_all_attributes;
40             }
41              
42             sub _inherit_attributes_from_handle_class {
43             my ( $class, @args ) = @_;
44              
45             my $meta = $class->meta;
46              
47             my @handle_attrs = do {
48             no strict 'refs';
49             @{ "${class}::_handle_attrs" } = $class->_get_handle_attributes(@args)
50             };
51              
52             $meta->add_attribute($_) for @handle_attrs;
53             }
54              
55             sub create_handle {
56             my ( $self, @args ) = @_;
57              
58             my $class = ref $self;
59            
60             my @handle_attrs = do {
61             no strict 'refs';
62             @{ "${class}::_handle_attrs" };
63             };
64              
65             $self->construct_handle(
66             child => $self,
67             ( map { $_->init_arg => scalar($_->get_value($self)) } grep { $_->has_value($self) } @handle_attrs ),
68             @args,
69             );
70             }
71              
72             sub construct_handle {
73             my ( $self, @args ) = @_;
74             $self->handle_class->new(@args);
75             }
76              
77             requires 'is_abnormal_exit';
78              
79             has restart_policy => (
80             isa => enum(__PACKAGE__ . "::RestartPolicy" => qw(permanent transient temporary)),
81             is => "rw",
82             default => "transient",
83             );
84              
85             sub is_transient {
86             my $self = shift;
87             $self->restart_policy eq 'transient';
88             }
89              
90             sub is_permanent {
91             my $self = shift;
92             $self->restart_policy eq 'permanent';
93             }
94              
95             sub is_temporary {
96             my $self = shift;
97             $self->restart_policy eq 'temporary';
98             }
99              
100             sub should_restart {
101             my ( $self, @args ) = @_;
102              
103             if ( $self->is_permanent ) {
104             return 1;
105             } elsif ( $self->is_transient ) {
106             return $self->is_abnormal_exit(@args);
107             } elsif ( $self->is_temporary ) {
108             return;
109             }
110              
111             # never reached
112             return 1;
113             }
114              
115             sub respawn { shift->spawn(@_) }
116              
117             __PACKAGE__
118              
119             __END__
120              
121             =pod
122              
123             =head1 NAME
124              
125             POE::Component::Supervisor::Supervised - A role for supervision descriptors.
126              
127             =head1 SYNOPSIS
128              
129             # See e.g. POE::Component::Supervisor::Supervised::Proc;
130              
131             =head1 DESCRIPTION
132              
133             All children supervised by the L<POE::Component::Supervisor> must do this role.
134              
135             This role provides an API for instantiating
136             L<POE::Component::Supervisor::Handle> as required by the supervisor,
137             corresponding to living instances of the child. The
138             L<POE::Component::Supervisor::Supervised> objects serve as descriptors for
139             these handles, and know how to spawn the actual child.
140              
141             =head1 ATTRIBUTES
142              
143             =over 4
144              
145             =item restart_policy
146              
147             One of C<permanent>, C<transient> or C<temporary>.
148              
149             Defaults to C<transient>.
150              
151             See C<should_restart>.
152              
153             =item handle_class
154              
155             This attribute should be extended by your class to provide a default for
156             C<_inherit_attributes_from_handle_class> (and subsequently C<create_handle>) to
157             work.
158              
159             =back
160              
161             =head1 METHODS
162              
163             =over 4
164              
165             =item construct_handle
166              
167             Calls C<new> on C<handle_class> with the arguments.
168              
169             =item create_handle
170              
171             Iterates the inherited attributes and copies them from the C<$self>, and also
172             passes C<$self> as the C<child> parameter, along with all provided arguments to
173             C<construct_handle>.
174              
175             =item should_restart
176              
177             Returns a boolean value, which instructs the supervisor as to whether or not
178             the child should be restarted after exit.
179              
180             If the child is C<permanent> this always returns true.
181              
182             If the child is C<transient> this returns true if C<is_abnormal_exit> returns
183             true.
184              
185             If the child is C<temporary> this returns false.
186              
187             =item is_abnormal_exit %args
188              
189             Required.
190              
191             Given exit arguments from the handle, check whether or not the exit was normal
192             or not.
193              
194             For example L<POE::Component::Supervisor::Supervised::Proc> will by default
195             check if the exit status is 0.
196              
197             Only applies to C<transient> children.
198              
199             =item spawn
200              
201             Required.
202              
203             Creates a new L<POE::Component::Supervisor::Handle> object for the supervisor.
204              
205             =item respawn
206              
207             An alias for C<spawn> by default.
208              
209             May be overridden if respawning requires cleanup first, or something like that.
210              
211             =item is_transient
212              
213             =item is_temporary
214              
215             =item is_permanent
216              
217             Boolean query methods that operatoe on C<restart_policy>.
218              
219             =back
220              
221             =cut
222              
223