UNPKG

pg-boss

Version:

Queueing jobs in Node.js using PostgreSQL like a boss

208 lines (144 loc) 8.52 kB
'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var assert = require('assert'); module.exports = { applyConfig: applyConfig, applyNewJobCheckInterval: applyNewJobCheckInterval, checkPublishArgs: checkPublishArgs, checkSubscribeArgs: checkSubscribeArgs, checkFetchArgs: checkFetchArgs, assertAsync: assertAsync }; function checkPublishArgs(args) { var name = void 0, data = void 0, options = void 0; try { if (typeof args[0] === 'string') { name = args[0]; data = args[1]; assert(typeof data !== 'function', 'publish() cannot accept a function as the payload. Did you intend to use subscribe()?'); options = args[2]; } else if (_typeof(args[0]) === 'object') { assert(args.length === 1, 'publish object API only accepts 1 argument'); var job = args[0]; assert(job, 'boss requires all jobs to have a name'); name = job.name; data = job.data; options = job.options; } options = options || {}; assert(name, 'boss requires all jobs to have a queue name'); assert((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object', 'options should be an object'); } catch (error) { return Promise.reject(error); } return Promise.resolve({ name: name, data: data, options: options }); } function checkSubscribeArgs(name, args) { var options = void 0, callback = void 0; try { assert(name, 'missing job name'); if (args.length === 1) { callback = args[0]; options = {}; } else if (args.length > 1) { options = args[0] || {}; callback = args[1]; } assert(typeof callback === 'function', 'expected callback to be a function'); if (options) assert((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object', 'expected config to be an object'); name = sanitizeQueueNameForFetch(name); } catch (e) { return Promise.reject(e); } return Promise.resolve({ options: options, callback: callback }); } function checkFetchArgs(name, batchSize) { return assertAsync(name, 'missing queue name').then(function () { name = sanitizeQueueNameForFetch(name); assert(!batchSize || batchSize >= 1, 'fetch() assert: optional batchSize arg must be at least 1'); }).then(function () { return { name: name, batchSize: batchSize }; }); } function sanitizeQueueNameForFetch(name) { return name.replace(/[%_\*]/g, function (match) { return match === '*' ? '%' : '\\' + match; }); } function assertAsync(arg, errorMessage) { try { assert(arg, errorMessage); return Promise.resolve(arg); } catch (e) { return Promise.reject(e); } } function applyConfig(config) { assert(config && ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' || typeof config === 'string'), 'configuration assert: string or config object is required to connect to postgres'); config = applyDatabaseConfig(config); config = applyNewJobCheckInterval(config); config = applyExpireConfig(config); config = applyArchiveConfig(config); config = applyDeleteConfig(config); config = applyMonitoringConfig(config); config = applyUuidConfig(config); return config; } function applyDatabaseConfig(config) { config = typeof config === 'string' ? { connectionString: config } : config || {}; if (config.schema) { assert(typeof config.schema === 'string', 'configuration assert: schema must be a string'); assert(config.schema.length <= 50, 'configuration assert: schema name cannot exceed 50 characters'); assert(!/\W/.test(config.schema), 'configuration assert: ' + config.schema + ' cannot be used as a schema. Only alphanumeric characters and underscores are allowed'); } config.schema = config.schema || 'pgboss'; // byodb means we don't apply connection pooling if (_typeof(config.db) !== 'object') { assert(!('poolSize' in config) || config.poolSize >= 1, 'configuration assert: poolSize must be at least 1'); config.poolSize = config.poolSize || config.max || 10; } return config; } function applyNewJobCheckInterval(config) { assert(!('newJobCheckInterval' in config) || config.newJobCheckInterval >= 100, 'configuration assert: newJobCheckInterval must be at least every 100ms'); assert(!('newJobCheckIntervalSeconds' in config) || config.newJobCheckIntervalSeconds >= 1, 'configuration assert: newJobCheckIntervalSeconds must be at least every second'); config.newJobCheckInterval = 'newJobCheckIntervalSeconds' in config ? config.newJobCheckIntervalSeconds * 1000 : 'newJobCheckInterval' in config ? config.newJobCheckInterval : 1000; // default is 1 second return config; } function applyExpireConfig(config) { assert(!('expireCheckInterval' in config) || config.expireCheckInterval >= 100, 'configuration assert: expireCheckInterval must be at least every 100ms'); assert(!('expireCheckIntervalSeconds' in config) || config.expireCheckIntervalSeconds >= 1, 'configuration assert: expireCheckIntervalSeconds must be at least every second'); assert(!('expireCheckIntervalMinutes' in config) || config.expireCheckIntervalMinutes >= 1, 'configuration assert: expireCheckIntervalMinutes must be at least every minute'); config.expireCheckInterval = 'expireCheckIntervalMinutes' in config ? config.expireCheckIntervalMinutes * 60 * 1000 : 'expireCheckIntervalSeconds' in config ? config.expireCheckIntervalSeconds * 1000 : 'expireCheckInterval' in config ? config.expireCheckInterval : 60 * 1000; // default is 1 minute return config; } function applyArchiveConfig(config) { assert(!('archiveCheckInterval' in config) || config.archiveCheckInterval >= 100, 'configuration assert: archiveCheckInterval must be at least every 100ms'); assert(!('archiveCheckIntervalSeconds' in config) || config.archiveCheckIntervalSeconds >= 1, 'configuration assert: archiveCheckIntervalSeconds must be at least every second'); assert(!('archiveCheckIntervalMinutes' in config) || config.archiveCheckIntervalMinutes >= 1, 'configuration assert: archiveCheckIntervalMinutes must be at least every minute'); config.archiveCheckInterval = 'archiveCheckIntervalMinutes' in config ? config.archiveCheckIntervalMinutes * 60 * 1000 : 'archiveCheckIntervalSeconds' in config ? config.archiveCheckIntervalSeconds * 1000 : 'archiveCheckInterval' in config ? config.archiveCheckInterval : 60 * 60 * 1000; // default is 1 hour assert(!('archiveCompletedJobsEvery' in config) || typeof config.archiveCompletedJobsEvery === 'string', 'configuration assert: archiveCompletedJobsEvery should be a readable PostgreSQL interval such as "1 day"'); config.archiveCompletedJobsEvery = config.archiveCompletedJobsEvery || '1 hour'; return config; } function applyDeleteConfig(config) { config.deleteCheckInterval = 'deleteCheckInterval' in config ? config.deleteCheckInterval : 60 * 60 * 1000; // default is 1 hour // TODO: discontinue pg interval strings in favor of ms int for better validation (when interval is specified lower than check interval, for example) assert(!('deleteArchivedJobsEvery' in config) || typeof config.deleteArchivedJobsEvery === 'string', 'configuration assert: deleteArchivedJobsEvery should be a readable PostgreSQL interval such as "7 days"'); config.deleteArchivedJobsEvery = config.deleteArchivedJobsEvery || '7 days'; return config; } function applyMonitoringConfig(config) { assert(!('monitorStateIntervalSeconds' in config) || config.monitorStateIntervalSeconds >= 1, 'configuration assert: monitorStateIntervalSeconds must be at least every second'); assert(!('monitorStateIntervalMinutes' in config) || config.monitorStateIntervalMinutes >= 1, 'configuration assert: monitorStateIntervalMinutes must be at least every minute'); config.monitorStateInterval = 'monitorStateIntervalMinutes' in config ? config.monitorStateIntervalMinutes * 60 * 1000 : 'monitorStateIntervalSeconds' in config ? config.monitorStateIntervalSeconds * 1000 : null; return config; } function applyUuidConfig(config) { assert(!('uuid' in config) || config.uuid === 'v1' || config.uuid === 'v4', 'configuration assert: uuid option only supports v1 or v4'); config.uuid = config.uuid || 'v1'; return config; }