package Ubic::Service::Skeleton; BEGIN { $Ubic::Service::Skeleton::VERSION = '1.33_02'; } use strict; use warnings; # ABSTRACT: skeleton of any service with common start/stop logic use Ubic::Result qw(result); use Scalar::Util qw(blessed); use Time::HiRes qw(sleep); use Ubic::Service::Utils qw(wait_for_status); use parent qw(Ubic::Service); sub status { my ($self) = @_; my $result = $self->status_impl; $result ||= 'unknown'; $result = result($result); return $result; } sub start { my ($self) = @_; my $status = $self->status; if ($status->status eq 'running') { return 'already running'; # TODO - update $status field instead? } elsif ($status->status eq 'not running') { return $self->_do_start; } elsif ($status->status eq 'broken') { # checks inside _do_start and _do_stop guarantee correct status $self->_do_stop; return $self->_do_start; } else { die result('unknown', "wrong status '$status'"); } } sub stop { my ($self) = @_; my $status = $self->status; if ($status->status eq 'not running') { return 'not running'; } return $self->_do_stop; } sub status_impl { die 'not implemented'; } sub start_impl { die 'not implemented'; } sub stop_impl { die 'not implemented'; } sub timeout_options { return {}; } ##### internal methods ###### sub _do_start { my ($self) = @_; my $status; my $start_result = $self->start_impl; if (blessed($start_result) and $start_result->isa('Ubic::Result::Class')) { $status = $start_result; } if (not $status or $status->type eq 'starting') { $status = wait_for_status({ service => $self, expect_status => ['running', 'not running'], %{ $self->timeout_options->{start} || {} }, }); if ($status->status eq 'running') { $status->type('started'); # fake status to report correct action (hopefully) } } if (not $status) { die result('unknown', 'no result'); } if ($status->status eq 'running') { return $status; } else { die result($status, 'start failed'); } } sub _do_stop { my ($self) = @_; my $status; my $stop_result = $self->stop_impl; if (blessed($stop_result) and $stop_result->isa('Ubic::Result::Class')) { $status = $stop_result; } if (not $status or $status->type eq 'stopping') { $status = wait_for_status({ service => $self, expect_status => ['not running'], %{ $self->timeout_options->{stop} || {} }, }); if ($status->status eq 'not running') { $status->type('stopped'); # fake status to report correct action (hopefully) } } if (not $status) { die result('unknown', 'no result'); } if ($status->status eq 'not running') { return $status; } else { die result($status, 'stop failed'); } } 1; __END__ =pod =head1 NAME Ubic::Service::Skeleton - skeleton of any service with common start/stop logic =head1 VERSION version 1.33_02 =head1 ACTIONS =over =item B<< status() >> Get status of service. Possible values: C, C, C, C. =item B<< start() >> Start service. Throws exception on failure. =item B<< stop() >> Stop service. Return values: C, C. Throws exception on failure. =back =head1 OVERLOADABLE METHODS Subclass must overload following methods with simple status, start and stop implementations. =over =item B Status implentation. Should return result object or plain string which coerces to result object. =item B Start implementation. It can check for status itself and return proper C value, or it can allow skeleton class to recheck status after that, in several attempts. To choose second option, it should return non-result value or C. See C method for details about recheck policy. =item B Stop implementation. It can check for status itself and return proper C value, or it can allow skeleton class to recheck status after that, in several attempts. To choose second option, it should return non-result value or C. See C method for details about recheck policy. =item B Return hashref with timeout options. Possible options: =over =item I Params to be used when checking for status of started service. Should contain hashref with I and I options for C function from C. =back =back =head1 AUTHOR Vyacheslav Matyukhin =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Yandex LLC. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut