- 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>
141 lines
4.1 KiB
Plaintext
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"
|
|
}
|
|
}
|