@Override protected void doStart() { Exceptions.checkNotClosed(this.closed.get(), this); notifyStarted(); log.info("{}: Started.", this.traceObjectId); this.runTask = doRun(); this.runTask.whenComplete((r, ex) -> { // Handle any exception that may have been thrown. if (ex != null && !(Exceptions.unwrap(ex) instanceof CancellationException && state() != State.RUNNING)) { // We ignore CancellationExceptions while shutting down - those are expected. errorHandler(ex); } // Make sure the service is stopped when the runTask is done (whether successfully or not). if (state() == State.RUNNING) { stopAsync(); } }); }
@Override protected void doStop() { this.stopToken.requestCancellation(); super.doStop(); }
notifyStopped(); } else { if (stopException != null && stopException != runException) { notifyFailed(runException);
@Override protected void errorHandler(Throwable ex) { ex = Exceptions.unwrap(ex); closeQueue(ex); if (!isShutdownException(ex)) { // Shutdown exceptions means we are already stopping, so no need to do anything else. For all other cases, // record the failure and then stop the OperationProcessor. super.errorHandler(ex); stopAsync(); } }
@Override protected void doStop() { Exceptions.checkNotClosed(this.closed.get(), this); log.info("{}: Stopping.", this.traceObjectId); if (this.runTask == null) { notifyStoppedOrFailed(null); } else if (this.runTask.isDone()) { // Our runTask is done. See if it completed normally or not. notifyStoppedOrFailed(Futures.getException(this.runTask)); } else { // Still running. Wait (async) for the task to complete or a timeout to expire. CompletableFuture .anyOf(this.runTask, Futures.delayedFuture(getShutdownTimeout(), this.executor)) .whenComplete((r, ex) -> { if (ex != null) { ex = Exceptions.unwrap(ex); } if (ex == null && !this.runTask.isDone()) { // Still no exception, but our service did not properly shut down. ex = new TimeoutException("Timeout expired while waiting for the Service to shut down."); } this.runTask = null; notifyStoppedOrFailed(ex); }); } }
private Void iterationErrorHandler(Throwable ex) { if (isShutdownException(ex) && !canRun()) { // Writer is not running and we caught a CancellationException. // This is a normal behavior and it is triggered by stopAsync(); just exit without logging or triggering anything else. log.info("{}: StorageWriter intercepted {} while shutting down.", this.traceObjectId, Exceptions.unwrap(ex).getClass().getSimpleName()); return null; } boolean critical = isCriticalError(ex); logError(ex, critical); if (critical) { // Setting a stop exception guarantees the main Writer loop will not continue running again. super.errorHandler(ex); stopAsync(); } else { this.state.recordIterationError(); } return null; }
@Override protected void doStop() { // We need to first stop the operation queue, which will prevent any new items from being processed. Throwable ex = new CancellationException("OperationProcessor is shutting down."); closeQueue(ex); // Close the DataFrameBuilder and cancel any operations caught in limbo. synchronized (this.stateLock) { this.dataFrameBuilder.close(); } this.state.fail(ex, null); this.metrics.close(); super.doStop(); }