UNPKG

redis-smq-common

Version:

Provides essential components and utilities shared across RedisSMQ packages.

96 lines 3.79 kB
import { RunnableWorker } from '../runnable-worker.js'; import { async } from '../../async/index.js'; import { findFilesByPattern } from '../../env/filesystem.js'; export class WorkerLoader { logger; filenamePattern; onWorkerError; workerManager; constructor(logger, filenamePattern, onWorkerError, workerManager) { this.logger = logger.createLogger(this.constructor.name); this.filenamePattern = filenamePattern; this.onWorkerError = onWorkerError; this.workerManager = workerManager; } createWorker(filename, payload) { const worker = new RunnableWorker(filename, payload, this.logger); worker.removeAllListeners('worker.error'); worker.on('worker.error', (err) => { this.onWorkerError(err, filename); }); this.workerManager.addWorker(worker); return worker; } loadFromDirectory(directory, payload, cb) { findFilesByPattern(directory, this.filenamePattern, (err, files) => { if (err) { this.logger.error(`Failed to read directory ${directory}: ${err.message}`, err); cb(err); return; } const workerFiles = files ?? []; if (workerFiles.length === 0) { this.logger.warn(`No ${this.filenamePattern} files found in ${directory}`); cb(); return; } this.logger.debug(`Found ${workerFiles.length} worker files`); this.createWorkersBatch(workerFiles, payload, cb); }); } createWorkersBatch(filepaths, payload, cb) { const tempWorkers = []; async.eachOf(filepaths, (filepath, index, done) => { this.logger.debug(`Creating worker ${index + 1}/${filepaths.length}: ${filepath}`); try { const worker = new RunnableWorker(filepath, payload, this.logger); worker.on('worker.error', (err) => { this.logger.debug(`Temporary worker error from ${filepath}: ${err.message}`); }); tempWorkers.push(worker); done(); } catch (error) { const err = error instanceof Error ? error : new Error('Failed to create worker'); this.logger.error(`Failed to create worker from ${filepath}: ${err.message}`, err); done(err); } }, (err) => { if (err) { this.logger.error(`Error creating workers: ${err.message}`, err); this.cleanupTempWorkers(tempWorkers, () => cb(err)); return; } tempWorkers.forEach((worker) => { worker.removeAllListeners('worker.error'); worker.on('worker.error', (err) => { this.onWorkerError(err, worker.getWorkerFilename()); }); this.workerManager.addWorker(worker); }); this.logger.debug(`Successfully created ${tempWorkers.length} workers`); cb(); }); } cleanupTempWorkers(workers, cb) { if (workers.length === 0) { cb(); return; } this.logger.debug(`Cleaning up ${workers.length} temporary workers...`); async.each(workers, (worker, _, done) => { worker.shutdown((err) => { if (err) { this.logger.warn(`Temp worker cleanup failed: ${err.message}`); } done(); }); }, () => { this.logger.debug('Temporary workers cleaned up'); cb(); }); } } //# sourceMappingURL=worker-loader.js.map