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