ch.icclab.cyclops.health.HealthStatus.java Source code

Java tutorial

Introduction

Here is the source code for ch.icclab.cyclops.health.HealthStatus.java

Source

package ch.icclab.cyclops.health;
/*
 * Copyright (c) 2017. Zuercher Hochschule fuer Angewandte Wissenschaften
 * All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

import ch.icclab.cyclops.application.Main;
import ch.icclab.cyclops.consume.ConsumeManager;
import ch.icclab.cyclops.executor.TaskExecutor;
import ch.icclab.cyclops.load.Loader;
import ch.icclab.cyclops.load.model.ServerSettings;
import ch.icclab.cyclops.publish.RabbitMQPublisher;
import ch.icclab.cyclops.timeseries.DbAccess;
import com.google.common.base.Stopwatch;
import org.joda.time.Period;
import java.util.concurrent.TimeUnit;

/**
 * Author: Martin Skoviera (linkedin.com/in/skoviera)
 * Created: 10.02.17
 * Description: Global health status of the micro service
 */
public class HealthStatus {
    private static HealthStatus singleton = new HealthStatus();

    // is the micro service in a healthy status?
    private boolean healthy;

    // reason for being unhealthy
    private String reason;

    // how to reschedule subsequent Health checks
    private long period = Loader.getSettings().getServerSettings().getServerHealthCheck();
    private boolean kill = Loader.getSettings().getServerSettings().getServerHealthShutdown();
    private TimeUnit unit = ServerSettings.SERVER_HEALTH_CHECK_UNIT;

    // stopwatch to see the status
    private Stopwatch watch;

    public synchronized static HealthStatus getInstance() {
        return singleton;
    }

    private HealthStatus() {
        this.healthy = true;
        this.reason = null;
        this.watch = Stopwatch.createStarted();
    }

    public class Health {
        private Period period;
        private boolean alive;

        public Health(boolean alive, Period period) {
            this.period = period;
            this.alive = alive;
        }

        public Period getPeriod() {
            return period;
        }

        public boolean isAlive() {
            return alive;
        }
    }

    /**
     * Health status of the micro service
     * @return Health status
     */
    public synchronized Health getHealth() {
        Period period = new Period(watch.elapsed(TimeUnit.MILLISECONDS));
        return new Health(healthy, period);
    }

    /**
     * Reason for an unhealthy micro service
     * @return String reason or null
     */
    public synchronized String getReason() {
        return reason;
    }

    /**
     * Restore the microservice
     */
    protected synchronized void setHealthy() {
        // if not already healthy
        if (!healthy) {
            healthy = true;
            reason = null;
            resetWatch();

            // stop remaining scheduled checks
            TaskExecutor.getInstance().shutDown();

            // try to start publisher
            if (RabbitMQPublisher.getInstance() == null) {
                healthy = false;
            }

            // try to start consumer
            if (!ConsumeManager.startDataAndCommandProcessing()) {

                healthy = false;

                // shut down publisher
                RabbitMQPublisher.shutDown();
            }

            // schedule micro service check
            scheduleCheck();
        }
    }

    /**
     * Pause the microservice and schedule a check
     */
    protected synchronized void setUnhealthy(String why) {
        if (healthy) {
            healthy = false;
            reason = why;
            resetWatch();

            // cancel all tasks in the task executor service
            TaskExecutor.getInstance().shutDown();

            // stop listening for commands and pause data ingestion
            ConsumeManager.stopDataAndCommandProcessing();

            // shut down also RabbitMQ Publisher
            RabbitMQPublisher.shutDown();

            // close the database pool
            new DbAccess().shutDown();

            // optionally kill the micro service
            if (kill)
                System.exit(Main.ERR_HEALTH);

            // schedule micro service check
            scheduleCheck();
        }
    }

    /**
     * Schedule another micro service check
     */
    public synchronized void scheduleCheck() {
        TaskExecutor.getInstance().addScheduledTask(new HealthCheck(), period, period, unit);
    }

    /**
     * Reset elapsed time
     */
    private void resetWatch() {
        if (watch == null) {
            watch = Stopwatch.createStarted();
        }

        watch.reset();
        watch.start();
    }
}