diff --git a/src/task-queue.ts b/src/task-queue.ts index 9a462b29..d42c05e4 100644 --- a/src/task-queue.ts +++ b/src/task-queue.ts @@ -1,18 +1,46 @@ +/** + * @fileoverview Task queue for managing Claude prompts and operations + * + * Provides a priority queue for tasks with: + * - Priority-based ordering (higher priority first) + * - Dependency tracking between tasks + * - State persistence via StateStore + * - Session assignment for task execution + * + * @module task-queue + */ + import { EventEmitter } from 'node:events'; import { Task, CreateTaskOptions } from './task.js'; import { getStore } from './state-store.js'; import { TaskState } from './types.js'; +/** + * Events emitted by TaskQueue + */ export interface TaskQueueEvents { + /** Fired when a task is added to the queue */ taskAdded: (task: Task) => void; + /** Fired when a task is removed from the queue */ taskRemoved: (taskId: string) => void; + /** Fired when a task's state changes */ taskUpdated: (task: Task) => void; } +/** + * Priority queue for managing tasks with dependency support. + * + * @description + * Tasks are ordered by priority (descending) then creation time (ascending). + * Dependencies can be specified to ensure tasks run in correct order. + * + * @extends EventEmitter + */ export class TaskQueue extends EventEmitter { private tasks: Map = new Map(); private store = getStore(); + /** Creates a new TaskQueue and loads persisted tasks. */ constructor() { super(); this.loadFromStore(); @@ -26,6 +54,7 @@ export class TaskQueue extends EventEmitter { } } + /** Adds a new task to the queue. */ addTask(options: CreateTaskOptions): Task { const task = new Task(options); this.tasks.set(task.id, task); @@ -34,10 +63,12 @@ export class TaskQueue extends EventEmitter { return task; } + /** Gets a task by ID. */ getTask(id: string): Task | undefined { return this.tasks.get(id); } + /** Removes a task by ID. Returns true if removed. */ removeTask(id: string): boolean { const removed = this.tasks.delete(id); if (removed) { @@ -47,16 +78,19 @@ export class TaskQueue extends EventEmitter { return removed; } + /** Updates a task and persists the change. */ updateTask(task: Task): void { this.tasks.set(task.id, task); this.store.setTask(task.id, task.toState()); this.emit('taskUpdated', task); } + /** Gets all tasks in the queue. */ getAllTasks(): Task[] { return Array.from(this.tasks.values()); } + /** Gets pending tasks sorted by priority then creation time. */ getPendingTasks(): Task[] { return this.getAllTasks() .filter((t) => t.isPending()) @@ -69,22 +103,27 @@ export class TaskQueue extends EventEmitter { }); } + /** Gets tasks currently being executed. */ getRunningTasks(): Task[] { return this.getAllTasks().filter((t) => t.isRunning()); } + /** Gets successfully completed tasks. */ getCompletedTasks(): Task[] { return this.getAllTasks().filter((t) => t.isCompleted()); } + /** Gets tasks that failed execution. */ getFailedTasks(): Task[] { return this.getAllTasks().filter((t) => t.isFailed()); } + /** Returns true if there's a task ready for execution. */ hasNext(): boolean { return this.getNextAvailable() !== null; } + /** Gets the next task ready for execution (with satisfied dependencies). */ getNextAvailable(): Task | null { const pending = this.getPendingTasks(); @@ -97,6 +136,7 @@ export class TaskQueue extends EventEmitter { return null; } + /** Alias for getNextAvailable(). */ next(): Task | null { return this.getNextAvailable(); } @@ -111,16 +151,19 @@ export class TaskQueue extends EventEmitter { return true; } + /** Gets all tasks assigned to a specific session. */ getTasksBySession(sessionId: string): Task[] { return this.getAllTasks().filter((t) => t.assignedSessionId === sessionId); } + /** Gets the currently running task for a session, if any. */ getRunningTaskForSession(sessionId: string): Task | null { return this.getAllTasks().find( (t) => t.isRunning() && t.assignedSessionId === sessionId ) || null; } + /** Gets counts of tasks by status. */ getCount(): { total: number; pending: number; running: number; completed: number; failed: number } { const tasks = this.getAllTasks(); return { @@ -132,6 +175,7 @@ export class TaskQueue extends EventEmitter { }; } + /** Removes all completed tasks. Returns count removed. */ clearCompleted(): number { let count = 0; for (const task of this.getAllTasks()) { @@ -143,6 +187,7 @@ export class TaskQueue extends EventEmitter { return count; } + /** Removes all failed tasks. Returns count removed. */ clearFailed(): number { let count = 0; for (const task of this.getAllTasks()) { @@ -154,6 +199,7 @@ export class TaskQueue extends EventEmitter { return count; } + /** Removes all tasks from the queue. Returns count removed. */ clearAll(): number { const count = this.tasks.size; for (const id of this.tasks.keys()) { @@ -163,6 +209,7 @@ export class TaskQueue extends EventEmitter { return count; } + /** Gets tasks from persistent storage. */ getStoredTasks(): Record { return this.store.getTasks(); } @@ -171,6 +218,7 @@ export class TaskQueue extends EventEmitter { // Singleton instance let queueInstance: TaskQueue | null = null; +/** Gets or creates the singleton TaskQueue instance. */ export function getTaskQueue(): TaskQueue { if (!queueInstance) { queueInstance = new TaskQueue();