mirror of
https://github.com/apache/nifi.git
synced 2025-02-13 13:35:20 +00:00
NIFI-6155: Ensure that any task submitted to FlowEngine catches Throwable so that the task doesn't die just die silently in the case of an unexpected error/exception
This closes #3395. Signed-off-by: Bryan Bende <bbende@apache.org>
This commit is contained in:
parent
4de51fd3d5
commit
76392ee862
@ -149,6 +149,8 @@ public class ConnectableTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public InvocationResult invoke() {
|
public InvocationResult invoke() {
|
||||||
|
logger.trace("Triggering {}", connectable);
|
||||||
|
|
||||||
if (scheduleState.isTerminated()) {
|
if (scheduleState.isTerminated()) {
|
||||||
return InvocationResult.DO_NOT_YIELD;
|
return InvocationResult.DO_NOT_YIELD;
|
||||||
}
|
}
|
||||||
@ -165,12 +167,14 @@ public class ConnectableTask {
|
|||||||
|
|
||||||
// Make sure processor has work to do.
|
// Make sure processor has work to do.
|
||||||
if (!isWorkToDo()) {
|
if (!isWorkToDo()) {
|
||||||
|
logger.debug("Yielding {} because it has no work to do", connectable);
|
||||||
return InvocationResult.yield("No work to do");
|
return InvocationResult.yield("No work to do");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numRelationships > 0) {
|
if (numRelationships > 0) {
|
||||||
final int requiredNumberOfAvailableRelationships = connectable.isTriggerWhenAnyDestinationAvailable() ? 1 : numRelationships;
|
final int requiredNumberOfAvailableRelationships = connectable.isTriggerWhenAnyDestinationAvailable() ? 1 : numRelationships;
|
||||||
if (!repositoryContext.isRelationshipAvailabilitySatisfied(requiredNumberOfAvailableRelationships)) {
|
if (!repositoryContext.isRelationshipAvailabilitySatisfied(requiredNumberOfAvailableRelationships)) {
|
||||||
|
logger.debug("Yielding {} because Backpressure is Applied", connectable);
|
||||||
return InvocationResult.yield("Backpressure Applied");
|
return InvocationResult.yield("Backpressure Applied");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,14 @@ import org.apache.nifi.nar.NarThreadContextClassLoader;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.FutureTask;
|
import java.util.concurrent.FutureTask;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public final class FlowEngine extends ScheduledThreadPoolExecutor {
|
public final class FlowEngine extends ScheduledThreadPoolExecutor {
|
||||||
@ -79,6 +82,53 @@ public final class FlowEngine extends ScheduledThreadPoolExecutor {
|
|||||||
super.beforeExecute(thread, runnable);
|
super.beforeExecute(thread, runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScheduledFuture<?> schedule(final Runnable command, final long delay, final TimeUnit unit) {
|
||||||
|
return super.schedule(wrap(command), delay, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScheduledFuture<?> scheduleAtFixedRate(final Runnable command, final long initialDelay, final long period, final TimeUnit unit) {
|
||||||
|
return super.scheduleAtFixedRate(wrap(command), initialDelay, period, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScheduledFuture<?> scheduleWithFixedDelay(final Runnable command, final long initialDelay, final long delay, final TimeUnit unit) {
|
||||||
|
return super.scheduleWithFixedDelay(wrap(command), initialDelay, delay, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <V> ScheduledFuture<V> schedule(final Callable<V> callable, final long delay, final TimeUnit unit) {
|
||||||
|
return super.schedule(wrap(callable), delay, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Runnable wrap(final Runnable runnable) {
|
||||||
|
return new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
runnable.run();
|
||||||
|
} catch (final Throwable t) {
|
||||||
|
logger.error("Uncaught Exception in Runnable task", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Callable<T> wrap(final Callable<T> callable) {
|
||||||
|
return new Callable<T>() {
|
||||||
|
@Override
|
||||||
|
public T call() throws Exception {
|
||||||
|
try {
|
||||||
|
return callable.call();
|
||||||
|
} catch (final Throwable t) {
|
||||||
|
logger.error("Uncaught Exception in Callable task", t);
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook method called by the thread that executed the given runnable after execution of the runnable completed. Logs the fact of completion and any errors that might have occurred.
|
* Hook method called by the thread that executed the given runnable after execution of the runnable completed. Logs the fact of completion and any errors that might have occurred.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user