Search in sources :

Example 46 with TaskResult

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());
}
Also used : StartWorkflowRequest(com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest) TaskResult(com.netflix.conductor.common.metadata.tasks.TaskResult) Workflow(com.netflix.conductor.common.run.Workflow) Test(org.junit.Test)

Example 47 with TaskResult

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);
}
Also used : TaskResult(com.netflix.conductor.common.metadata.tasks.TaskResult) RejectedExecutionException(java.util.concurrent.RejectedExecutionException)

Example 48 with TaskResult

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);
        }
    }
}
Also used : Task(com.netflix.conductor.common.metadata.tasks.Task) TaskResult(com.netflix.conductor.common.metadata.tasks.TaskResult) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException)

Example 49 with TaskResult

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);
}
Also used : TaskResult(com.netflix.conductor.common.metadata.tasks.TaskResult)

Example 50 with TaskResult

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());
}
Also used : TaskClient(com.netflix.conductor.client.http.TaskClient) Task(com.netflix.conductor.common.metadata.tasks.Task) Worker(com.netflix.conductor.client.worker.Worker) TaskResult(com.netflix.conductor.common.metadata.tasks.TaskResult) ConductorClientException(com.netflix.conductor.client.exceptions.ConductorClientException) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Aggregations

TaskResult (com.netflix.conductor.common.metadata.tasks.TaskResult)66 Test (org.junit.Test)29 Task (com.netflix.conductor.common.metadata.tasks.Task)22 Workflow (com.netflix.conductor.common.run.Workflow)17 WorkflowTask (com.netflix.conductor.common.metadata.workflow.WorkflowTask)13 TaskClient (com.netflix.conductor.client.http.TaskClient)11 Worker (com.netflix.conductor.client.worker.Worker)11 CountDownLatch (java.util.concurrent.CountDownLatch)9 SubWorkflow (com.netflix.conductor.core.execution.tasks.SubWorkflow)8 HashMap (java.util.HashMap)8 StartWorkflowRequest (com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest)7 UserTask (com.netflix.conductor.tests.utils.UserTask)7 Map (java.util.Map)7 WorkflowDef (com.netflix.conductor.common.metadata.workflow.WorkflowDef)6 PrintWriter (java.io.PrintWriter)5 StringWriter (java.io.StringWriter)5 List (java.util.List)5 TaskDef (com.netflix.conductor.common.metadata.tasks.TaskDef)4 ApplicationException (com.netflix.conductor.core.execution.ApplicationException)4 TypeReference (com.fasterxml.jackson.core.type.TypeReference)2