private FusionTask(final String desc, final Task<S> task, final PromisePropagator<S, T> propagator) { super(desc, TaskType.FUSION.getName()); _propagator = completing(adaptToAcceptTraceContext(propagator)); _asyncTask = task; _predecessorShallowTraceBuilder = null; }
private <R> FusionTask(final String desc, final FusionTask<S, R> predecessor, final PromisePropagator<R, T> propagator) { super(desc, TaskType.FUSION.getName()); _asyncTask = predecessor._asyncTask; _predecessorShallowTraceBuilder = predecessor.getShallowTraceBuilder(); _propagator = completing(compose(predecessor._propagator, adaptToAcceptTraceContext(propagator))); }
/** * A helper for creating task wrapper with associated retry policy. * * @param name A name of the task that needs to be retried. * @param policy Retry policy that will control this task's behavior. * @param taskFunction A task generator function. It will receive a zero-based attempt number as a parameter. * @param <U> Type of a task result. */ public static <U> Task<U> withRetryPolicy(String name, RetryPolicy policy, Function1<Integer, Task<U>> taskFunction) { RetriableTask<U> retriableTask = new RetriableTask<>(name, policy, taskFunction); Task<U> retryTaskWrapper = Task.async(name + " retriableTask", retriableTask::run); retryTaskWrapper.getShallowTraceBuilder().setTaskType(TaskType.WITH_RETRY.getName()); return retryTaskWrapper; }
@Test public void testDocWithTraceHavingTaskType() throws IOException { final String json = buildJson(new String[] {traceStr(1, "name", ResultType.UNFINISHED, false, TaskType.FUSION.getName())}, new String[0], "test", 0L); Trace decodedTrace = decodeString(json); assertEquals(decodedTrace.getTraceMap().get(1L).getTaskType(), TaskType.FUSION.getName()); }
@Test public void testShareableTaskType() { Task<Integer> value = Task.value(10); Task<Integer> shareableTask = value.shareable(); assertEquals(shareableTask.getShallowTrace().getTaskType(), TaskType.SHAREABLE.getName()); }
@Test public void testWithTimeoutTaskType() { Task<?> taskWithTimeout = Task.value("test").withTimeout(50, TimeUnit.MILLISECONDS); runAndWait("taskWithTimeoutTaskType", taskWithTimeout); assertEquals(doesTaskTypeExistInTrace(taskWithTimeout.getTrace(), TaskType.TIMEOUT.getName()), true); Assert.assertEquals(taskWithTimeout.getShallowTrace().getTaskType(), TaskType.WITH_TIMEOUT.getName()); }
@Test public void testWithRecoverTaskType() { Task<String> task = getFailureTask().recoverWith(e -> Task.value("recoveryTask")); runAndWait(task); assertEquals(doesTaskTypeExistInTrace(task.getTrace(), TaskType.RECOVER.getName()), true); assertEquals(task.getShallowTrace().getTaskType(), TaskType.WITH_RECOVER.getName()); }
@Test public void testWithRetryTaskType() { Task<String> task = Task.withRetryPolicy(RetryPolicy.attempts(1, 0), attempt -> Task.value("successful attempt " + attempt)); runAndWait(task); assertEquals(doesTaskTypeExistInTrace(task.getTrace(), TaskType.RETRY.getName()), true); assertEquals(task.getShallowTrace().getTaskType(), TaskType.WITH_RETRY.getName()); }
@Test public void testFusionTaskType() { Task<Integer> task = getSuccessTask().map(String::length); runAndWait("fusionTaskType", task); assertEquals(task.getShallowTrace().getTaskType(), TaskType.FUSION.getName()); }
@Test public void testBlockingTaskType() { TestingExecutorService es = new TestingExecutorService(Executors.newSingleThreadExecutor()); try { Task<String> task = Task.blocking(() -> "blocking task", es); runAndWait("blockingTaskType", task); assertEquals(task.getShallowTrace().getTaskType(), TaskType.BLOCKING.getName()); } finally { es.shutdown(); } }
@Test public void testFlatMapTaskType() { Task<String> task = Task.value("Welcome"); Task<String> flatMap = task.flatMap("+earth", s -> Task.callable(() -> s + " on earth!")); runAndWait("flatMapTaskType", flatMap); assertEquals(flatMap.getShallowTrace().getTaskType(), TaskType.FLATTEN.getName()); }
return promise; }); blockingTask.getShallowTraceBuilder().setTaskType(TaskType.BLOCKING.getName()); return blockingTask;
@Test public void testWithSideEffectTaskType() { Task<?> taskWithSideEffect = Task.value("value1Task", "value1").withSideEffect("delayed sideEffect", v -> delayedValue("value2", 100, TimeUnit.MILLISECONDS)); runAndWait("taskWithSideEffectTaskType", taskWithSideEffect); Assert.assertEquals(taskWithSideEffect.getShallowTrace().getTaskType(), TaskType.WITH_SIDE_EFFECT.getName()); }
return result; }); shareableTask.getShallowTraceBuilder().setTaskType(TaskType.SHAREABLE.getName()); return shareableTask;
@Test public void testReversibleUnstartedTrace() throws IOException { final ShallowTraceBuilder test = new ShallowTraceBuilder(IdGenerator.getNextId()).setName("test").setResultType(ResultType.UNFINISHED) .setTaskType(TaskType.FUSION.getName()); final Trace trace = Trace.single(test.build(), "test", 0L); assertReversible(trace); }
return result; }); flattenTask.getShallowTraceBuilder().setTaskType(TaskType.FLATTEN.getName()); return flattenTask;
}); withSideEffectTask.getShallowTraceBuilder().setTaskType(TaskType.WITH_SIDE_EFFECT.getName()); return withSideEffectTask;
}); recovery.getShallowTraceBuilder().setSystemHidden(true); recovery.getShallowTraceBuilder().setTaskType(TaskType.RECOVER.getName()); Promises.propagateResult(recovery, result); context.after(that).run(recovery); return result; }); recoverWithTask.getShallowTraceBuilder().setTaskType(TaskType.WITH_RECOVER.getName()); return recoverWithTask;
/** Create a wrapped task with associated recovery task that will retry if necessary. */ private Task<T> wrap(int attempt) { Task<T> retryTask = Task.async(_policy.getName() + ", attempt " + attempt, context -> { final SettablePromise<T> result = Promises.settable(); Task<T> task = _taskFunction.apply(attempt); final Task<T> recovery = Task.async(_name + " recovery", recoveryContext -> { final SettablePromise<T> recoveryResult = Promises.settable(); if (task.isFailed()) { // Failed task will cause retry to be scheduled. ErrorClassification errorClassification = _policy.getErrorClassifier().apply(task.getError()); retry(attempt + 1, task.getError(), errorClassification, recoveryContext, recoveryResult); } else { recoveryResult.done(task.get()); } return recoveryResult; }); // Recovery task should run immediately after the original task to process its error. recovery.setPriority(Priority.MAX_PRIORITY); recovery.getShallowTraceBuilder().setSystemHidden(true); Promises.propagateResult(recovery, result); context.after(task).run(recovery); context.run(task); return result; }); retryTask.getShallowTraceBuilder().setTaskType(TaskType.RETRY.getName()); return retryTask; }