Files
jobqueue/docs/jobqueue.c4
Giancarmine Salucci a9429e2118 fix: harden queue lifecycle and publish gate
- Preserve phase results on partial retry and keep interrupted phase
  context after restart.
- Avoid webhook bookkeeping crashes when retention deletes stale jobs.
- Add deeper unit, integration, and e2e coverage around queue seams.
- Require verify job to pass before publish runs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-16 18:39:19 +02:00

141 lines
4.1 KiB
Plaintext

specification {
element actor {
style {
shape person
}
}
element system {
style {
shape rectangle
}
}
element container {
style {
shape rectangle
}
}
element component {
style {
shape component
}
}
element database {
style {
shape storage
}
}
relationship async {
color amber
line dotted
}
}
model {
consumer = actor "Consumer application"
webhookReceiver = system "Webhook receiver"
jobqueue = system "jobqueue" {
api = container "Public API" {
technology "ESM / TypeScript"
description "JobQueue constructor plus enqueue, retry, cancel, query, stream, shutdown APIs"
}
runtime = container "Runtime orchestrator" {
technology "Node.js"
description "Coordinates persistence, execution, retries, events, SSE, webhooks, and shutdown"
queue = component "JobQueue"
storage = component "SqliteStorage"
pool = component "WorkerPool"
runner = component "PhaseRunner"
retry = component "RetryStrategy"
events = component "TypedEventBus"
sse = component "SseSerializer"
retention = component "RetentionScheduler"
webhooks = component "WebhookDispatcher"
queue -> storage "persists job state"
queue -> pool "dispatches runnable jobs"
queue -> runner "executes phase pipeline"
queue -> retry "classifies failures"
queue -> events "emits typed queue events"
queue -> sse "serializes SSE payloads"
queue -> retention "runs stale/delete cycle"
queue -[async]-> webhooks "dispatches outbound callbacks"
}
sqlite = database "SQLite jobs database" {
technology "better-sqlite3 + WAL"
}
handlers = container "Registered phase handlers" {
technology "Consumer-provided async functions"
}
streams = container "SSE subscribers" {
technology "ReadableStream consumers"
}
api -> runtime.queue "constructs and invokes"
runtime.storage -> sqlite "reads/writes rows"
runtime.runner -> handlers "invokes phase handlers"
runtime.events -> streams "pushes queue events"
}
consumer -> jobqueue.api "enqueue / retry / cancel / inspect / subscribe"
jobqueue.runtime.webhooks -[async]-> webhookReceiver "POST job events"
}
views {
view index {
title "jobqueue landscape"
include *
autoLayout LeftRight
}
view library of jobqueue {
title "jobqueue containers"
include *
autoLayout LeftRight
}
view runtime of jobqueue.runtime {
title "jobqueue runtime components"
include *
autoLayout LeftRight
}
dynamic view enqueue-to-complete {
title "Enqueue to successful completion"
consumer -> jobqueue.api "enqueue()"
jobqueue.api -> jobqueue.runtime.queue "create job"
jobqueue.runtime.queue -> jobqueue.runtime.storage "persist pending row"
jobqueue.runtime.queue -> jobqueue.runtime.pool "schedule worker"
jobqueue.runtime.pool -> jobqueue.runtime.runner "run phases"
jobqueue.runtime.runner -> jobqueue.handlers "invoke handler(s)"
jobqueue.runtime.runner -> jobqueue.runtime.storage "persist progress + phase results"
jobqueue.runtime.queue -> jobqueue.runtime.events "emit queue events"
jobqueue.runtime.events -> jobqueue.streams "push SSE"
jobqueue.runtime.queue -> jobqueue.runtime.webhooks "send completion webhook"
jobqueue.runtime.webhooks -> webhookReceiver "POST payload"
jobqueue.runtime.queue -> jobqueue.runtime.storage "mark webhook_sent"
}
dynamic view retry-flow {
title "Failure and retry flow"
jobqueue.runtime.runner -> jobqueue.handlers "invoke handler"
jobqueue.handlers -> jobqueue.runtime.queue "throw recoverable error"
jobqueue.runtime.queue -> jobqueue.runtime.retry "classify error"
jobqueue.runtime.retry -> jobqueue.runtime.queue "retry with delay"
jobqueue.runtime.queue -> jobqueue.runtime.storage "persist pending retry"
jobqueue.runtime.queue -> jobqueue.runtime.events "emit job:retrying"
jobqueue.runtime.events -> jobqueue.streams "push SSE"
jobqueue.runtime.queue -[async]-> jobqueue.runtime.webhooks "dispatch retry webhook"
}
}