001/* 002 * Copyright (C) 2009 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.util.concurrent; 016 017import static com.google.common.util.concurrent.Internal.toNanosSaturated; 018 019import com.google.common.annotations.GwtIncompatible; 020import com.google.errorprone.annotations.CanIgnoreReturnValue; 021import com.google.errorprone.annotations.DoNotMock; 022import java.time.Duration; 023import java.util.concurrent.Executor; 024import java.util.concurrent.TimeUnit; 025import java.util.concurrent.TimeoutException; 026 027/** 028 * An object with an operational state, plus asynchronous {@link #startAsync()} and {@link 029 * #stopAsync()} lifecycle methods to transition between states. Example services include 030 * webservers, RPC servers and timers. 031 * 032 * <p>The normal lifecycle of a service is: 033 * 034 * <ul> 035 * <li>{@linkplain State#NEW NEW} -> 036 * <li>{@linkplain State#STARTING STARTING} -> 037 * <li>{@linkplain State#RUNNING RUNNING} -> 038 * <li>{@linkplain State#STOPPING STOPPING} -> 039 * <li>{@linkplain State#TERMINATED TERMINATED} 040 * </ul> 041 * 042 * <p>There are deviations from this if there are failures or if {@link Service#stopAsync} is called 043 * before the {@link Service} reaches the {@linkplain State#RUNNING RUNNING} state. The set of legal 044 * transitions form a <a href="http://en.wikipedia.org/wiki/Directed_acyclic_graph">DAG</a>, 045 * therefore every method of the listener will be called at most once. N.B. The {@link State#FAILED} 046 * and {@link State#TERMINATED} states are terminal states, once a service enters either of these 047 * states it cannot ever leave them. 048 * 049 * <p>Implementors of this interface are strongly encouraged to extend one of the abstract classes 050 * in this package which implement this interface and make the threading and state management 051 * easier. 052 * 053 * @author Jesse Wilson 054 * @author Luke Sandberg 055 * @since 9.0 (in 1.0 as {@code com.google.common.base.Service}) 056 */ 057@DoNotMock("Create an AbstractIdleService") 058@GwtIncompatible 059@ElementTypesAreNonnullByDefault 060public interface Service { 061 /** 062 * If the service state is {@link State#NEW}, this initiates service startup and returns 063 * immediately. A stopped service may not be restarted. 064 * 065 * @return this 066 * @throws IllegalStateException if the service is not {@link State#NEW} 067 * @since 15.0 068 */ 069 @CanIgnoreReturnValue 070 Service startAsync(); 071 072 /** Returns {@code true} if this service is {@linkplain State#RUNNING running}. */ 073 boolean isRunning(); 074 075 /** Returns the lifecycle state of the service. */ 076 State state(); 077 078 /** 079 * If the service is {@linkplain State#STARTING starting} or {@linkplain State#RUNNING running}, 080 * this initiates service shutdown and returns immediately. If the service is {@linkplain 081 * State#NEW new}, it is {@linkplain State#TERMINATED terminated} without having been started nor 082 * stopped. If the service has already been stopped, this method returns immediately without 083 * taking action. 084 * 085 * @return this 086 * @since 15.0 087 */ 088 @CanIgnoreReturnValue 089 Service stopAsync(); 090 091 /** 092 * Waits for the {@link Service} to reach the {@linkplain State#RUNNING running state}. 093 * 094 * @throws IllegalStateException if the service reaches a state from which it is not possible to 095 * enter the {@link State#RUNNING} state. e.g. if the {@code state} is {@code 096 * State#TERMINATED} when this method is called then this will throw an IllegalStateException. 097 * @since 15.0 098 */ 099 void awaitRunning(); 100 101 /** 102 * Waits for the {@link Service} to reach the {@linkplain State#RUNNING running state} for no more 103 * than the given time. 104 * 105 * @param timeout the maximum time to wait 106 * @throws TimeoutException if the service has not reached the given state within the deadline 107 * @throws IllegalStateException if the service reaches a state from which it is not possible to 108 * enter the {@link State#RUNNING RUNNING} state. e.g. if the {@code state} is {@code 109 * State#TERMINATED} when this method is called then this will throw an IllegalStateException. 110 * @since 28.0 111 */ 112 default void awaitRunning(Duration timeout) throws TimeoutException { 113 awaitRunning(toNanosSaturated(timeout), TimeUnit.NANOSECONDS); 114 } 115 116 /** 117 * Waits for the {@link Service} to reach the {@linkplain State#RUNNING running state} for no more 118 * than the given time. 119 * 120 * @param timeout the maximum time to wait 121 * @param unit the time unit of the timeout argument 122 * @throws TimeoutException if the service has not reached the given state within the deadline 123 * @throws IllegalStateException if the service reaches a state from which it is not possible to 124 * enter the {@link State#RUNNING RUNNING} state. e.g. if the {@code state} is {@code 125 * State#TERMINATED} when this method is called then this will throw an IllegalStateException. 126 * @since 15.0 127 */ 128 @SuppressWarnings("GoodTime") // should accept a java.time.Duration 129 void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException; 130 131 /** 132 * Waits for the {@link Service} to reach the {@linkplain State#TERMINATED terminated state}. 133 * 134 * @throws IllegalStateException if the service {@linkplain State#FAILED fails}. 135 * @since 15.0 136 */ 137 void awaitTerminated(); 138 139 /** 140 * Waits for the {@link Service} to reach a terminal state (either {@link Service.State#TERMINATED 141 * terminated} or {@link Service.State#FAILED failed}) for no more than the given time. 142 * 143 * @param timeout the maximum time to wait 144 * @throws TimeoutException if the service has not reached the given state within the deadline 145 * @throws IllegalStateException if the service {@linkplain State#FAILED fails}. 146 * @since 28.0 147 */ 148 default void awaitTerminated(Duration timeout) throws TimeoutException { 149 awaitTerminated(toNanosSaturated(timeout), TimeUnit.NANOSECONDS); 150 } 151 152 /** 153 * Waits for the {@link Service} to reach a terminal state (either {@link Service.State#TERMINATED 154 * terminated} or {@link Service.State#FAILED failed}) for no more than the given time. 155 * 156 * @param timeout the maximum time to wait 157 * @param unit the time unit of the timeout argument 158 * @throws TimeoutException if the service has not reached the given state within the deadline 159 * @throws IllegalStateException if the service {@linkplain State#FAILED fails}. 160 * @since 15.0 161 */ 162 @SuppressWarnings("GoodTime") // should accept a java.time.Duration 163 void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException; 164 165 /** 166 * Returns the {@link Throwable} that caused this service to fail. 167 * 168 * @throws IllegalStateException if this service's state isn't {@linkplain State#FAILED FAILED}. 169 * @since 14.0 170 */ 171 Throwable failureCause(); 172 173 /** 174 * Registers a {@link Listener} to be {@linkplain Executor#execute executed} on the given 175 * executor. The listener will have the corresponding transition method called whenever the 176 * service changes state. The listener will not have previous state changes replayed, so it is 177 * suggested that listeners are added before the service starts. 178 * 179 * <p>{@code addListener} guarantees execution ordering across calls to a given listener but not 180 * across calls to multiple listeners. Specifically, a given listener will have its callbacks 181 * invoked in the same order as the underlying service enters those states. Additionally, at most 182 * one of the listener's callbacks will execute at once. However, multiple listeners' callbacks 183 * may execute concurrently, and listeners may execute in an order different from the one in which 184 * they were registered. 185 * 186 * <p>RuntimeExceptions thrown by a listener will be caught and logged. Any exception thrown 187 * during {@code Executor.execute} (e.g., a {@code RejectedExecutionException}) will be caught and 188 * logged. 189 * 190 * @param listener the listener to run when the service changes state is complete 191 * @param executor the executor in which the listeners callback methods will be run. For fast, 192 * lightweight listeners that would be safe to execute in any thread, consider {@link 193 * MoreExecutors#directExecutor}. 194 * @since 13.0 195 */ 196 void addListener(Listener listener, Executor executor); 197 198 /** 199 * The lifecycle states of a service. 200 * 201 * <p>The ordering of the {@link State} enum is defined such that if there is a state transition 202 * from {@code A -> B} then {@code A.compareTo(B) < 0}. N.B. The converse is not true, i.e. if 203 * {@code A.compareTo(B) < 0} then there is <b>not</b> guaranteed to be a valid state transition 204 * {@code A -> B}. 205 * 206 * @since 9.0 (in 1.0 as {@code com.google.common.base.Service.State}) 207 */ 208 enum State { 209 /** A service in this state is inactive. It does minimal work and consumes minimal resources. */ 210 NEW, 211 212 /** A service in this state is transitioning to {@link #RUNNING}. */ 213 STARTING, 214 215 /** A service in this state is operational. */ 216 RUNNING, 217 218 /** A service in this state is transitioning to {@link #TERMINATED}. */ 219 STOPPING, 220 221 /** 222 * A service in this state has completed execution normally. It does minimal work and consumes 223 * minimal resources. 224 */ 225 TERMINATED, 226 227 /** 228 * A service in this state has encountered a problem and may not be operational. It cannot be 229 * started nor stopped. 230 */ 231 FAILED, 232 } 233 234 /** 235 * A listener for the various state changes that a {@link Service} goes through in its lifecycle. 236 * 237 * <p>All methods are no-ops by default, implementors should override the ones they care about. 238 * 239 * @author Luke Sandberg 240 * @since 15.0 (present as an interface in 13.0) 241 */ 242 abstract class Listener { 243 /** 244 * Called when the service transitions from {@linkplain State#NEW NEW} to {@linkplain 245 * State#STARTING STARTING}. This occurs when {@link Service#startAsync} is called the first 246 * time. 247 */ 248 public void starting() {} 249 250 /** 251 * Called when the service transitions from {@linkplain State#STARTING STARTING} to {@linkplain 252 * State#RUNNING RUNNING}. This occurs when a service has successfully started. 253 */ 254 public void running() {} 255 256 /** 257 * Called when the service transitions to the {@linkplain State#STOPPING STOPPING} state. The 258 * only valid values for {@code from} are {@linkplain State#STARTING STARTING} or {@linkplain 259 * State#RUNNING RUNNING}. This occurs when {@link Service#stopAsync} is called. 260 * 261 * @param from The previous state that is being transitioned from. 262 */ 263 public void stopping(State from) {} 264 265 /** 266 * Called when the service transitions to the {@linkplain State#TERMINATED TERMINATED} state. 267 * The {@linkplain State#TERMINATED TERMINATED} state is a terminal state in the transition 268 * diagram. Therefore, if this method is called, no other methods will be called on the {@link 269 * Listener}. 270 * 271 * @param from The previous state that is being transitioned from. Failure can occur in any 272 * state with the exception of {@linkplain State#FAILED FAILED} and {@linkplain 273 * State#TERMINATED TERMINATED}. 274 */ 275 public void terminated(State from) {} 276 277 /** 278 * Called when the service transitions to the {@linkplain State#FAILED FAILED} state. The 279 * {@linkplain State#FAILED FAILED} state is a terminal state in the transition diagram. 280 * Therefore, if this method is called, no other methods will be called on the {@link Listener}. 281 * 282 * @param from The previous state that is being transitioned from. Failure can occur in any 283 * state with the exception of {@linkplain State#NEW NEW} or {@linkplain State#TERMINATED 284 * TERMINATED}. 285 * @param failure The exception that caused the failure. 286 */ 287 public void failed(State from, Throwable failure) {} 288 } 289}