Search in sources :

Example 1 with InvocationResult

use of org.apache.nifi.controller.tasks.InvocationResult in project nifi by apache.

the class TimerDrivenSchedulingAgent method createTrigger.

private Runnable createTrigger(final ConnectableTask connectableTask, final LifecycleState scheduleState, final AtomicReference<ScheduledFuture<?>> futureRef) {
    final Connectable connectable = connectableTask.getConnectable();
    final Runnable yieldDetectionRunnable = new Runnable() {

        @Override
        public void run() {
            // Call the task. It will return a boolean indicating whether or not we should yield
            // based on a lack of work for to do for the component.
            final InvocationResult invocationResult = connectableTask.invoke();
            if (invocationResult.isYield()) {
                logger.debug("Yielding {} due to {}", connectable, invocationResult.getYieldExplanation());
            }
            // If the component is yielded, cancel its future and re-submit it to run again
            // after the yield has expired.
            final long newYieldExpiration = connectable.getYieldExpiration();
            final long now = System.currentTimeMillis();
            if (newYieldExpiration > now) {
                final long yieldMillis = newYieldExpiration - now;
                final long scheduleMillis = connectable.getSchedulingPeriod(TimeUnit.MILLISECONDS);
                final ScheduledFuture<?> scheduledFuture = futureRef.get();
                if (scheduledFuture == null) {
                    return;
                }
                // so that we can do this again the next time that the component is yielded.
                if (scheduledFuture.cancel(false)) {
                    final long yieldNanos = Math.max(TimeUnit.MILLISECONDS.toNanos(scheduleMillis), TimeUnit.MILLISECONDS.toNanos(yieldMillis));
                    synchronized (scheduleState) {
                        if (scheduleState.isScheduled()) {
                            final long schedulingNanos = connectable.getSchedulingPeriod(TimeUnit.NANOSECONDS);
                            final ScheduledFuture<?> newFuture = flowEngine.scheduleWithFixedDelay(this, yieldNanos, schedulingNanos, TimeUnit.NANOSECONDS);
                            scheduleState.replaceFuture(scheduledFuture, newFuture);
                            futureRef.set(newFuture);
                        }
                    }
                }
            } else if (noWorkYieldNanos > 0L && invocationResult.isYield()) {
                // Component itself didn't yield but there was no work to do, so the framework will choose
                // to yield the component automatically for a short period of time.
                final ScheduledFuture<?> scheduledFuture = futureRef.get();
                if (scheduledFuture == null) {
                    return;
                }
                // so that we can do this again the next time that the component is yielded.
                if (scheduledFuture.cancel(false)) {
                    synchronized (scheduleState) {
                        if (scheduleState.isScheduled()) {
                            final ScheduledFuture<?> newFuture = flowEngine.scheduleWithFixedDelay(this, noWorkYieldNanos, connectable.getSchedulingPeriod(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS);
                            scheduleState.replaceFuture(scheduledFuture, newFuture);
                            futureRef.set(newFuture);
                        }
                    }
                }
            }
        }
    };
    return yieldDetectionRunnable;
}
Also used : Connectable(org.apache.nifi.connectable.Connectable) InvocationResult(org.apache.nifi.controller.tasks.InvocationResult) ScheduledFuture(java.util.concurrent.ScheduledFuture)

Aggregations

ScheduledFuture (java.util.concurrent.ScheduledFuture)1 Connectable (org.apache.nifi.connectable.Connectable)1 InvocationResult (org.apache.nifi.controller.tasks.InvocationResult)1