import debugModule from 'debug'; import EventEmitter from 'node:events'; import safe from 'safetydance'; const debug = debugModule('box:asynctask'); // this runs in-process class AsyncTask extends EventEmitter { name; #abortController; constructor(name) { super(); this.name = name; this.#abortController = new AbortController(); } async _run(/*signal*/) { // subclasses implement this } async start() { // should not throw! debug(`start: ${this.name} started`); const [error] = await safe(this._run(this.#abortController.signal)); debug(`start: ${this.name} finished`); this.emit('done', { errorMessage: error?.message || '' }); this.#abortController = null; } stop() { if (this.#abortController === null) return; // already finished debug(`stop: ${this.name} . sending abort signal`); this.#abortController.abort(); } emitProgress(percent, message) { this.emit('data', 'progress', { percent, message }); } emitData(obj) { this.emit('data', 'data', obj); } } export default { AsyncTask };