- Updated all component headers and documentation
- Changed navbar and footer branding
- Updated homepage hero badge
- Modified page title in index.html
- Simplified footer text to 'Built with ❤️'
- Consistent V2 capitalization across all references
405 lines
14 KiB
JavaScript
405 lines
14 KiB
JavaScript
/*eslint-env node */
|
|
'use strict';
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.QueueGetters = void 0;
|
|
const queue_base_1 = require("./queue-base");
|
|
const job_1 = require("./job");
|
|
const utils_1 = require("../utils");
|
|
/**
|
|
*
|
|
* @class QueueGetters
|
|
* @extends QueueBase
|
|
*
|
|
* @description Provides different getters for different aspects of a queue.
|
|
*/
|
|
class QueueGetters extends queue_base_1.QueueBase {
|
|
getJob(jobId) {
|
|
return this.Job.fromId(this, jobId);
|
|
}
|
|
commandByType(types, count, callback) {
|
|
return types.map((type) => {
|
|
type = type === 'waiting' ? 'wait' : type; // alias
|
|
const key = this.toKey(type);
|
|
switch (type) {
|
|
case 'completed':
|
|
case 'failed':
|
|
case 'delayed':
|
|
case 'prioritized':
|
|
case 'repeat':
|
|
case 'waiting-children':
|
|
return callback(key, count ? 'zcard' : 'zrange');
|
|
case 'active':
|
|
case 'wait':
|
|
case 'paused':
|
|
return callback(key, count ? 'llen' : 'lrange');
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Helper to easily extend Job class calls.
|
|
*/
|
|
get Job() {
|
|
return job_1.Job;
|
|
}
|
|
sanitizeJobTypes(types) {
|
|
const currentTypes = typeof types === 'string' ? [types] : types;
|
|
if (Array.isArray(currentTypes) && currentTypes.length > 0) {
|
|
const sanitizedTypes = [...currentTypes];
|
|
if (sanitizedTypes.indexOf('waiting') !== -1) {
|
|
sanitizedTypes.push('paused');
|
|
}
|
|
return [...new Set(sanitizedTypes)];
|
|
}
|
|
return [
|
|
'active',
|
|
'completed',
|
|
'delayed',
|
|
'failed',
|
|
'paused',
|
|
'prioritized',
|
|
'waiting',
|
|
'waiting-children',
|
|
];
|
|
}
|
|
/**
|
|
Returns the number of jobs waiting to be processed. This includes jobs that are
|
|
"waiting" or "delayed" or "prioritized" or "waiting-children".
|
|
*/
|
|
async count() {
|
|
const count = await this.getJobCountByTypes('waiting', 'paused', 'delayed', 'prioritized', 'waiting-children');
|
|
return count;
|
|
}
|
|
/**
|
|
* Returns the time to live for a rate limited key in milliseconds.
|
|
* @returns -2 if the key does not exist.
|
|
* -1 if the key exists but has no associated expire.
|
|
* @see {@link https://redis.io/commands/pttl/}
|
|
*/
|
|
async getRateLimitTtl() {
|
|
const client = await this.client;
|
|
return client.pttl(this.keys.limiter);
|
|
}
|
|
/**
|
|
* Job counts by type
|
|
*
|
|
* Queue#getJobCountByTypes('completed') => completed count
|
|
* Queue#getJobCountByTypes('completed,failed') => completed + failed count
|
|
* Queue#getJobCountByTypes('completed', 'failed') => completed + failed count
|
|
* Queue#getJobCountByTypes('completed', 'waiting', 'failed') => completed + waiting + failed count
|
|
*/
|
|
async getJobCountByTypes(...types) {
|
|
const result = await this.getJobCounts(...types);
|
|
return Object.values(result).reduce((sum, count) => sum + count, 0);
|
|
}
|
|
/**
|
|
* Returns the job counts for each type specified or every list/set in the queue by default.
|
|
*
|
|
* @returns An object, key (type) and value (count)
|
|
*/
|
|
async getJobCounts(...types) {
|
|
const currentTypes = this.sanitizeJobTypes(types);
|
|
const responses = await this.scripts.getCounts(currentTypes);
|
|
const counts = {};
|
|
responses.forEach((res, index) => {
|
|
counts[currentTypes[index]] = res || 0;
|
|
});
|
|
return counts;
|
|
}
|
|
/**
|
|
* Get current job state.
|
|
*
|
|
* @returns Returns one of these values:
|
|
* 'completed', 'failed', 'delayed', 'active', 'waiting', 'waiting-children', 'unknown'.
|
|
*/
|
|
getJobState(jobId) {
|
|
return this.scripts.getState(jobId);
|
|
}
|
|
/**
|
|
* Returns the number of jobs in completed status.
|
|
*/
|
|
getCompletedCount() {
|
|
return this.getJobCountByTypes('completed');
|
|
}
|
|
/**
|
|
* Returns the number of jobs in failed status.
|
|
*/
|
|
getFailedCount() {
|
|
return this.getJobCountByTypes('failed');
|
|
}
|
|
/**
|
|
* Returns the number of jobs in delayed status.
|
|
*/
|
|
getDelayedCount() {
|
|
return this.getJobCountByTypes('delayed');
|
|
}
|
|
/**
|
|
* Returns the number of jobs in active status.
|
|
*/
|
|
getActiveCount() {
|
|
return this.getJobCountByTypes('active');
|
|
}
|
|
/**
|
|
* Returns the number of jobs in prioritized status.
|
|
*/
|
|
getPrioritizedCount() {
|
|
return this.getJobCountByTypes('prioritized');
|
|
}
|
|
/**
|
|
* Returns the number of jobs in waiting or paused statuses.
|
|
*/
|
|
getWaitingCount() {
|
|
return this.getJobCountByTypes('waiting');
|
|
}
|
|
/**
|
|
* Returns the number of jobs in waiting-children status.
|
|
*/
|
|
getWaitingChildrenCount() {
|
|
return this.getJobCountByTypes('waiting-children');
|
|
}
|
|
/**
|
|
* Returns the jobs that are in the "waiting" status.
|
|
* @param start - zero based index from where to start returning jobs.
|
|
* @param end - zero based index where to stop returning jobs.
|
|
*/
|
|
getWaiting(start = 0, end = -1) {
|
|
return this.getJobs(['waiting'], start, end, true);
|
|
}
|
|
/**
|
|
* Returns the jobs that are in the "waiting-children" status.
|
|
* I.E. parent jobs that have at least one child that has not completed yet.
|
|
* @param start - zero based index from where to start returning jobs.
|
|
* @param end - zero based index where to stop returning jobs.
|
|
*/
|
|
getWaitingChildren(start = 0, end = -1) {
|
|
return this.getJobs(['waiting-children'], start, end, true);
|
|
}
|
|
/**
|
|
* Returns the jobs that are in the "active" status.
|
|
* @param start - zero based index from where to start returning jobs.
|
|
* @param end - zero based index where to stop returning jobs.
|
|
*/
|
|
getActive(start = 0, end = -1) {
|
|
return this.getJobs(['active'], start, end, true);
|
|
}
|
|
/**
|
|
* Returns the jobs that are in the "delayed" status.
|
|
* @param start - zero based index from where to start returning jobs.
|
|
* @param end - zero based index where to stop returning jobs.
|
|
*/
|
|
getDelayed(start = 0, end = -1) {
|
|
return this.getJobs(['delayed'], start, end, true);
|
|
}
|
|
/**
|
|
* Returns the jobs that are in the "prioritized" status.
|
|
* @param start - zero based index from where to start returning jobs.
|
|
* @param end - zero based index where to stop returning jobs.
|
|
*/
|
|
getPrioritized(start = 0, end = -1) {
|
|
return this.getJobs(['prioritized'], start, end, true);
|
|
}
|
|
/**
|
|
* Returns the jobs that are in the "completed" status.
|
|
* @param start - zero based index from where to start returning jobs.
|
|
* @param end - zero based index where to stop returning jobs.
|
|
*/
|
|
getCompleted(start = 0, end = -1) {
|
|
return this.getJobs(['completed'], start, end, false);
|
|
}
|
|
/**
|
|
* Returns the jobs that are in the "failed" status.
|
|
* @param start - zero based index from where to start returning jobs.
|
|
* @param end - zero based index where to stop returning jobs.
|
|
*/
|
|
getFailed(start = 0, end = -1) {
|
|
return this.getJobs(['failed'], start, end, false);
|
|
}
|
|
/**
|
|
* Returns the qualified job ids and the raw job data (if available) of the
|
|
* children jobs of the given parent job.
|
|
* It is possible to get either the already processed children, in this case
|
|
* an array of qualified job ids and their result values will be returned,
|
|
* or the pending children, in this case an array of qualified job ids will
|
|
* be returned.
|
|
* A qualified job id is a string representing the job id in a given queue,
|
|
* for example: "bull:myqueue:jobid".
|
|
*
|
|
* @param parentId The id of the parent job
|
|
* @param type "processed" | "pending"
|
|
* @param opts
|
|
*
|
|
* @returns { items: { id: string, v?: any, err?: string } [], jobs: JobJsonRaw[], total: number}
|
|
*/
|
|
async getDependencies(parentId, type, start, end) {
|
|
const key = this.toKey(type == 'processed'
|
|
? `${parentId}:processed`
|
|
: `${parentId}:dependencies`);
|
|
const { items, total, jobs } = await this.scripts.paginate(key, {
|
|
start,
|
|
end,
|
|
fetchJobs: true,
|
|
});
|
|
return {
|
|
items,
|
|
jobs,
|
|
total,
|
|
};
|
|
}
|
|
async getRanges(types, start = 0, end = 1, asc = false) {
|
|
const multiCommands = [];
|
|
this.commandByType(types, false, (key, command) => {
|
|
switch (command) {
|
|
case 'lrange':
|
|
multiCommands.push('lrange');
|
|
break;
|
|
case 'zrange':
|
|
multiCommands.push('zrange');
|
|
break;
|
|
}
|
|
});
|
|
const responses = await this.scripts.getRanges(types, start, end, asc);
|
|
let results = [];
|
|
responses.forEach((response, index) => {
|
|
const result = response || [];
|
|
if (asc && multiCommands[index] === 'lrange') {
|
|
results = results.concat(result.reverse());
|
|
}
|
|
else {
|
|
results = results.concat(result);
|
|
}
|
|
});
|
|
return [...new Set(results)];
|
|
}
|
|
/**
|
|
* Returns the jobs that are on the given statuses (note that JobType is synonym for job status)
|
|
* @param types - the statuses of the jobs to return.
|
|
* @param start - zero based index from where to start returning jobs.
|
|
* @param end - zero based index where to stop returning jobs.
|
|
* @param asc - if true, the jobs will be returned in ascending order.
|
|
*/
|
|
async getJobs(types, start = 0, end = -1, asc = false) {
|
|
const currentTypes = this.sanitizeJobTypes(types);
|
|
const jobIds = await this.getRanges(currentTypes, start, end, asc);
|
|
return Promise.all(jobIds.map(jobId => this.Job.fromId(this, jobId)));
|
|
}
|
|
/**
|
|
* Returns the logs for a given Job.
|
|
* @param jobId - the id of the job to get the logs for.
|
|
* @param start - zero based index from where to start returning jobs.
|
|
* @param end - zero based index where to stop returning jobs.
|
|
* @param asc - if true, the jobs will be returned in ascending order.
|
|
*/
|
|
async getJobLogs(jobId, start = 0, end = -1, asc = true) {
|
|
const client = await this.client;
|
|
const multi = client.multi();
|
|
const logsKey = this.toKey(jobId + ':logs');
|
|
if (asc) {
|
|
multi.lrange(logsKey, start, end);
|
|
}
|
|
else {
|
|
multi.lrange(logsKey, -(end + 1), -(start + 1));
|
|
}
|
|
multi.llen(logsKey);
|
|
const result = (await multi.exec());
|
|
if (!asc) {
|
|
result[0][1].reverse();
|
|
}
|
|
return {
|
|
logs: result[0][1],
|
|
count: result[1][1],
|
|
};
|
|
}
|
|
async baseGetClients(suffix) {
|
|
const client = await this.client;
|
|
const clients = (await client.client('LIST'));
|
|
try {
|
|
const list = this.parseClientList(clients, suffix);
|
|
return list;
|
|
}
|
|
catch (err) {
|
|
if (!utils_1.clientCommandMessageReg.test(err.message)) {
|
|
throw err;
|
|
}
|
|
return [];
|
|
}
|
|
}
|
|
/**
|
|
* Get the worker list related to the queue. i.e. all the known
|
|
* workers that are available to process jobs for this queue.
|
|
* Note: GCP does not support SETNAME, so this call will not work
|
|
*
|
|
* @returns - Returns an array with workers info.
|
|
*/
|
|
getWorkers() {
|
|
return this.baseGetClients(utils_1.WORKER_SUFFIX);
|
|
}
|
|
/**
|
|
* Get queue events list related to the queue.
|
|
* Note: GCP does not support SETNAME, so this call will not work
|
|
*
|
|
* @returns - Returns an array with queue events info.
|
|
*/
|
|
async getQueueEvents() {
|
|
return this.baseGetClients(utils_1.QUEUE_EVENT_SUFFIX);
|
|
}
|
|
/**
|
|
* Get queue metrics related to the queue.
|
|
*
|
|
* This method returns the gathered metrics for the queue.
|
|
* The metrics are represented as an array of job counts
|
|
* per unit of time (1 minute).
|
|
*
|
|
* @param start - Start point of the metrics, where 0
|
|
* is the newest point to be returned.
|
|
* @param end - End point of the metrics, where -1 is the
|
|
* oldest point to be returned.
|
|
*
|
|
* @returns - Returns an object with queue metrics.
|
|
*/
|
|
async getMetrics(type, start = 0, end = -1) {
|
|
const client = await this.client;
|
|
const metricsKey = this.toKey(`metrics:${type}`);
|
|
const dataKey = `${metricsKey}:data`;
|
|
const multi = client.multi();
|
|
multi.hmget(metricsKey, 'count', 'prevTS', 'prevCount');
|
|
multi.lrange(dataKey, start, end);
|
|
multi.llen(dataKey);
|
|
const [hmget, range, len] = (await multi.exec());
|
|
const [err, [count, prevTS, prevCount]] = hmget;
|
|
const [err2, data] = range;
|
|
const [err3, numPoints] = len;
|
|
if (err || err2) {
|
|
throw err || err2 || err3;
|
|
}
|
|
return {
|
|
meta: {
|
|
count: parseInt(count || '0', 10),
|
|
prevTS: parseInt(prevTS || '0', 10),
|
|
prevCount: parseInt(prevCount || '0', 10),
|
|
},
|
|
data,
|
|
count: numPoints,
|
|
};
|
|
}
|
|
parseClientList(list, suffix = '') {
|
|
const lines = list.split('\n');
|
|
const clients = [];
|
|
lines.forEach((line) => {
|
|
const client = {};
|
|
const keyValues = line.split(' ');
|
|
keyValues.forEach(function (keyValue) {
|
|
const index = keyValue.indexOf('=');
|
|
const key = keyValue.substring(0, index);
|
|
const value = keyValue.substring(index + 1);
|
|
client[key] = value;
|
|
});
|
|
const name = client['name'];
|
|
if (name && name === `${this.clientName()}${suffix ? `${suffix}` : ''}`) {
|
|
client['name'] = this.name;
|
|
clients.push(client);
|
|
}
|
|
});
|
|
return clients;
|
|
}
|
|
}
|
|
exports.QueueGetters = QueueGetters;
|
|
//# sourceMappingURL=queue-getters.js.map
|