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