UNPKG

redis-smq-common

Version:

RedisSMQ Common Library provides many components that are mainly used by RedisSMQ and RedisSMQ Monitor.

193 lines 9.19 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WorkerResourceGroup = void 0; const fs_1 = require("fs"); const path_1 = __importDefault(require("path")); const index_js_1 = require("../async/index.js"); const index_js_2 = require("../errors/index.js"); const index_js_3 = require("../redis-lock/index.js"); const index_js_4 = require("../power-switch/index.js"); const index_js_5 = require("../runnable/index.js"); const worker_runnable_js_1 = require("./worker-runnable.js"); class WorkerResourceGroup extends index_js_5.Runnable { constructor(redisClient, logger, resourceGroupId) { super(); this.workers = []; this.runWorkersLocked = false; this.lock = (cb) => { this.logger.debug('Attempting to acquire lock...'); this.locker.acquireLock((err, acquired) => { if (err) { this.logger.error(`Failed to acquire lock: ${err.message}`, err); cb(err); } else if (acquired) { this.logger.info(`Workers are exclusively running from this instance (Lock ID ${this.locker.getId()}).`); cb(); } else { this.logger.warn('Lock was not acquired, but no error was returned'); cb(); } }); }; this.runWorkers = (cb) => { if (!this.runWorkersLocked) { this.logger.info(`Starting ${this.workers.length} workers...`); this.runWorkersLocked = true; index_js_1.async.eachOf(this.workers, (worker, index, done) => { this.logger.debug(`Starting worker ${index + 1}/${this.workers.length} (ID: ${worker.getId()})`); worker.run((err) => { if (err) { this.logger.error(`Failed to start worker ${index + 1}/${this.workers.length} (ID: ${worker.getId()}): ${err.message}`, err); } else { this.logger.debug(`Worker ${index + 1}/${this.workers.length} (ID: ${worker.getId()}) started successfully`); } done(err); }); }, (err) => { this.runWorkersLocked = false; if (err) { this.logger.error(`Error starting workers: ${err.message}`, err); } else { this.logger.info(`All ${this.workers.length} workers started successfully`); } cb(err); }); } else { this.logger.warn('Attempted to run workers while already locked'); cb(new index_js_2.AbortError()); } }; this.shutDownWorkers = (cb) => { if (!this.runWorkersLocked) { this.logger.info(`Shutting down ${this.workers.length} workers...`); this.runWorkersLocked = true; index_js_1.async.eachOf(this.workers, (worker, index, done) => { this.logger.debug(`Shutting down worker ${index + 1}/${this.workers.length} (ID: ${worker.getId()})`); worker.shutdown((err) => { if (err) { this.logger.warn(`Error shutting down worker ${index + 1}/${this.workers.length} (ID: ${worker.getId()}): ${err.message}`); } else { this.logger.debug(`Worker ${index + 1}/${this.workers.length} (ID: ${worker.getId()}) shut down successfully`); } done(); }); }, () => { this.workers = []; this.runWorkersLocked = false; this.logger.info('All workers have been shut down'); cb(); }); } else { this.logger.debug('Workers shutdown requested but workers are locked, retrying in 1 second...'); setTimeout(() => this.shutDownWorkers(cb), 1000); } }; this.releaseLock = (cb) => { this.logger.debug('Releasing lock...'); this.locker.releaseLock((err) => { if (err) { this.logger.error(`Failed to release lock: ${err.message}`, err); } else { this.logger.info('Lock released successfully'); } cb(err); }); }; this.addWorker = (filename, payload) => { this.logger.debug(`Adding worker from file: ${filename}`); const worker = new worker_runnable_js_1.WorkerRunnable(filename, payload, this.logger); worker.on('worker.error', (err) => { this.logger.error(`Worker error from ${filename}: ${err.message}`, err); this.handleError(err); }); this.workers.push(worker); this.logger.info(`Worker added from file: ${filename}, total workers: ${this.workers.length}`); }; this.loadFromDir = (workersDir, payload, cb) => { if (this.isDown() && !this.isGoingUp()) { this.logger.info(`Loading workers from directory: ${workersDir}`); (0, fs_1.readdir)(workersDir, (err, files) => { if (err) { this.logger.error(`Failed to read workers directory ${workersDir}: ${err.message}`, err); cb(err); } else { this.logger.debug(`Found ${files.length} files in workers directory`); let workerCount = 0; index_js_1.async.eachOf(files !== null && files !== void 0 ? files : [], (file, index, done) => { if (file.endsWith('.worker.js')) { const filepath = path_1.default.resolve(workersDir, file); this.logger.debug(`Loading worker file ${index + 1}/${files.length}: ${file}`); this.addWorker(filepath, payload); workerCount++; done(); } else { this.logger.debug(`Skipping non-worker file: ${file}`); done(); } }, (err) => { if (err) { this.logger.error(`Error loading workers: ${err.message}`, err); } else { this.logger.info(`Successfully loaded ${workerCount} workers from ${files.length} files`); } cb(err); }); } }); } else { this.logger.warn('Cannot load workers: WorkerResourceGroup is not in DOWN state'); cb(new Error('Cannot load workers: WorkerResourceGroup is not in DOWN state')); } }; this.powerManager = new index_js_4.PowerSwitch(); this.logger = logger; this.logger.info(`Initializing WorkerResourceGroup with ID: ${resourceGroupId}`); this.redisClient = redisClient; this.redisClient.once('error', (err) => { this.logger.error(`Redis client error: ${err.message}`, err); this.handleError(err); }); this.logger.debug(`Creating RedisLock for resource group: ${resourceGroupId}`); this.locker = new index_js_3.RedisLock(redisClient, logger, resourceGroupId, 60000, true, 15000); this.locker.on('locker.error', (err) => { this.logger.error(`Locker error: ${err.message}`, err); this.handleError(err); }); this.logger.info(`WorkerResourceGroup initialized with ID: ${resourceGroupId}`); } getLogger() { return this.logger; } goingUp() { this.logger.debug('WorkerResourceGroup going up...'); return super.goingUp().concat([this.lock, this.runWorkers]); } goingDown() { this.logger.debug('WorkerResourceGroup going down...'); return [this.shutDownWorkers, this.releaseLock].concat(super.goingDown()); } handleError(err) { if (this.isRunning()) { this.logger.error(`WorkerResourceGroup error: ${err.message}`, err); this.emit('workerResourceGroup.error', err); super.handleError(err); } } } exports.WorkerResourceGroup = WorkerResourceGroup; //# sourceMappingURL=worker-resource-group.js.map