UNPKG

@sealos/agendash

Version:

A fork of dashboard for Agenda.js with Pagination and Search capabilities

293 lines 11.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AgendashController = void 0; const mongodb_1 = require("mongodb"); class AgendashController { constructor(agenda) { this.agenda = agenda; this.getJobs = (job, state, options) => { const preMatch = {}; if (job) { preMatch.name = job; } if (options.query && options.property) { if (options.isObjectId) { preMatch[options.property] = new mongodb_1.ObjectId(options.query); } else if (/^\d+$/.test(options.query)) { preMatch[options.property] = Number.parseInt(options.query, 10); } else { preMatch[options.property] = { $regex: options.query, $options: 'i' }; } } const postMatch = {}; if (state) { postMatch[state] = true; } const collection = this.agenda._collection; return collection .aggregate([ { $match: preMatch }, { $sort: { repeatInterval: -1, nextRunAt: -1, lastRunAt: -1, lastFinishedAt: -1, }, }, { $project: { job: '$$ROOT', _id: '$$ROOT._id', running: { $and: ['$lastRunAt', { $gt: ['$lastRunAt', '$lastFinishedAt'] }], }, scheduled: { $and: ['$nextRunAt', { $gte: ['$nextRunAt', new Date()] }], }, queued: { $and: [ '$nextRunAt', { $gte: [new Date(), '$nextRunAt'] }, { $gte: ['$nextRunAt', '$lastFinishedAt'] }, ], }, completed: { $and: [ '$lastFinishedAt', { $gt: ['$lastFinishedAt', '$failedAt'] }, ], }, failed: { $and: [ '$lastFinishedAt', '$failedAt', { $eq: ['$lastFinishedAt', '$failedAt'] }, ], }, repeating: { $and: ['$repeatInterval', { $ne: ['$repeatInterval', null] }], }, }, }, { $match: postMatch }, { $facet: { pages: [ { $count: 'totalMatchs' }, { $project: { totalPages: { $ceil: { $divide: ['$totalMatchs', options.limit] }, }, }, }, ], filtered: [{ $skip: options.skip }, { $limit: options.limit }], }, }, ]) .toArray(); }; this.getOverview = async () => { const collection = this.agenda._collection; const results = await collection .aggregate([ { $group: { _id: '$name', displayName: { $first: '$name' }, meta: { $addToSet: { type: '$type', priority: '$priority', repeatInterval: '$repeatInterval', repeatTimezone: '$repeatTimezone', }, }, total: { $sum: 1 }, running: { $sum: { $cond: [ { $and: [ '$lastRunAt', { $gt: ['$lastRunAt', '$lastFinishedAt'] }, ], }, 1, 0, ], }, }, scheduled: { $sum: { $cond: [ { $and: ['$nextRunAt', { $gte: ['$nextRunAt', new Date()] }], }, 1, 0, ], }, }, queued: { $sum: { $cond: [ { $and: [ '$nextRunAt', { $gte: [new Date(), '$nextRunAt'] }, { $gte: ['$nextRunAt', '$lastFinishedAt'] }, ], }, 1, 0, ], }, }, completed: { $sum: { $cond: [ { $and: [ '$lastFinishedAt', { $gt: ['$lastFinishedAt', '$failedAt'] }, ], }, 1, 0, ], }, }, failed: { $sum: { $cond: [ { $and: [ '$lastFinishedAt', '$failedAt', { $eq: ['$lastFinishedAt', '$failedAt'] }, ], }, 1, 0, ], }, }, repeating: { $sum: { $cond: [ { $and: [ '$repeatInterval', { $ne: ['$repeatInterval', null] }, ], }, 1, 0, ], }, }, }, }, ]) .toArray(); const states = { total: 0, running: 0, scheduled: 0, queued: 0, completed: 0, failed: 0, repeating: 0, }; const totals = { displayName: 'All Jobs', ...states }; for (const job of results) { for (const state of Object.keys(states)) { totals[state] += job[state]; } } results.unshift(totals); return results; }; this.api = async (job, state, { query: q, property, isObjectId, skip, limit }) => { limit = Number.parseInt(limit, 10) || 200; skip = Number.parseInt(skip, 10) || 0; const [overview, jobs] = await Promise.all([ this.getOverview(), this.getJobs(job, state, { query: q, property, isObjectId, skip, limit }), ]); return { overview, jobs: jobs[0].filtered, totalPages: jobs[0].pages[0] ? jobs[0].pages[0].totalPages : 0, title: 'Agendash', currentRequest: { title: 'Agendash', job: job || 'All Jobs', state, }, }; }; this.requeueJobs = async (jobIds) => { const collection = this.agenda._collection; const jobs = await collection .find({ _id: { $in: jobIds.map((jobId) => new mongodb_1.ObjectId(jobId)) }, }) .toArray(); if (jobs.length === 0) { throw new Error('Job not found'); } for (const job of jobs) { const newJob = this.agenda.create(job.name, job.data); // eslint-disable-next-line no-await-in-loop await newJob.save(); } return 'Jobs create successfully'; }; this.deleteJobs = (jobIds) => { return this.agenda.cancel({ _id: { $in: jobIds.map((jobId) => new mongodb_1.ObjectId(jobId)) }, }); }; this.createJob = (jobName, jobSchedule, jobRepeatEvery, jobData) => { // @TODO: Need to validate user input. const job = this.agenda.create(jobName, jobData); if (jobSchedule && jobRepeatEvery) { job.repeatAt(jobSchedule); job.repeatEvery(jobRepeatEvery); } else if (jobSchedule) { job.schedule(jobSchedule); } else if (jobRepeatEvery) { job.repeatEvery(jobRepeatEvery); } else { return Promise.reject(new Error('Jobs not created')); } return job.save(); }; agenda.on('ready', () => { const collection = agenda._collection; collection.createIndexes([ { key: { nextRunAt: -1, lastRunAt: -1, lastFinishedAt: -1 } }, { key: { name: 1, nextRunAt: -1, lastRunAt: -1, lastFinishedAt: -1 } }, ], // @ts-expect-error (error) => { if (error) { // Ignoring for now } }).then(() => { // Ignoring for now }); }); } } exports.AgendashController = AgendashController; //# sourceMappingURL=agendash.js.map