Files
wehub-resource-sync a9cd7750f4
CI / unit-test (push) Has been cancelled
CI / detect-changes (push) Has been cancelled
CI / build (push) Has been cancelled
Publish docs via GitHub Pages / Deploy docs (push) Has been cancelled
CI / test-harness (push) Has been cancelled
CI / generate-e2e-matrix (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / build-ui (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
UI v2 Integration CI / E2E (Integration) (push) Has been cancelled
UI v2 CI / Lint, Format & Test (push) Has been cancelled
UI v2 CI / E2E (Mocked) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:37:56 +08:00

201 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: "Task definition schema in Conductor — configure retry logic, exponential backoff, timeouts, rate limiting, and concurrency for durable workflow execution."
---
# Task Definition
Task Definitions are used to register SIMPLE tasks (workers). Conductor maintains a registry of user task types. A task type MUST be registered before being used in a workflow.
This should not be confused with [*Task Configurations*](workflowdef/index.md#task-configurations) which are part of the Workflow Definition, and are iterated in the `tasks` property in the definition.
## Schema
| Field | Type | Description | Notes |
| :-------------------------- | :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------- |
| name | string | Task Name. Unique name of the Task that resonates with its function. | Must be unique |
| description | string | Description of the task. | Optional |
| retryCount | number | Number of retries to attempt when a Task is marked as failure. | Defaults to 3 with maximum allowed capped at 10 |
| retryLogic | string (enum) | Mechanism for the retries. | See [Retry Logic](#retry-logic) |
| retryDelaySeconds | number | Base delay before the first retry. The meaning varies by `retryLogic`. | Defaults to 60 seconds |
| maxRetryDelaySeconds | number | Maximum delay between retries, in seconds. Caps the computed delay for `EXPONENTIAL_BACKOFF` and `LINEAR_BACKOFF` so delays never grow beyond this value. `0` disables the cap. | Defaults to 0 (no cap). See [Retry Logic](#retry-logic) |
| backoffJitterMs | number | Adds a random jitter of up to this many milliseconds to each retry delay. Spreads simultaneous retries across time to prevent thundering herd. `0` disables jitter. | Defaults to 0 (no jitter). See [Retry Logic](#retry-logic) |
| totalTimeoutSeconds | number | Maximum wall-clock time (in seconds) across all retry attempts combined. Once exceeded, the task fails immediately with no further retries, regardless of `retryCount`. `0` disables this limit. | Defaults to 0 (no limit). See [Timeout scenarios](../../../devguide/architecture/tasklifecycle.md#total-timeout) |
| timeoutPolicy | string (enum) | Task's timeout policy. | Defaults to `TIME_OUT_WF`; See [Timeout Policy](#timeout-policy) |
| timeoutSeconds | number | Time in seconds, after which the task is marked as `TIMED_OUT` if it has not reached a terminal state after transitioning to `IN_PROGRESS` status for the first time. | No timeouts if set to 0 |
| responseTimeoutSeconds | number | If greater than 0, the task is rescheduled if not updated with a status after this time (heartbeat mechanism). Useful when the worker polls for the task but fails to complete due to errors/network failure. | Defaults to 600 |
| pollTimeoutSeconds | number | Time in seconds, after which the task is marked as `TIMED_OUT` if not polled by a worker. | No timeouts if set to 0 |
| inputKeys | array of string(s) | Array of keys of task's expected input. Used for documenting task's input. | Optional. See [Using inputKeys and outputKeys](#using-inputkeys-and-outputkeys). |
| outputKeys | array of string(s) | Array of keys of task's expected output. Used for documenting task's output. | Optional. See [Using inputKeys and outputKeys](#using-inputkeys-and-outputkeys). |
| inputTemplate | object | Define default input values. | Optional. See [Using inputTemplate](#using-inputtemplate) |
| concurrentExecLimit | number | Number of tasks that can be executed at any given time. | Optional |
| rateLimitFrequencyInSeconds | number | Sets the rate limit frequency window. | Optional. See [Task Rate limits](#task-rate-limits) |
| rateLimitPerFrequency | number | Sets the max number of tasks that can be given to workers within window. | Optional. See [Task Rate limits](#task-rate-limits) below |
| ownerEmail | string | Email address of the team that owns the task. | Required |
### Retry Logic
The `retryLogic` field controls how the delay between retries is computed. The final delay applied is:
```
delay = clamp(computedDelay, 0, maxRetryDelaySeconds) + random(0, backoffJitterMs) ms
```
where `clamp` only applies when `maxRetryDelaySeconds > 0`.
| Value | Delay formula | Notes |
| :--- | :--- | :--- |
| `FIXED` | `retryDelaySeconds` | Constant delay every retry. |
| `EXPONENTIAL_BACKOFF` | `retryDelaySeconds × 2^attemptNumber` | Doubles each attempt. Cap with `maxRetryDelaySeconds` to avoid runaway delays. |
| `LINEAR_BACKOFF` | `retryDelaySeconds × backoffScaleFactor × attemptNumber` | Grows linearly. `backoffScaleFactor` defaults to 1. |
**`maxRetryDelaySeconds`** — caps the computed delay so it never exceeds this value. Example with `EXPONENTIAL_BACKOFF`, `retryDelaySeconds=1`, `maxRetryDelaySeconds=3`:
| Attempt | Raw delay | After cap |
| :--- | :--- | :--- |
| 0 | 1s | 1s |
| 1 | 2s | 2s |
| 2 | 4s | 3s |
| 3+ | 8s+ | 3s |
**`backoffJitterMs`** — adds a uniform random value in `[0, backoffJitterMs]` milliseconds to the final delay. This spreads retries from multiple failing workers across time (thundering herd prevention). Example: `retryDelaySeconds=2`, `backoffJitterMs=1000` → each retry fires between 2 000 ms and 3 000 ms after failure.
### Timeout Policy
* `RETRY`: Retries the task again
* `TIME_OUT_WF`: Workflow is marked as TIMED_OUT and terminated. This is the default value.
* `ALERT_ONLY`: Registers a counter (task_timeout)
### Task Concurrent Execution Limits
`concurrentExecLimit` limits the number of simultaneous Task executions at any point.
**Example**
You have 1000 task executions waiting in the queue, and 1000 workers polling this queue for tasks, but if you have set `concurrentExecLimit` to 10, only 10 tasks would be given to workers (which would lead to starvation). If any of the workers finishes execution, a new task(s) will be removed from the queue, while still keeping the current execution count to 10.
### Task Rate Limits
!!! note "Rate Limiting"
Rate limiting is only supported for the Redis-persistence module and is not available with other persistence layers.
* `rateLimitFrequencyInSeconds` and `rateLimitPerFrequency` should be used together.
* `rateLimitFrequencyInSeconds` sets the "frequency window", i.e the `duration` to be used in `events per duration`. Eg: 1s, 5s, 60s, 300s etc.
* `rateLimitPerFrequency`defines the number of Tasks that can be given to Workers per given "frequency window". No rate limit if set to 0.
**Example**
Let's set `rateLimitFrequencyInSeconds = 5`, and `rateLimitPerFrequency = 12`. This means our frequency window is of 5 seconds duration, and for each frequency window, Conductor would only give 12 tasks to workers. So, in a given minute, Conductor would only give 12*(60/5) = 144 tasks to workers irrespective of the number of workers that are polling for the task.
Note that unlike `concurrentExecLimit`, rate limiting doesn't take into account tasks already in progress or a terminal state. Even if all the previous tasks are executed within 1 sec, or would take a few days, the new tasks are still given to workers at configured frequency, 144 tasks per minute in above example.
### Using `inputKeys` and `outputKeys`
* `inputKeys` and `outputKeys` can be considered as parameters and return values for the Task.
* Consider the task Definition as being represented by an interface: ```(value1, value2 .. valueN) someTaskDefinition(key1, key2 .. keyN);```.
* However, these parameters are not strictly enforced at the moment. Both `inputKeys` and `outputKeys` act as a documentation for task re-use. The tasks in workflow need not define all of the keys in the task definition.
* In the future, this can be extended to be a strict template that all task implementations must adhere to, just like interfaces in programming languages.
### Using `inputTemplate`
* `inputTemplate` allows to define default values, which can be overridden by values provided in Workflow.
* Eg: In your Task Definition, you can define your inputTemplate as:
```json
"inputTemplate": {
"url": "https://some_url:7004"
}
```
* Now, in your workflow Definition, when using above task, you can use the default `url` or override with something else in the task's `inputParameters`.
```json
"inputParameters": {
"url": "${workflow.input.some_new_url}"
}
```
## Retry configuration examples
### Retrying a flaky external API call
```json
{
"name": "call_payment_api",
"retryCount": 5,
"retryLogic": "EXPONENTIAL_BACKOFF",
"retryDelaySeconds": 2,
"maxRetryDelaySeconds": 60,
"backoffJitterMs": 2000,
"responseTimeoutSeconds": 30,
"timeoutSeconds": 300,
"timeoutPolicy": "RETRY",
"ownerEmail": "payments@example.com"
}
```
Retries up to 5 times with delays 2s, 4s, 8s, 16s, 32s — capped at 60s — plus up to 2 seconds of random jitter on each attempt. Prevents hammering a degraded payment provider.
### Bounded retry budget with `totalTimeoutSeconds`
```json
{
"name": "process_order",
"retryCount": 10,
"retryLogic": "FIXED",
"retryDelaySeconds": 5,
"totalTimeoutSeconds": 120,
"timeoutPolicy": "TIME_OUT_WF",
"ownerEmail": "orders@example.com"
}
```
Retries every 5 seconds, but the entire sequence — all attempts combined — must finish within 2 minutes. Even if `retryCount` isn't exhausted, the task fails once the 2-minute budget is consumed.
### High-throughput worker with jitter
```json
{
"name": "send_notification",
"retryCount": 3,
"retryLogic": "FIXED",
"retryDelaySeconds": 1,
"backoffJitterMs": 3000,
"concurrentExecLimit": 500,
"ownerEmail": "notifications@example.com"
}
```
When thousands of notifications fail simultaneously (e.g., downstream outage), jitter spreads the retries across a 3-second window instead of all hammering the service at once.
## Complete Example
``` json
{
"name": "encode_task",
"retryCount": 3,
"retryLogic": "EXPONENTIAL_BACKOFF",
"retryDelaySeconds": 10,
"maxRetryDelaySeconds": 120,
"backoffJitterMs": 5000,
"totalTimeoutSeconds": 600,
"timeoutSeconds": 1200,
"timeoutPolicy": "TIME_OUT_WF",
"responseTimeoutSeconds": 3600,
"pollTimeoutSeconds": 3600,
"inputKeys": [
"sourceRequestId",
"qcElementType"
],
"outputKeys": [
"state",
"skipped",
"result"
],
"concurrentExecLimit": 100,
"rateLimitFrequencyInSeconds": 60,
"rateLimitPerFrequency": 50,
"ownerEmail": "foo@bar.com",
"description": "Sample Encoding task"
}
```