1 /* 2 * Copyright (C) 2009 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.google.common.util.concurrent; 16 17 import com.google.common.annotations.GwtIncompatible; 18 import com.google.errorprone.annotations.CanIgnoreReturnValue; 19 import com.google.errorprone.annotations.DoNotMock; 20 import java.util.concurrent.Executor; 21 import java.util.concurrent.TimeUnit; 22 import java.util.concurrent.TimeoutException; 23 24 /** 25 * An object with an operational state, plus asynchronous {@link #startAsync()} and {@link 26 * #stopAsync()} lifecycle methods to transition between states. Example services include 27 * webservers, RPC servers and timers. 28 * 29 * <p>The normal lifecycle of a service is: 30 * 31 * <ul> 32 * <li>{@linkplain State#NEW NEW} -> 33 * <li>{@linkplain State#STARTING STARTING} -> 34 * <li>{@linkplain State#RUNNING RUNNING} -> 35 * <li>{@linkplain State#STOPPING STOPPING} -> 36 * <li>{@linkplain State#TERMINATED TERMINATED} 37 * </ul> 38 * 39 * <p>There are deviations from this if there are failures or if {@link Service#stopAsync} is called 40 * before the {@link Service} reaches the {@linkplain State#RUNNING RUNNING} state. The set of legal 41 * transitions form a <a href="http://en.wikipedia.org/wiki/Directed_acyclic_graph">DAG</a>, 42 * therefore every method of the listener will be called at most once. N.B. The {@link State#FAILED} 43 * and {@link State#TERMINATED} states are terminal states, once a service enters either of these 44 * states it cannot ever leave them. 45 * 46 * <p>Implementors of this interface are strongly encouraged to extend one of the abstract classes 47 * in this package which implement this interface and make the threading and state management 48 * easier. 49 * 50 * @author Jesse Wilson 51 * @author Luke Sandberg 52 * @since 9.0 (in 1.0 as {@code com.google.common.base.Service}) 53 */ 54 @DoNotMock("Create an AbstractIdleService") 55 @GwtIncompatible 56 @ElementTypesAreNonnullByDefault 57 public interface Service { 58 /** 59 * If the service state is {@link State#NEW}, this initiates service startup and returns 60 * immediately. A stopped service may not be restarted. 61 * 62 * @return this 63 * @throws IllegalStateException if the service is not {@link State#NEW} 64 * @since 15.0 65 */ 66 @CanIgnoreReturnValue startAsync()67 Service startAsync(); 68 69 /** Returns {@code true} if this service is {@linkplain State#RUNNING running}. */ isRunning()70 boolean isRunning(); 71 72 /** Returns the lifecycle state of the service. */ state()73 State state(); 74 75 /** 76 * If the service is {@linkplain State#STARTING starting} or {@linkplain State#RUNNING running}, 77 * this initiates service shutdown and returns immediately. If the service is {@linkplain 78 * State#NEW new}, it is {@linkplain State#TERMINATED terminated} without having been started nor 79 * stopped. If the service has already been stopped, this method returns immediately without 80 * taking action. 81 * 82 * @return this 83 * @since 15.0 84 */ 85 @CanIgnoreReturnValue stopAsync()86 Service stopAsync(); 87 88 /** 89 * Waits for the {@link Service} to reach the {@linkplain State#RUNNING running state}. 90 * 91 * @throws IllegalStateException if the service reaches a state from which it is not possible to 92 * enter the {@link State#RUNNING} state. e.g. if the {@code state} is {@code 93 * State#TERMINATED} when this method is called then this will throw an IllegalStateException. 94 * @since 15.0 95 */ awaitRunning()96 void awaitRunning(); 97 98 /** 99 * Waits for the {@link Service} to reach the {@linkplain State#RUNNING running state} for no more 100 * than the given time. 101 * 102 * @param timeout the maximum time to wait 103 * @param unit the time unit of the timeout argument 104 * @throws TimeoutException if the service has not reached the given state within the deadline 105 * @throws IllegalStateException if the service reaches a state from which it is not possible to 106 * enter the {@link State#RUNNING RUNNING} state. e.g. if the {@code state} is {@code 107 * State#TERMINATED} when this method is called then this will throw an IllegalStateException. 108 * @since 15.0 109 */ 110 @SuppressWarnings("GoodTime") // should accept a java.time.Duration awaitRunning(long timeout, TimeUnit unit)111 void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException; 112 113 /** 114 * Waits for the {@link Service} to reach the {@linkplain State#TERMINATED terminated state}. 115 * 116 * @throws IllegalStateException if the service {@linkplain State#FAILED fails}. 117 * @since 15.0 118 */ awaitTerminated()119 void awaitTerminated(); 120 121 /** 122 * Waits for the {@link Service} to reach a terminal state (either {@link Service.State#TERMINATED 123 * terminated} or {@link Service.State#FAILED failed}) for no more than the given time. 124 * 125 * @param timeout the maximum time to wait 126 * @param unit the time unit of the timeout argument 127 * @throws TimeoutException if the service has not reached the given state within the deadline 128 * @throws IllegalStateException if the service {@linkplain State#FAILED fails}. 129 * @since 15.0 130 */ 131 @SuppressWarnings("GoodTime") // should accept a java.time.Duration awaitTerminated(long timeout, TimeUnit unit)132 void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException; 133 134 /** 135 * Returns the {@link Throwable} that caused this service to fail. 136 * 137 * @throws IllegalStateException if this service's state isn't {@linkplain State#FAILED FAILED}. 138 * @since 14.0 139 */ failureCause()140 Throwable failureCause(); 141 142 /** 143 * Registers a {@link Listener} to be {@linkplain Executor#execute executed} on the given 144 * executor. The listener will have the corresponding transition method called whenever the 145 * service changes state. The listener will not have previous state changes replayed, so it is 146 * suggested that listeners are added before the service starts. 147 * 148 * <p>{@code addListener} guarantees execution ordering across calls to a given listener but not 149 * across calls to multiple listeners. Specifically, a given listener will have its callbacks 150 * invoked in the same order as the underlying service enters those states. Additionally, at most 151 * one of the listener's callbacks will execute at once. However, multiple listeners' callbacks 152 * may execute concurrently, and listeners may execute in an order different from the one in which 153 * they were registered. 154 * 155 * <p>RuntimeExceptions thrown by a listener will be caught and logged. Any exception thrown 156 * during {@code Executor.execute} (e.g., a {@code RejectedExecutionException}) will be caught and 157 * logged. 158 * 159 * @param listener the listener to run when the service changes state is complete 160 * @param executor the executor in which the listeners callback methods will be run. For fast, 161 * lightweight listeners that would be safe to execute in any thread, consider {@link 162 * MoreExecutors#directExecutor}. 163 * @since 13.0 164 */ addListener(Listener listener, Executor executor)165 void addListener(Listener listener, Executor executor); 166 167 /** 168 * The lifecycle states of a service. 169 * 170 * <p>The ordering of the {@link State} enum is defined such that if there is a state transition 171 * from {@code A -> B} then {@code A.compareTo(B) < 0}. N.B. The converse is not true, i.e. if 172 * {@code A.compareTo(B) < 0} then there is <b>not</b> guaranteed to be a valid state transition 173 * {@code A -> B}. 174 * 175 * @since 9.0 (in 1.0 as {@code com.google.common.base.Service.State}) 176 */ 177 enum State { 178 /** A service in this state is inactive. It does minimal work and consumes minimal resources. */ 179 NEW, 180 181 /** A service in this state is transitioning to {@link #RUNNING}. */ 182 STARTING, 183 184 /** A service in this state is operational. */ 185 RUNNING, 186 187 /** A service in this state is transitioning to {@link #TERMINATED}. */ 188 STOPPING, 189 190 /** 191 * A service in this state has completed execution normally. It does minimal work and consumes 192 * minimal resources. 193 */ 194 TERMINATED, 195 196 /** 197 * A service in this state has encountered a problem and may not be operational. It cannot be 198 * started nor stopped. 199 */ 200 FAILED, 201 } 202 203 /** 204 * A listener for the various state changes that a {@link Service} goes through in its lifecycle. 205 * 206 * <p>All methods are no-ops by default, implementors should override the ones they care about. 207 * 208 * @author Luke Sandberg 209 * @since 15.0 (present as an interface in 13.0) 210 */ 211 abstract class Listener { 212 /** 213 * Called when the service transitions from {@linkplain State#NEW NEW} to {@linkplain 214 * State#STARTING STARTING}. This occurs when {@link Service#startAsync} is called the first 215 * time. 216 */ starting()217 public void starting() {} 218 219 /** 220 * Called when the service transitions from {@linkplain State#STARTING STARTING} to {@linkplain 221 * State#RUNNING RUNNING}. This occurs when a service has successfully started. 222 */ running()223 public void running() {} 224 225 /** 226 * Called when the service transitions to the {@linkplain State#STOPPING STOPPING} state. The 227 * only valid values for {@code from} are {@linkplain State#STARTING STARTING} or {@linkplain 228 * State#RUNNING RUNNING}. This occurs when {@link Service#stopAsync} is called. 229 * 230 * @param from The previous state that is being transitioned from. 231 */ stopping(State from)232 public void stopping(State from) {} 233 234 /** 235 * Called when the service transitions to the {@linkplain State#TERMINATED TERMINATED} state. 236 * The {@linkplain State#TERMINATED TERMINATED} state is a terminal state in the transition 237 * diagram. Therefore, if this method is called, no other methods will be called on the {@link 238 * Listener}. 239 * 240 * @param from The previous state that is being transitioned from. Failure can occur in any 241 * state with the exception of {@linkplain State#FAILED FAILED} and {@linkplain 242 * State#TERMINATED TERMINATED}. 243 */ terminated(State from)244 public void terminated(State from) {} 245 246 /** 247 * Called when the service transitions to the {@linkplain State#FAILED FAILED} state. The 248 * {@linkplain State#FAILED FAILED} state is a terminal state in the transition diagram. 249 * Therefore, if this method is called, no other methods will be called on the {@link Listener}. 250 * 251 * @param from The previous state that is being transitioned from. Failure can occur in any 252 * state with the exception of {@linkplain State#NEW NEW} or {@linkplain State#TERMINATED 253 * TERMINATED}. 254 * @param failure The exception that caused the failure. 255 */ failed(State from, Throwable failure)256 public void failed(State from, Throwable failure) {} 257 } 258 } 259