use of org.apache.nifi.annotation.lifecycle.OnUnscheduled in project nifi by apache.
the class StandardProcessorNode method stop.
/**
* Will idempotently stop the processor using the following sequence: <i>
* <ul>
* <li>Transition (atomically) Processor's scheduled state from RUNNING to
* STOPPING. If the above state transition succeeds, then invoke any method
* on the Processor with the {@link OnUnscheduled} annotation. Once those methods
* have been called and returned (either normally or exceptionally), start checking
* to see if all of the Processor's active threads have finished. If not, check again
* every 100 milliseconds until they have.
* Once all after threads have completed, the processor's @OnStopped operation will be invoked
* and its scheduled state is set to STOPPED which completes processor stop
* sequence.</li>
* </ul>
* </i>
*
* <p>
* If for some reason processor's scheduled state can not be transitioned to
* STOPPING (e.g., the processor didn't finish @OnScheduled operation when
* stop was called), the attempt will be made to transition processor's
* scheduled state from STARTING to STOPPING which will allow
* {@link #start(ScheduledExecutorService, long, ProcessContext, Runnable)}
* method to initiate processor's shutdown upon exiting @OnScheduled
* operation, otherwise the processor's scheduled state will remain
* unchanged ensuring that multiple calls to this method are idempotent.
* </p>
*/
@Override
public CompletableFuture<Void> stop(final ProcessScheduler processScheduler, final ScheduledExecutorService executor, final ProcessContext processContext, final SchedulingAgent schedulingAgent, final LifecycleState scheduleState) {
final Processor processor = processorRef.get().getProcessor();
LOG.info("Stopping processor: " + processor.getClass());
desiredState = ScheduledState.STOPPED;
final CompletableFuture<Void> future = new CompletableFuture<>();
if (this.scheduledState.compareAndSet(ScheduledState.RUNNING, ScheduledState.STOPPING)) {
// will ensure that the Processor represented by this node can only be stopped once
scheduleState.incrementActiveThreadCount(null);
// will continue to monitor active threads, invoking OnStopped once there are no
// active threads (with the exception of the thread performing shutdown operations)
executor.execute(new Runnable() {
@Override
public void run() {
try {
if (scheduleState.isScheduled()) {
schedulingAgent.unschedule(StandardProcessorNode.this, scheduleState);
activateThread();
try (final NarCloseable nc = NarCloseable.withComponentNarLoader(processor.getClass(), processor.getIdentifier())) {
ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnUnscheduled.class, processor, processContext);
} finally {
deactivateThread();
}
}
// all threads are complete if the active thread count is 1. This is because this thread that is
// performing the lifecycle actions counts as 1 thread.
final boolean allThreadsComplete = scheduleState.getActiveThreadCount() == 1;
if (allThreadsComplete) {
activateThread();
try (final NarCloseable nc = NarCloseable.withComponentNarLoader(processor.getClass(), processor.getIdentifier())) {
ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnStopped.class, processor, processContext);
} finally {
deactivateThread();
}
scheduleState.decrementActiveThreadCount(null);
scheduledState.set(ScheduledState.STOPPED);
future.complete(null);
// Processor if need be.
if (desiredState == ScheduledState.RUNNING) {
processScheduler.startProcessor(StandardProcessorNode.this, true);
}
} else {
// Not all of the active threads have finished. Try again in 100 milliseconds.
executor.schedule(this, 100, TimeUnit.MILLISECONDS);
}
} catch (final Exception e) {
LOG.warn("Failed while shutting down processor " + processor, e);
}
}
});
} else {
// We do compareAndSet() instead of set() to ensure that Processor
// stoppage is handled consistently including a condition where
// Processor never got a chance to transition to RUNNING state
// before stop() was called. If that happens the stop processor
// routine will be initiated in start() method, otherwise the IF
// part will handle the stop processor routine.
this.scheduledState.compareAndSet(ScheduledState.STARTING, ScheduledState.STOPPING);
future.complete(null);
}
return future;
}
use of org.apache.nifi.annotation.lifecycle.OnUnscheduled in project nifi by apache.
the class ConsumeKafka method stopConnectionRetainer.
@OnUnscheduled
public void stopConnectionRetainer() {
if (connectionRetainer != null) {
final ComponentLog logger = getLogger();
logger.debug("Canceling connectionRetainer... {}", new Object[] { connectionRetainer });
try {
connectionRetainer.shutdownNow();
} catch (final Exception e) {
logger.warn("Failed to shutdown connection retainer {} due to {}", new Object[] { connectionRetainer, e }, e);
}
connectionRetainer = null;
}
}
Aggregations