#!/usr/bin/perl
package ubic_watchdog;
BEGIN {
  $ubic_watchdog::VERSION = '1.20';
}

use strict;
use warnings;

# ABSTRACT: watchdog which checks all ubic services.


use Getopt::Long 2.33;
use Pod::Usage;

use Ubic::Logger;
use Ubic;
use Try::Tiny;

return 1 if caller();

my $verbose;
GetOptions(
    'v|verbose' => \$verbose,
) or pod2usage(2);

sub check($);

sub check_all {
    my @services = @_;
    for my $service (@services) {
        my $child = fork;
        unless (defined $child) {
            die "fork failed";
        }
        unless ($child) {
            check($service);
            exit;
        }
    }
    1 while wait() > 0;
    return;
}

sub check($) {
    my $service = shift;
    my $name = $service->full_name;
    if ($verbose) {
        INFO("Checking $name");
    }

    try {
        my $lock = Ubic->lock($name);
        if ($service->isa('Ubic::Multiservice')) {
            INFO("$name is multiservice, checking subservices") if $verbose;
            check_all($service->services);
            return;
        }
        unless (Ubic->is_enabled($name)) {
            INFO("$name disabled") if $verbose;
            return;
        }
        # TODO - alarm?
        my $status = Ubic->status($name);
        unless ($status->status eq 'running') {
            Ubic->set_cached_status($name, $status->status); # following start can throw exception
            ERROR("$name is broken, restarting");
            Ubic->start($name);
        }
        $status = Ubic->status($name);
        if ($status->status ne 'running') {
            INFO("$name started, but status is still '$status'");
        }
        Ubic->set_cached_status($name, $status); # if service's start implementation is invalid, ubic-watchdog will restart it every minute, so be careful
    }
    catch {
        ERROR("Failed to check $name: $_");
    };

    INFO("$name checked") if $verbose;
}

my @services = Ubic->services;
check_all(@services);

__END__
=pod

=head1 NAME

ubic_watchdog - watchdog which checks all ubic services.

=head1 VERSION

version 1.20

=head1 SYNOPSIS

    ubic-watchdog [-v]

=head1 DESCRIPTION

This is a generic watchdog for all ubic services.

It checks every enabled service by asking for its status and tries to start it if service is down or broken.

Every service is checked in parallel fashion, each one in separate forked process.

=head1 DEPLOYMENT

This script should be invoked every minute (or as often as you like), usually as cron job.

=head1 AUTHOR

Vyacheslav Matyukhin <mmcleric@yandex-team.ru>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2010 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

