Skip to content

kravetsone/taskora

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

194 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

taskora

Test npm license

Task queue for Node.js. TypeScript-first, Redis-backed, batteries-included.

Define tasks with handlers, dispatch jobs with full type inference, compose them into workflows, schedule them on cron or intervals, retry on failure, cancel in flight, inspect everything. Runs on Node, Bun, and Deno. Full docs at kravetsone.github.io/taskora.

v0.x β€” the public API is stable enough to use in production (332 tests across the full feature surface, every commit runs on 5 runtime/driver combinations), but minor versions may still break API until 1.0.

Install

npm install taskora ioredis
# or: pnpm add taskora ioredis
# or: bun add taskora ioredis
# or: yarn add taskora ioredis

ioredis is an optional peer dependency β€” required for the Redis adapter. On Bun you can skip it and use the native Bun.RedisClient driver via taskora/redis/bun.

Quick start

import { createTaskora } from "taskora"
import { redisAdapter } from "taskora/redis"
import { z } from "zod"

const taskora = createTaskora({
  adapter: redisAdapter("redis://localhost:6379"),
})

// Define a task with full type inference from the schema
const sendEmailTask = taskora.task("send-email", {
  input: z.object({
    to: z.string().email(),
    subject: z.string(),
  }),
  retry: { attempts: 3, backoff: "exponential" },
  handler: async (data, ctx) => {
    ctx.log.info("sending", { to: data.to })
    return { messageId: await mailer.send(data) }
  },
})

// Start the worker loop
await taskora.start()

// Dispatch a job β€” typed end-to-end
const handle = sendEmailTask.dispatch({
  to: "alice@example.com",
  subject: "Welcome",
})

const { messageId } = await handle.result // typed!

Features

Task primitives

  • Named tasks with Standard Schema validation (Zod, Valibot, ArkType β€” any library)
  • Typed dispatch() β†’ typed ResultHandle β†’ typed await handle.result
  • Task contracts β€” split producer and worker into separate processes without leaking handler code
  • Configurable retry with fixed/linear/exponential backoff, jitter, retryOn / noRetryOn filters, and ctx.retry() for manual control
  • Per-task concurrency, timeouts, middleware (Koa-style onion), and onCancel hooks

Workflows (canvas)

  • chain() β€” sequential pipeline with type inference across steps
  • group() β€” parallel execution with tuple result
  • chord() β€” group header feeding a callback
  • .pipe(), .map(), .chunk() β€” fluent composition and batch helpers
  • Cascade cancellation, workflow TTL, full DAG model

Flow control

  • Debounce β€” replace-on-new-dispatch within a window
  • Throttle β€” rate-limit by key
  • Deduplicate β€” skip if a matching job already exists
  • TTL / expiration β€” fail or discard jobs older than maxAge
  • Collect β€” accumulate items into batches with debounce + maxSize + maxWait triggers
  • Singleton β€” one active job at a time, global across workers
  • Per-key concurrency limits

Scheduling

  • app.schedule() with interval ("5m", "1h") or cron expressions
  • Leader election via Redis, automatic failover
  • Missed-run policies: "skip" / "catch-up" / "catch-up-limit:N"
  • Runtime management: pause, resume, trigger, list, update

Cancellation (docs)

  • First-class "cancelled" state, distinct from "failed"
  • handle.cancel() works on waiting, delayed, retrying, and active jobs
  • Instant cancellation via Redis pub/sub (no polling)
  • onCancel hook for cleanup, cascade cancellation for workflows

Versioning & migrations (docs)

  • Task version + migration chain (tuple or sparse record form)
  • Worker silently nacks future versions, fails expired ones
  • Inspector shows version distribution to check drain state before bumping since

Observability

  • Typed events: completed / failed / retrying / progress / active / stalled / cancelled
  • Inspector API: stats, jobs by state, cross-task find(jobId) with full timeline
  • Admin dashboard β€” @taskora/board (separate fullstack package) β€” React SPA with SSE live updates, workflow DAG visualisation, DLQ management
  • Structured job logs via ctx.log.info() / warn() / error()
  • Progress reporting via ctx.progress()

Dead letter queue

  • app.deadLetters.list() / retry() / retryAll() β€” single and bulk recovery
  • Configurable retention: { completed: { maxAge, maxItems }, failed: { ... } }

Runtime support

  • Node 20 (maintenance LTS) and Node 24 (current LTS)
  • Bun 1.3+ with either ioredis or native Bun.RedisClient
  • Deno 2.x via npm: specifier
  • Zero runtime dependencies β€” everything is an optional peer

Runs everywhere β€” tested everywhere

Every commit runs the full 300-test integration suite against a live Redis on every supported runtime Γ— driver combination, in parallel on CI:

Runtime Driver
Node 24 (current LTS) taskora/redis (ioredis) 300 / 300
Node 20 (maintenance LTS) taskora/redis (ioredis) 300 / 300
Bun 1.3+ taskora/redis/ioredis 300 / 300
Bun 1.3+ taskora/redis/bun (native Bun.RedisClient) 300 / 300
Deno 2.x taskora/redis (via npm: specifier) 300 / 300

1,500 live-Redis test runs per push β€” covering Lua scripts, blocking dequeues, pub/sub cancellation, distributed leader election, workflow DAGs, schedulers, flow control, and DLQ management. The release workflow is gated on every cell being green. See Cross-runtime CI for the full matrix and how to reproduce any cell locally.

Package layout

taskora                 β€” core engine, Task API, workflows (zero DB deps)
taskora/redis           β€” Redis adapter, re-exports ./redis/ioredis
taskora/redis/ioredis   β€” explicit ioredis driver (Node, Bun, Deno)
taskora/redis/bun       β€” native Bun.RedisClient driver (Bun only, no peer deps)
taskora/memory          β€” in-memory adapter for development & tests
taskora/test            β€” test runner with virtual time

@taskora/board          β€” admin dashboard, separate fullstack package (peer deps: taskora, hono)

Documentation

Full documentation at kravetsone.github.io/taskora.

AI-friendly documentation

taskora ships a curated /taskora Agent Skill β€” a single SKILL.md that Claude Code, Cursor, Windsurf, Cline and 40+ other AI coding agents can consume directly. Install into any supported agent with one command:

npx skills add kravetsone/taskora/documentation/skills

The CLI detects which agents you have installed and syncs the skill into the right directory for each. See the AI Skills guide for agent-specific install paths and manual installation.

License

MIT Β© kravetsone

About

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages