use of com.netflix.conductor.common.metadata.tasks.TaskResult in project conductor by Netflix.
the class ExclusiveJoinEndToEndTest method testDecision1TrueAndDecision2True.
@Test
public void testDecision1TrueAndDecision2True() {
workflowInput.put("decision_1", "true");
workflowInput.put("decision_2", "true");
StartWorkflowRequest startWorkflowRequest = new StartWorkflowRequest().withName(CONDUCTOR_WORKFLOW_DEF_NAME).withCorrelationId("").withInput(workflowInput).withVersion(1);
String wfInstanceId = workflowClient.startWorkflow(startWorkflowRequest);
String taskId = taskClient.getPendingTaskForWorkflow(wfInstanceId, "task1").getTaskId();
taskOutput.put("taskReferenceName", "task1");
TaskResult taskResult = setTaskResult(wfInstanceId, taskId, TaskResult.Status.COMPLETED, taskOutput);
taskClient.updateTask(taskResult);
taskId = taskClient.getPendingTaskForWorkflow(wfInstanceId, "task2").getTaskId();
taskOutput.put("taskReferenceName", "task2");
taskResult = setTaskResult(wfInstanceId, taskId, TaskResult.Status.COMPLETED, taskOutput);
taskClient.updateTask(taskResult);
taskId = taskClient.getPendingTaskForWorkflow(wfInstanceId, "task3").getTaskId();
taskOutput.put("taskReferenceName", "task3");
taskResult = setTaskResult(wfInstanceId, taskId, TaskResult.Status.COMPLETED, taskOutput);
taskClient.updateTask(taskResult);
Workflow workflow = workflowClient.getWorkflow(wfInstanceId, true);
String taskReferenceName = workflow.getTaskByRefName("exclusiveJoin").getOutputData().get("taskReferenceName").toString();
assertEquals("task3", taskReferenceName);
assertEquals(Workflow.WorkflowStatus.COMPLETED, workflow.getStatus());
}
use of com.netflix.conductor.common.metadata.tasks.TaskResult in project conductor by Netflix.
the class WorkflowTaskCoordinator method execute.
private void execute(Worker worker, Task task) {
String taskType = task.getTaskDefName();
try {
if (!worker.preAck(task)) {
logger.debug("Worker decided not to ack the task {}, taskId = {}", taskType, task.getTaskId());
return;
}
if (!taskClient.ack(task.getTaskId(), worker.getIdentity())) {
MetricsContainer.incrementTaskAckFailedCount(worker.getTaskDefName());
return;
}
logger.debug("Ack successful for {}, taskId = {}", taskType, task.getTaskId());
} catch (Exception e) {
logger.error(String.format("ack exception for task %s, taskId = %s in worker - %s", task.getTaskDefName(), task.getTaskId(), worker.getIdentity()), e);
MetricsContainer.incrementTaskAckErrorCount(worker.getTaskDefName(), e);
return;
}
com.google.common.base.Stopwatch stopwatch = com.google.common.base.Stopwatch.createStarted();
TaskResult result = null;
try {
logger.debug("Executing task {} in worker {} at {}", task, worker.getClass().getSimpleName(), worker.getIdentity());
result = worker.execute(task);
result.setWorkflowInstanceId(task.getWorkflowInstanceId());
result.setTaskId(task.getTaskId());
result.setWorkerId(worker.getIdentity());
} catch (Exception e) {
logger.error("Unable to execute task {}", task, e);
if (result == null) {
task.setStatus(Task.Status.FAILED);
result = new TaskResult(task);
}
handleException(e, result, worker, task);
} finally {
stopwatch.stop();
MetricsContainer.getExecutionTimer(worker.getTaskDefName()).record(stopwatch.elapsed(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
}
logger.debug("Task {} executed by worker {} at {} with status {}", task.getTaskId(), worker.getClass().getSimpleName(), worker.getIdentity(), task.getStatus());
updateWithRetry(updateRetryCount, task, result, worker);
}
use of com.netflix.conductor.common.metadata.tasks.TaskResult in project conductor by Netflix.
the class WorkflowTaskCoordinator method pollForTask.
private void pollForTask(Worker worker) {
if (eurekaClient != null && !eurekaClient.getInstanceRemoteStatus().equals(InstanceStatus.UP)) {
logger.debug("Instance is NOT UP in discovery - will not poll");
return;
}
if (worker.paused()) {
MetricsContainer.incrementTaskPausedCount(worker.getTaskDefName());
logger.debug("Worker {} has been paused. Not polling anymore!", worker.getClass());
return;
}
String domain = Optional.ofNullable(PropertyFactory.getString(worker.getTaskDefName(), DOMAIN, null)).orElse(PropertyFactory.getString(ALL_WORKERS, DOMAIN, null));
logger.debug("Polling {}, domain={}, count = {} timeout = {} ms", worker.getTaskDefName(), domain, worker.getPollCount(), worker.getLongPollTimeoutInMS());
List<Task> tasks = Collections.emptyList();
try {
// get the remaining capacity of worker queue to prevent queue full exception
int realPollCount = Math.min(workerQueue.remainingCapacity(), worker.getPollCount());
if (realPollCount <= 0) {
logger.warn("All workers are busy, not polling. queue size = {}, max = {}", workerQueue.size(), workerQueueSize);
return;
}
String taskType = worker.getTaskDefName();
tasks = getPollTimer(taskType).record(() -> taskClient.batchPollTasksInDomain(taskType, domain, worker.getIdentity(), realPollCount, worker.getLongPollTimeoutInMS()));
incrementTaskPollCount(taskType, tasks.size());
logger.debug("Polled {}, domain {}, received {} tasks in worker - {}", worker.getTaskDefName(), domain, tasks.size(), worker.getIdentity());
} catch (Exception e) {
MetricsContainer.incrementTaskPollErrorCount(worker.getTaskDefName(), e);
logger.error("Error when polling for tasks", e);
}
for (Task task : tasks) {
try {
executorService.submit(() -> {
try {
logger.debug("Executing task {}, taskId - {} in worker - {}", task.getTaskDefName(), task.getTaskId(), worker.getIdentity());
execute(worker, task);
} catch (Throwable t) {
task.setStatus(Task.Status.FAILED);
TaskResult result = new TaskResult(task);
handleException(t, result, worker, task);
}
});
} catch (RejectedExecutionException e) {
MetricsContainer.incrementTaskExecutionQueueFullCount(worker.getTaskDefName());
logger.error("Execution queue is full, returning task: {}", task.getTaskId(), e);
returnTask(worker, task);
}
}
}
use of com.netflix.conductor.common.metadata.tasks.TaskResult in project conductor by Netflix.
the class WorkflowTaskCoordinator method returnTask.
/**
* Returns task back to conductor by calling updateTask API without any change to task for error scenarios where
* worker can't work on the task due to ack failures, {@code executorService.submit} throwing {@link RejectedExecutionException},
* etc. This guarantees that task will be picked up by any worker again after task's {@code callbackAfterSeconds}.
* This is critical especially for tasks without responseTimeoutSeconds setting in which case task will get stuck
* in IN_PROGRESS status forever when these errors occur if task is not returned.
*/
private void returnTask(Worker worker, Task task) {
logger.warn("Returning task {} back to conductor", task.getTaskId());
updateWithRetry(updateRetryCount, task, new TaskResult(task), worker);
}
use of com.netflix.conductor.common.metadata.tasks.TaskResult in project conductor by Netflix.
the class TaskPollExecutorTest method testLargePayloadCanFailUpdateWithRetry.
@Test
public void testLargePayloadCanFailUpdateWithRetry() {
Task task = testTask();
Worker worker = mock(Worker.class);
when(worker.getPollingInterval()).thenReturn(3000);
when(worker.getTaskDefName()).thenReturn(TEST_TASK_DEF_NAME);
when(worker.execute(any())).thenReturn(new TaskResult(task));
TaskClient taskClient = Mockito.mock(TaskClient.class);
when(taskClient.pollTask(any(), any(), any())).thenReturn(task);
when(taskClient.ack(any(), any())).thenReturn(true);
doAnswer(invocation -> {
Object[] args = invocation.getArguments();
TaskResult result = (TaskResult) args[0];
assertNull(result.getReasonForIncompletion());
result.setReasonForIncompletion("some_reason");
throw new ConductorClientException();
}).when(taskClient).evaluateAndUploadLargePayload(any(TaskResult.class), any());
TaskPollExecutor taskPollExecutor = new TaskPollExecutor(null, taskClient, 1, 3, new HashMap<>(), "test-worker-");
CountDownLatch latch = new CountDownLatch(1);
doAnswer(invocation -> {
latch.countDown();
return null;
}).when(worker).onErrorUpdate(any());
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> taskPollExecutor.pollAndExecute(worker), 0, 1, TimeUnit.SECONDS);
Uninterruptibles.awaitUninterruptibly(latch);
// When evaluateAndUploadLargePayload fails indefinitely, task update shouldn't be called.
verify(taskClient, times(0)).updateTask(any());
}
Aggregations