builderman

A dependency-aware task runner for building, developing, and orchestrating complex workflows

Cancellation

You can cancel a running pipeline using an AbortSignal. This is useful for implementing timeouts, user-initiated cancellation, or graceful shutdown.

Basic Cancellation

import { pipeline, PipelineError } from "builderman"

const controller = new AbortController()

const runPromise = pipeline([backend, frontend]).run({
  signal: controller.signal,
})

// Cancel after 5 seconds
setTimeout(() => {
  controller.abort()
}, 5000)

const result = await runPromise

if (!result.ok && result.error.code === PipelineError.Aborted) {
  console.error("Pipeline was cancelled")
  console.log(`Tasks still running: ${result.stats.summary.running}`)
}

What Happens on Cancellation

When a pipeline is cancelled:

Timeout Example

Here's a practical example of implementing a timeout:

async function runWithTimeout(pipeline, timeoutMs) {
  const controller = new AbortController()

  const timeoutId = setTimeout(() => {
    controller.abort()
  }, timeoutMs)

  const result = await pipeline.run({
    signal: controller.signal,
  })
  
  clearTimeout(timeoutId)

  return result
}

const result = await runWithTimeout(
  pipeline([task1, task2, task3]),
  30000 // 30 second timeout
)

if (!result.ok && result.error.code === PipelineError.Aborted) {
  console.error("Pipeline timed out after 30 seconds")
}

User-Initiated Cancellation

You can also cancel based on user input or other events:

const controller = new AbortController()

// Handle Ctrl+C
process.on("SIGINT", () => {
  console.log("\nCancelling pipeline...")
  controller.abort()
})

const result = await pipeline([task1, task2, task3]).run({
  signal: controller.signal,
})

if (!result.ok && result.error.code === PipelineError.Aborted) {
  console.log("Pipeline was cancelled by user")
}

Related: Learn about Error Handling and Teardown.