UNPKG

redis-smq

Version:

A simple high-performance Redis message queue for Node.js.

126 lines 5.63 kB
import { async, CallbackEmptyReplyError, logger, } from 'redis-smq-common'; import { RedisClient } from '../../common/redis-client/redis-client.js'; import { ELuaScriptName } from '../../common/redis-client/scripts/scripts.js'; import { redisKeys } from '../../common/redis-keys/redis-keys.js'; import { Configuration } from '../../config/index.js'; import { _parseQueueParamsAndValidate } from '../queue/_/_parse-queue-params-and-validate.js'; import { EQueueProperty, Queue, } from '../queue/index.js'; import { _hasRateLimitExceeded } from './_/_has-rate-limit-exceeded.js'; import { QueueRateLimitInvalidIntervalError, QueueRateLimitInvalidLimitError, QueueRateLimitQueueNotFoundError, } from './errors/index.js'; export class QueueRateLimit { redisClient; logger; queue; constructor() { this.logger = logger.getLogger(Configuration.getSetConfig().logger, `queue-rate-limit`); this.redisClient = new RedisClient(); this.redisClient.on('error', (err) => this.logger.error(err)); this.queue = new Queue(); } clear(queue, cb) { this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else if (!client) cb(new CallbackEmptyReplyError()); else _parseQueueParamsAndValidate(client, queue, (err, queueParams) => { if (err) cb(err); else if (!queueParams) cb(new CallbackEmptyReplyError()); else { const { keyQueueProperties, keyQueueRateLimitCounter } = redisKeys.getQueueKeys(queueParams, null); const multi = client.multi(); multi.hdel(keyQueueProperties, String(EQueueProperty.RATE_LIMIT)); multi.del(keyQueueRateLimitCounter); multi.exec((err) => cb(err)); } }); }); } set(queue, rateLimit, cb) { this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else if (!client) cb(new CallbackEmptyReplyError()); else _parseQueueParamsAndValidate(client, queue, (err, queueParams) => { if (err) cb(err); else if (!queueParams) cb(new CallbackEmptyReplyError()); else { const limit = Number(rateLimit.limit); if (isNaN(limit) || limit <= 0) { cb(new QueueRateLimitInvalidLimitError()); } const interval = Number(rateLimit.interval); if (isNaN(interval) || interval < 1000) { cb(new QueueRateLimitInvalidIntervalError()); } const validatedRateLimit = { interval, limit }; const { keyQueueProperties } = redisKeys.getQueueKeys(queueParams, null); client.runScript(ELuaScriptName.SET_QUEUE_RATE_LIMIT, [keyQueueProperties], [EQueueProperty.RATE_LIMIT, JSON.stringify(validatedRateLimit)], (err, reply) => { if (err) cb(err); else if (reply !== 'OK') cb(new QueueRateLimitQueueNotFoundError()); else cb(); }); } }); }); } hasExceeded(queue, rateLimit, cb) { this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else if (!client) cb(new CallbackEmptyReplyError()); else _parseQueueParamsAndValidate(client, queue, (err, queueParams) => { if (err) cb(err); else if (!queueParams) cb(new CallbackEmptyReplyError()); else _hasRateLimitExceeded(client, queueParams, rateLimit, cb); }); }); } get(queue, cb) { this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else if (!client) cb(new CallbackEmptyReplyError()); else _parseQueueParamsAndValidate(client, queue, (err, queueParams) => { if (err) cb(err); else if (!queueParams) cb(new CallbackEmptyReplyError()); else { const { keyQueueProperties } = redisKeys.getQueueKeys(queueParams, null); client.hget(keyQueueProperties, String(EQueueProperty.RATE_LIMIT), (err, reply) => { if (err) cb(err); else if (!reply) cb(null, null); else { const rateLimit = JSON.parse(reply); cb(null, rateLimit); } }); } }); }); } shutdown = (cb) => { async.waterfall([this.queue.shutdown, this.redisClient.shutdown], cb); }; } //# sourceMappingURL=queue-rate-limit.js.map