Dependencies
Task dependencies, blocking, and dependency graphs
Dependencies
Tasks can depend on other tasks, enabling complex workflows where work is automatically sequenced based on completion.
Basic Dependencies
import { createTask, completeTask, getTask } from 'digital-tasks'
// Create first task
const task1 = await createTask({
function: { type: 'code', name: 'fetchData', ... },
})
// Create task that depends on task1
const task2 = await createTask({
function: { type: 'code', name: 'processData', ... },
dependencies: [task1.id],
})
console.log(task2.status) // 'blocked'
// When task1 completes, task2 automatically unblocks
await completeTask(task1.id, { data: [...] })
const updated = await getTask(task2.id)
console.log(updated.status) // 'queued'Multiple Dependencies
// Task depends on multiple tasks completing
const finalTask = await createTask({
function: processFunc,
dependencies: [task1.id, task2.id, task3.id],
})
// Task remains blocked until ALL dependencies complete
console.log(finalTask.status) // 'blocked'
await completeTask(task1.id, result1)
await completeTask(task2.id, result2)
// Still blocked - task3 not complete
const stillBlocked = await getTask(finalTask.id)
console.log(stillBlocked.status) // 'blocked'
await completeTask(task3.id, result3)
// Now unblocked
const unblocked = await getTask(finalTask.id)
console.log(unblocked.status) // 'queued'Dependency Types
interface TaskDependency {
taskId: string
type: 'completion' | 'success' | 'any'
}
// Default: completion (task must complete, success or failure)
const task = await createTask({
function: func,
dependencies: ['task_1'], // Same as [{ taskId: 'task_1', type: 'completion' }]
})
// Success: task must complete successfully
const strictTask = await createTask({
function: func,
dependencies: [{ taskId: 'task_1', type: 'success' }],
})
// Any: proceeds when dependency reaches any terminal state
const flexibleTask = await createTask({
function: func,
dependencies: [{ taskId: 'task_1', type: 'any' }],
})Dependency Graph Utilities
Get Dependants
Find tasks that depend on a given task:
import { getDependants } from 'digital-tasks'
const allTasks = await getAllProjectTasks(projectId)
const dependants = getDependants(task.id, allTasks)
// Returns tasks that will be affected when this task completes
console.log(dependants.map(t => t.name))Get Dependencies
Find tasks that a given task depends on:
import { getDependencies } from 'digital-tasks'
const dependencies = getDependencies(task, allTasks)
// Returns the actual task objects this task is waiting for
console.log(dependencies.map(t => ({ id: t.id, status: t.status })))Get Ready Tasks
Find tasks that can be executed now:
import { getReadyTasks } from 'digital-tasks'
const allTasks = await getAllProjectTasks(projectId)
const ready = getReadyTasks(allTasks)
// Returns tasks with status 'queued' and no unsatisfied dependencies
console.log(`${ready.length} tasks ready to execute`)Check for Cycles
Detect circular dependencies:
import { hasCycles } from 'digital-tasks'
const tasks = [
{ id: 'a', dependencies: ['b'] },
{ id: 'b', dependencies: ['c'] },
{ id: 'c', dependencies: ['a'] }, // Creates cycle!
]
const cyclic = hasCycles(tasks)
console.log(cyclic) // trueTopological Sort
Get execution order:
import { sortTasks } from 'digital-tasks'
const sorted = sortTasks(allTasks)
// Returns tasks in valid execution order
// Tasks with no dependencies come first
sorted.forEach((task, index) => {
console.log(`${index + 1}. ${task.name}`)
})Dependency Visualization
import { visualizeDependencies } from 'digital-tasks'
const diagram = visualizeDependencies(allTasks, {
format: 'mermaid',
})
console.log(diagram)
// graph TD
// task_1[Fetch Data]
// task_2[Process Data]
// task_3[Generate Report]
// task_1 --> task_2
// task_2 --> task_3Cascading Effects
Failed Dependencies
When a dependency fails:
// task2 depends on task1
await failTask(task1.id, 'Error occurred')
// task2 can be configured to:
// 1. Stay blocked (default for 'success' type)
// 2. Automatically fail
// 3. Unblock anyway ('any' type)
const task2 = await createTask({
function: func,
dependencies: [{ taskId: task1.id, type: 'success' }],
onDependencyFailed: 'fail', // 'block' | 'fail' | 'ignore'
})Cancelled Dependencies
await cancelTask(task1.id, 'No longer needed')
// Dependent tasks can cascade cancel
const task2 = await createTask({
function: func,
dependencies: [task1.id],
onDependencyCancelled: 'cancel', // 'block' | 'cancel' | 'ignore'
})Dynamic Dependencies
Add or remove dependencies at runtime:
import { addDependency, removeDependency } from 'digital-tasks'
// Add dependency
await addDependency(task2.id, task1.id)
// Remove dependency
await removeDependency(task2.id, task1.id)Data Flow Between Tasks
Pass output from one task as input to dependents:
// Task 1 produces data
const task1 = await createTask({
function: {
type: 'code',
name: 'fetchUsers',
output: 'array',
},
})
// Task 2 consumes task1's output
const task2 = await createTask({
function: {
type: 'code',
name: 'processUsers',
args: { users: 'Array of users' },
},
dependencies: [task1.id],
inputMapping: {
users: { from: task1.id, path: 'output' },
},
})
// When task1 completes, task2 receives its output
await completeTask(task1.id, [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }])
// task2.input.users is now [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]Parallel and Sequential Groups
import { createTask, parallel, sequential } from 'digital-tasks'
// Parallel: all tasks can run simultaneously
const parallelGroup = parallel([
createTask({ function: func1 }),
createTask({ function: func2 }),
createTask({ function: func3 }),
])
// Sequential: each task depends on the previous
const sequentialGroup = sequential([
createTask({ function: step1 }),
createTask({ function: step2 }),
createTask({ function: step3 }),
])
// Automatically creates: step2 depends on step1, step3 depends on step2Best Practices
- Avoid circular dependencies - Use
hasCycles()to validate - Keep dependency chains short - Long chains increase latency
- Use success type sparingly - Consider if 'completion' suffices
- Handle failed dependencies explicitly - Configure cascade behavior
- Visualize complex graphs - Catch issues early
Was this page helpful?