UNPKG

@akala/core

Version:
75 lines (69 loc) 2.64 kB
import { EventEmitter } from './events/event-emitter.js' import type { IEvent } from './events/shared.js'; import { each as eachAsync } from './eachAsync.js'; import sequencify, { type Task } from './sequencify.js' interface EventMap { start: IEvent<[string[]], void> task_start: IEvent<[{ message: string, task: Task, taskName: string }], void> task_stop: IEvent<[{ message: string, task: Task, taskName: string }, Task], void> error: IEvent<[{ error: Error, task: Task }], void> stop: IEvent<[Error] | [], void> } /** * Orchestrates task execution with dependency management * @class Orchestrator * @extends EventEmitter * @fires Orchestrator#start * @fires Orchestrator#task_start * @fires Orchestrator#task_stop * @fires Orchestrator#error * @fires Orchestrator#stop */ export class Orchestrator extends EventEmitter<EventMap> { public readonly tasks: Record<string, Task & { name: string, action?: () => void | Promise<void> }> = {}; /** * Adds a task to the orchestrator * @param {string} name - Unique identifier for the task * @param {string[]} dependencies - Array of task names this task depends on * @param {function} [action] - Optional async function to execute for the task */ public add(name: string, dependencies: string[], action?: () => void | Promise<void>) { this.tasks[name] = { name, dep: dependencies, action } } /** * Executes tasks in dependency order * @param {...string} names - Task names to execute (and their dependencies) * @returns {Promise<void>} Resolves when all tasks complete, rejects on critical error */ public async start(...names: string[]): Promise<void> { const seq = sequencify(this.tasks, names); this.emit('start', names); try { await eachAsync(seq.sequence, async (task) => { this.emit('task_start', { message: `starting ${task}...`, task: this.tasks[task], taskName: task }); if (this.tasks[task].action) try { await this.tasks[task].action(); } catch (e) { this.emit('error', { error: e, task: this.tasks[task] }); throw e; } this.emit('task_stop', { message: `${task} finished.`, task: this.tasks[task], taskName: task }, this.tasks[task]); }) this.emit('stop'); } catch (e) { this.emit('stop', e); } } }