com.google.common.util.concurrent

## Class ServiceManager

- java.lang.Object
- - com.google.common.util.concurrent.ServiceManager

-     @Beta
      public final class ServiceManager
      extends java.lang.Object

  A manager for monitoring and controlling a set of services. This class provides methods for starting, stopping and inspecting a collection of services. Additionally, users can monitor state transitions with the listener mechanism.

  While it is recommended that service lifecycles be managed via this class, state transitions initiated via other mechanisms do not impact the correctness of its methods. For example, if the services are started by some mechanism besides `startAsync()`, the listeners will be invoked when appropriate and `awaitHealthy()` will still work as expected.

  Here is a simple example of how to use a `ServiceManager` to start a server.

         class Server {
         public static void main(String[] args) {
           Set<Service> services = ...;
           ServiceManager manager = new ServiceManager(services);
           manager.addListener(new Listener() {
               public void stopped() {}
               public void healthy() {
                 // Services have been initialized and are healthy, start accepting requests...
               }
               public void failure(Service service) {
                 // Something failed, at this point we could log it, notify a load balancer, or take
                 // some other action.  For now we will just exit.
                 System.exit(1);
               }
             },
             MoreExecutors.directExecutor());

           Runtime.getRuntime().addShutdownHook(new Thread() {
             public void run() {
               // Give the services 5 seconds to stop to ensure that we are responsive to shutdown
               // requests.
               try {
                 manager.stopAsync().awaitStopped(5, TimeUnit.SECONDS);
               } catch (TimeoutException timeout) {
                 // stopping timed out
               }
             }
           });
           manager.startAsync();  // start all the services asynchronously
         }
       }

  This class uses the ServiceManager's methods to start all of its services, to respond to service failure and to ensure that when the JVM is shutting down all the services are stopped.

  Since:
    14.0

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `static class` | `ServiceManager.Listener` A listener for the aggregate state changes of the services that are under management.

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `ServiceManager(java.lang.Iterable<? extends Service> services)` Constructs a new instance for managing the given services.

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `addListener(ServiceManager.Listener listener)` Registers a `ServiceManager.Listener` to be run when this `ServiceManager` changes state.
    `void` | `addListener(ServiceManager.Listener listener, java.util.concurrent.Executor executor)` Registers a `ServiceManager.Listener` to be executed on the given executor.
    `void` | `awaitHealthy()` Waits for the `ServiceManager` to become healthy.
    `void` | `awaitHealthy(long timeout, java.util.concurrent.TimeUnit unit)` Waits for the `ServiceManager` to become healthy for no more than the given time.
    `void` | `awaitStopped()` Waits for the all the services to reach a terminal state.
    `void` | `awaitStopped(long timeout, java.util.concurrent.TimeUnit unit)` Waits for the all the services to reach a terminal state for no more than the given time.
    `boolean` | `isHealthy()` Returns true if all services are currently in the running state.
    `ImmutableMultimap<Service.State,Service>` | `servicesByState()` Provides a snapshot of the current state of all the services under management.
    `ServiceManager` | `startAsync()` Initiates service startup on all the services being managed.
    `ImmutableMap<Service,java.lang.Long>` | `startupTimes()` Returns the service load times.
    `ServiceManager` | `stopAsync()` Initiates service shutdown if necessary on all the services being managed.
    `java.lang.String` | `toString()`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- - ### Constructor Detail

    - #### ServiceManager

          public ServiceManager(java.lang.Iterable<? extends Service> services)

      Constructs a new instance for managing the given services.
      Parameters:
        `services` - The services to manage
      Throws:
        `java.lang.IllegalArgumentException` - if not all services are new or if there are any duplicate services.

  - ### Method Detail

    - #### addListener

          public void addListener(ServiceManager.Listener listener,
                         java.util.concurrent.Executor executor)

      Registers a `ServiceManager.Listener` to be executed on the given executor. The listener will not have previous state changes replayed, so it is suggested that listeners are added before any of the managed services are started.

      `addListener` guarantees execution ordering across calls to a given listener but not across calls to multiple listeners. Specifically, a given listener will have its callbacks invoked in the same order as the underlying service enters those states. Additionally, at most one of the listener's callbacks will execute at once. However, multiple listeners' callbacks may execute concurrently, and listeners may execute in an order different from the one in which they were registered.

      RuntimeExceptions thrown by a listener will be caught and logged. Any exception thrown during `Executor.execute` (e.g., a `RejectedExecutionException`) will be caught and logged.

      For fast, lightweight listeners that would be safe to execute in any thread, consider calling `addListener(Listener)`.

      Parameters:
        `listener` - the listener to run when the manager changes state
        `executor` - the executor in which the listeners callback methods will be run.

    - #### addListener

          public void addListener(ServiceManager.Listener listener)

      Registers a `ServiceManager.Listener` to be run when this `ServiceManager` changes state. The listener will not have previous state changes replayed, so it is suggested that listeners are added before any of the managed services are started.

      `addListener` guarantees execution ordering across calls to a given listener but not across calls to multiple listeners. Specifically, a given listener will have its callbacks invoked in the same order as the underlying service enters those states. Additionally, at most one of the listener's callbacks will execute at once. However, multiple listeners' callbacks may execute concurrently, and listeners may execute in an order different from the one in which they were registered.

      RuntimeExceptions thrown by a listener will be caught and logged.

      Parameters:
        `listener` - the listener to run when the manager changes state

    - #### startAsync

          public ServiceManager startAsync()

      Initiates service startup on all the services being managed. It is only valid to call this method if all of the services are new.
      Returns:
        this
      Throws:
        `java.lang.IllegalStateException` - if any of the Services are not `new` when the method is called.

    - #### awaitHealthy

          public void awaitHealthy()

      Waits for the `ServiceManager` to become healthy. The manager will become healthy after all the component services have reached the running state.
      Throws:
        `java.lang.IllegalStateException` - if the service manager reaches a state from which it cannot become healthy.

    - #### awaitHealthy

          public void awaitHealthy(long timeout,
                          java.util.concurrent.TimeUnit unit)
                            throws java.util.concurrent.TimeoutException

      Waits for the `ServiceManager` to become healthy for no more than the given time. The manager will become healthy after all the component services have reached the running state.
      Parameters:
        `timeout` - the maximum time to wait
        `unit` - the time unit of the timeout argument
      Throws:
        `java.util.concurrent.TimeoutException` - if not all of the services have finished starting within the deadline
        `java.lang.IllegalStateException` - if the service manager reaches a state from which it cannot become healthy.

    - #### stopAsync

          public ServiceManager stopAsync()

      Initiates service shutdown if necessary on all the services being managed.
      Returns:
        this

    - #### awaitStopped

          public void awaitStopped()

      Waits for the all the services to reach a terminal state. After this method returns all services will either be terminated or failed.

    - #### awaitStopped

          public void awaitStopped(long timeout,
                          java.util.concurrent.TimeUnit unit)
                            throws java.util.concurrent.TimeoutException

      Waits for the all the services to reach a terminal state for no more than the given time. After this method returns all services will either be terminated or failed.
      Parameters:
        `timeout` - the maximum time to wait
        `unit` - the time unit of the timeout argument
      Throws:
        `java.util.concurrent.TimeoutException` - if not all of the services have stopped within the deadline

    - #### isHealthy

          public boolean isHealthy()

      Returns true if all services are currently in the running state.

      Users who want more detailed information should use the `servicesByState()` method to get detailed information about which services are not running.

    - #### servicesByState

          public ImmutableMultimap<Service.State,Service> servicesByState()

      Provides a snapshot of the current state of all the services under management.

      N.B. This snapshot is guaranteed to be consistent, i.e. the set of states returned will correspond to a point in time view of the services.

    - #### startupTimes

          public ImmutableMap<Service,java.lang.Long> startupTimes()

      Returns the service load times. This value will only return startup times for services that have finished starting.
      Returns:
        Map of services and their corresponding startup time in millis, the map entries will be ordered by startup time.

    - #### toString

          public java.lang.String toString()

      Overrides:
        `toString` in class `java.lang.Object`