Search in sources :

Example 1 with OnUnscheduled

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;
}
Also used : NarCloseable(org.apache.nifi.nar.NarCloseable) CompletableFuture(java.util.concurrent.CompletableFuture) Processor(org.apache.nifi.processor.Processor) OnUnscheduled(org.apache.nifi.annotation.lifecycle.OnUnscheduled) OnStopped(org.apache.nifi.annotation.lifecycle.OnStopped) ProcessorInstantiationException(org.apache.nifi.controller.exception.ProcessorInstantiationException)

Example 2 with OnUnscheduled

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;
    }
}
Also used : ComponentLog(org.apache.nifi.logging.ComponentLog) KafkaException(org.apache.kafka.common.KafkaException) ProcessException(org.apache.nifi.processor.exception.ProcessException) WakeupException(org.apache.kafka.common.errors.WakeupException) OnUnscheduled(org.apache.nifi.annotation.lifecycle.OnUnscheduled)

Aggregations

OnUnscheduled (org.apache.nifi.annotation.lifecycle.OnUnscheduled)2 CompletableFuture (java.util.concurrent.CompletableFuture)1 KafkaException (org.apache.kafka.common.KafkaException)1 WakeupException (org.apache.kafka.common.errors.WakeupException)1 OnStopped (org.apache.nifi.annotation.lifecycle.OnStopped)1 ProcessorInstantiationException (org.apache.nifi.controller.exception.ProcessorInstantiationException)1 ComponentLog (org.apache.nifi.logging.ComponentLog)1 NarCloseable (org.apache.nifi.nar.NarCloseable)1 Processor (org.apache.nifi.processor.Processor)1 ProcessException (org.apache.nifi.processor.exception.ProcessException)1