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