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