import { Logger } from '../Logger'; import { TaskProvider } from './TaskProvider/TaskProvider'; import { ImmutableTaskList, Task, TaskList } from './Task'; import { TaskId } from './TaskId'; export class TaskQueue { private provider: TaskProvider; private readonly logger: Logger; constructor(provider: TaskProvider, logger: Logger) { this.provider = provider; this.logger = logger; } add(task: Task) { let items = this.getItems(); items.push(task); this.flushItems(items); } get(ts: number): Task | undefined { const readyItems = this.getItems().filter(t => t.ts <= ts); if (readyItems.length === 0) { return undefined; } return readyItems[0]; } findById(taskId: TaskId): Task | undefined { const [matched, _] = this.split(t => t.id === taskId); return matched.shift(); } has(predicate: (t: Task) => boolean): boolean { const [matched, _] = this.split(predicate); return matched.length > 0; } modify(predicate: (t: Task) => boolean, modifier: (t: Task) => Task): number { const [matched, other] = this.split(predicate); const modified = matched.map(modifier); const modifiedCount = modified.length; this.flushItems(modified.concat(other)); return modifiedCount; } remove(predicate: (t: Task) => boolean): number { const [_, other] = this.split(predicate); const result = other.length; this.flushItems(other); return result; } seeItems(): ImmutableTaskList { return this.getItems(); } private split(predicate: (t: Task) => boolean): [TaskList, TaskList] { const matched: TaskList = []; const other: TaskList = []; this.getItems().forEach(t => { if (predicate(t)) { matched.push(t); } else { other.push(t); } }); return [matched, other]; } private getItems(): TaskList { return this.provider.getTasks(); } private flushItems(items: TaskList): void { items.sort((x, y) => x.ts - y.ts || x.id.localeCompare(y.id)); this.provider.setTasks(items); } }