/** * Add a listener for the final query info. This notification is guaranteed to be fired only once. * Listener is always notified asynchronously using a dedicated notification thread pool so, care should * be taken to avoid leaking {@code this} when adding a listener in a constructor. */ public void addQueryInfoStateChangeListener(StateChangeListener<QueryInfo> stateChangeListener) { AtomicBoolean done = new AtomicBoolean(); StateChangeListener<Optional<QueryInfo>> fireOnceStateChangeListener = finalQueryInfo -> { if (finalQueryInfo.isPresent() && done.compareAndSet(false, true)) { stateChangeListener.stateChanged(finalQueryInfo.get()); } }; finalQueryInfo.addStateChangeListener(fireOnceStateChangeListener); }
/** * Add a listener for the final stage info. This notification is guaranteed to be fired only once. * Listener is always notified asynchronously using a dedicated notification thread pool so, care should * be taken to avoid leaking {@code this} when adding a listener in a constructor. Additionally, it is * possible notifications are observed out of order due to the asynchronous execution. */ public void addFinalStageInfoListener(StateChangeListener<StageInfo> finalStatusListener) { AtomicBoolean done = new AtomicBoolean(); StateChangeListener<Optional<StageInfo>> fireOnceStateChangeListener = finalStageInfo -> { if (finalStageInfo.isPresent() && done.compareAndSet(false, true)) { finalStatusListener.stateChanged(finalStageInfo.get()); } }; finalStageInfo.addStateChangeListener(fireOnceStateChangeListener); }
@Override public void addFinalQueryInfoListener(StateChangeListener<QueryInfo> stateChangeListener) { executor.execute(() -> stateChangeListener.stateChanged(queryInfo)); }
private void fireStateChanged(T newState, FutureStateChange<T> futureStateChange, List<StateChangeListener<T>> stateChangeListeners) { checkState(!Thread.holdsLock(lock), "Can not fire state change event while holding the lock"); requireNonNull(newState, "newState is null"); executor.execute(() -> { checkState(!Thread.holdsLock(lock), "Can not notify while holding the lock"); try { futureStateChange.complete(newState); } catch (Throwable e) { log.error(e, "Error setting future state for %s", name); } for (StateChangeListener<T> stateChangeListener : stateChangeListeners) { try { stateChangeListener.stateChanged(newState); } catch (Throwable e) { log.error(e, "Error notifying state change listener for %s", name); } } }); }
/** * Adds a listener to be notified when the state instance changes according to {@code .equals()}. */ public void addStateChangeListener(StateChangeListener<T> stateChangeListener) { requireNonNull(stateChangeListener, "stateChangeListener is null"); boolean inTerminalState; synchronized (lock) { inTerminalState = isTerminalState(state); if (!inTerminalState) { stateChangeListeners.add(stateChangeListener); } } // state machine will never transition from a terminal state, so fire state change immediately if (inTerminalState) { stateChangeListener.stateChanged(state); } }
@Override public void addStateChangeListener(StateChangeListener<TaskInfo> stateChangeListener) { taskStateMachine.addStateChangeListener(newValue -> stateChangeListener.stateChanged(getTaskInfo())); }
@Override public void addStateChangeListener(StateChangeListener<QueryState> stateChangeListener) { stateChangeListener.stateChanged(QueryState.FAILED); }
/** * Adds a listener to be notified when the state instance changes according to {@code .equals()}. * Listener is always notified asynchronously using a dedicated notification thread pool so, care should * be taken to avoid leaking {@code this} when adding a listener in a constructor. Additionally, it is * possible notifications are observed out of order due to the asynchronous execution. The listener is * immediately notified immediately of the current state. */ public void addStateChangeListener(StateChangeListener<T> stateChangeListener) { requireNonNull(stateChangeListener, "stateChangeListener is null"); boolean inTerminalState; T currentState; synchronized (lock) { currentState = state; inTerminalState = isTerminalState(currentState); if (!inTerminalState) { stateChangeListeners.add(stateChangeListener); } } // fire state change listener with the current state // always fire listener callbacks from a different thread safeExecute(() -> stateChangeListener.stateChanged(currentState)); }
/** * Add a listener for the final task info. This notification is guaranteed to be fired only once. * Listener is always notified asynchronously using a dedicated notification thread pool so, care should * be taken to avoid leaking {@code this} when adding a listener in a constructor. Additionally, it is * possible notifications are observed out of order due to the asynchronous execution. */ public void addFinalTaskInfoListener(StateChangeListener<TaskInfo> stateChangeListener) { AtomicBoolean done = new AtomicBoolean(); StateChangeListener<Optional<TaskInfo>> fireOnceStateChangeListener = finalTaskInfo -> { if (finalTaskInfo.isPresent() && done.compareAndSet(false, true)) { stateChangeListener.stateChanged(finalTaskInfo.get()); } }; finalTaskInfo.addStateChangeListener(fireOnceStateChangeListener); fireOnceStateChangeListener.stateChanged(finalTaskInfo.get()); }
private void fireStateChange() { for (StateChangeListener<QueryState> listener : listeners) { listener.stateChanged(state); } } }
@Override public void addStateChangeListener(StateChangeListener<QueryState> stateChangeListener) { executor.execute(() -> stateChangeListener.stateChanged(FAILED)); }
private void fireStateChangedListener(T newState, StateChangeListener<T> stateChangeListener) { try { stateChangeListener.stateChanged(newState); } catch (Throwable e) { log.error(e, "Error notifying state change listener for %s", name); } }
@Override public void addFinalTaskInfoListener(StateChangeListener<TaskInfo> stateChangeListener) { AtomicBoolean done = new AtomicBoolean(); StateChangeListener<TaskState> fireOnceStateChangeListener = state -> { if (state.isDone() && done.compareAndSet(false, true)) { stateChangeListener.stateChanged(getTaskInfo()); } }; taskStateMachine.addStateChangeListener(fireOnceStateChangeListener); fireOnceStateChangeListener.stateChanged(taskStateMachine.getState()); }
@Override public void addStateChangeListener(StateChangeListener<TaskStatus> stateChangeListener) { taskStateMachine.addStateChangeListener(newValue -> stateChangeListener.stateChanged(getTaskStatus())); }