Files
RuDS/specs/task.allium

87 lines
2.3 KiB
Plaintext

-- allium: 1
-- bDS Background Task Manager
-- Distilled from: src/main/engine/TaskManager.ts
entity Task {
title: String
status: pending | running | completed | failed | cancelled
progress: Decimal? -- 0.0..1.0
message: String?
created_at: Timestamp
transitions status {
pending -> running
running -> completed
running -> failed
running -> cancelled
}
}
config {
max_concurrent: Integer = 3
progress_throttle: Duration = 250.milliseconds
}
invariant MaxConcurrency {
-- At most max_concurrent tasks run simultaneously
let running_tasks = Tasks where status = running
running_tasks.count <= config.max_concurrent
}
invariant FifoQueue {
-- When max concurrent reached, new tasks queue in FIFO order
-- Queued tasks transition to running as slots open
}
rule SubmitTask {
when: SubmitTaskRequested(title, work)
let running_tasks = Tasks where status = running
ensures: Task.created(title: title, status: pending)
ensures:
if running_tasks.count < config.max_concurrent:
TaskStarted(task, work)
}
rule CompleteTask {
when: TaskWorkCompleted(task)
ensures: task.status = completed
ensures: task.progress = 1.0
ensures: NextQueuedTaskStarted()
}
rule FailTask {
when: TaskWorkFailed(task, error_message)
ensures: task.status = failed
ensures: task.message = error_message
ensures: NextQueuedTaskStarted()
}
rule CancelTask {
when: CancelTaskRequested(task)
requires: task.status = running or task.status = pending
-- AbortController-based cancellation
ensures: task.status = cancelled
ensures: NextQueuedTaskStarted()
}
rule ReportProgress {
when: ProgressReported(task, value, message)
-- Progress events throttled to 250ms
ensures: task.progress = value
ensures: task.message = message
}
invariant ProgressThrottled {
-- Progress update events are throttled to prevent UI flooding
-- At most one progress event per 250ms per task
}
-- External tasks: lifecycle controlled by caller (e.g., renderer-side scripts)
rule RegisterExternalTask {
when: RegisterExternalTaskRequested(title)
ensures: Task.created(title: title, status: running)
@guidance
-- External tasks are not managed by the queue
-- The caller is responsible for updating status
}