Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add top-level agenda.disable and agenda.enable methods #1536

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion src/JobDbRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,20 @@
* Internal method to unlock jobs so that they can be re-run
*/
async unlockJobs(jobIds: ObjectId[]): Promise<void> {
await this.collection.updateMany(
await this.updateMany(
{ _id: { $in: jobIds }, nextRunAt: { $ne: null } },
{ $unset: { lockedAt: true } }
);
}

/**
* Internal method to toggle the `disabled` flag on jobs in the DB
*/
async setJobsDisabled(query: Filter<IJobParameters>, disabled: boolean): Promise<number> {
const result = await this.updateMany(query, { $set: { disabled }});

Check failure on line 101 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Insert `·`

Check failure on line 101 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Insert `·`

Check failure on line 101 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Insert `·`

Check failure on line 101 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Insert `·`

Check failure on line 101 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Insert `·`

Check failure on line 101 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Insert `·`

Check failure on line 101 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Insert `·`

Check failure on line 101 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Insert `·`
return result || 0;
}

async lockJob(job: JobWithId): Promise<IJobParameters | undefined> {
// Query to run against collection to see if we need to lock it
const criteria: Filter<Omit<IJobParameters, 'lockedAt'> & { lockedAt?: Date | null }> = {
Expand Down Expand Up @@ -136,7 +144,7 @@
disabled: { $ne: true },
$or: [
{
lockedAt: { $eq: null as any },

Check warning on line 147 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Unexpected any. Specify a different type

Check warning on line 147 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Unexpected any. Specify a different type

Check warning on line 147 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Unexpected any. Specify a different type

Check warning on line 147 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Unexpected any. Specify a different type

Check warning on line 147 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Unexpected any. Specify a different type

Check warning on line 147 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Unexpected any. Specify a different type

Check warning on line 147 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Unexpected any. Specify a different type

Check warning on line 147 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Unexpected any. Specify a different type
nextRunAt: { $lte: nextScanAt }
},
{
Expand Down Expand Up @@ -234,8 +242,8 @@
// We have a result from the above calls
if (res) {
// Grab ID and nextRunAt from MongoDB and store it as an attribute on Job
job.attrs._id = res._id;

Check warning on line 245 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Assignment to property of function parameter 'job'

Check warning on line 245 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Assignment to property of function parameter 'job'

Check warning on line 245 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Assignment to property of function parameter 'job'

Check warning on line 245 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Assignment to property of function parameter 'job'

Check warning on line 245 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Assignment to property of function parameter 'job'

Check warning on line 245 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Assignment to property of function parameter 'job'

Check warning on line 245 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Assignment to property of function parameter 'job'

Check warning on line 245 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Assignment to property of function parameter 'job'
job.attrs.nextRunAt = res.nextRunAt;

Check warning on line 246 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Assignment to property of function parameter 'job'

Check warning on line 246 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Assignment to property of function parameter 'job'

Check warning on line 246 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Assignment to property of function parameter 'job'

Check warning on line 246 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Assignment to property of function parameter 'job'

Check warning on line 246 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Assignment to property of function parameter 'job'

Check warning on line 246 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Assignment to property of function parameter 'job'

Check warning on line 246 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Assignment to property of function parameter 'job'

Check warning on line 246 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Assignment to property of function parameter 'job'

// check if we should process the job immediately
this.agenda.emit('processJob', job);
Expand Down Expand Up @@ -397,4 +405,25 @@
throw error;
}
}

/**
* Internal method used to update multiple jobs with one call
* @name JobDbRepository#updateMany
* @function
* @returns {Promise} the number of jobs updated in the DB
*/
private async updateMany(
query: Filter<IJobParameters>,
update: UpdateFilter<IJobParameters>
): Promise<number> {
const { modifiedCount, matchedCount } = await this.collection.updateMany(

Check failure on line 419 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Replace `⏎↹↹↹query,⏎↹↹↹update⏎↹↹` with `query,·update`

Check failure on line 419 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Replace `⏎↹↹↹query,⏎↹↹↹update⏎↹↹` with `query,·update`

Check failure on line 419 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Replace `⏎↹↹↹query,⏎↹↹↹update⏎↹↹` with `query,·update`

Check failure on line 419 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Replace `⏎↹↹↹query,⏎↹↹↹update⏎↹↹` with `query,·update`

Check failure on line 419 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Replace `⏎↹↹↹query,⏎↹↹↹update⏎↹↹` with `query,·update`

Check failure on line 419 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Replace `⏎↹↹↹query,⏎↹↹↹update⏎↹↹` with `query,·update`

Check failure on line 419 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Replace `⏎↹↹↹query,⏎↹↹↹update⏎↹↹` with `query,·update`

Check failure on line 419 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Replace `⏎↹↹↹query,⏎↹↹↹update⏎↹↹` with `query,·update`
query,
update
);
if(matchedCount !== modifiedCount) {

Check failure on line 423 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Insert `·`

Check failure on line 423 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Insert `·`

Check failure on line 423 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Insert `·`

Check failure on line 423 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Insert `·`

Check failure on line 423 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Insert `·`

Check failure on line 423 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Insert `·`

Check failure on line 423 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Insert `·`

Check failure on line 423 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Insert `·`
log(`WARN: ${matchedCount} jobs matched query but ${modifiedCount} were modified`);

Check failure on line 424 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Replace `··` with `↹`

Check failure on line 424 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Replace `··` with `↹`

Check failure on line 424 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Replace `··` with `↹`

Check failure on line 424 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Replace `··` with `↹`

Check failure on line 424 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Replace `··` with `↹`

Check failure on line 424 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Replace `··` with `↹`

Check failure on line 424 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Replace `··` with `↹`

Check failure on line 424 in src/JobDbRepository.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Replace `··` with `↹`
}

return modifiedCount;
}
}
48 changes: 47 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EventEmitter } from 'events';
import * as debug from 'debug';

import type { Db, Filter, MongoClientOptions, Sort } from 'mongodb';
import type { Db, Filter, MongoClientOptions, Sort, UpdateResult } from 'mongodb';

Check failure on line 4 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

'UpdateResult' is defined but never used

Check failure on line 4 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

'UpdateResult' is defined but never used

Check failure on line 4 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

'UpdateResult' is defined but never used

Check failure on line 4 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

'UpdateResult' is defined but never used

Check failure on line 4 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

'UpdateResult' is defined but never used

Check failure on line 4 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

'UpdateResult' is defined but never used

Check failure on line 4 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

'UpdateResult' is defined but never used

Check failure on line 4 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

'UpdateResult' is defined but never used
import { SortDirection } from 'mongodb';
import { ForkOptions } from 'child_process';
import type { IJobDefinition } from './types/JobDefinition';
Expand Down Expand Up @@ -200,6 +200,52 @@
}
}

/**

Check failure on line 203 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Replace `··` with `↹`

Check failure on line 203 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Replace `··` with `↹`

Check failure on line 203 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Replace `··` with `↹`

Check failure on line 203 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Replace `··` with `↹`

Check failure on line 203 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Replace `··` with `↹`

Check failure on line 203 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Replace `··` with `↹`

Check failure on line 203 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Replace `··` with `↹`

Check failure on line 203 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Replace `··` with `↹`
* Disables any jobs matching the passed MongoDB query by setting the `disabled` flag to `true`

Check failure on line 204 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Insert `↹`

Check failure on line 204 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Insert `↹`

Check failure on line 204 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Insert `↹`

Check failure on line 204 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Insert `↹`

Check failure on line 204 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Insert `↹`

Check failure on line 204 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Insert `↹`

Check failure on line 204 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Insert `↹`

Check failure on line 204 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Insert `↹`
* @name Agenda#disable

Check failure on line 205 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Insert `↹`

Check failure on line 205 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Insert `↹`

Check failure on line 205 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Insert `↹`

Check failure on line 205 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Insert `↹`

Check failure on line 205 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Insert `↹`

Check failure on line 205 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Insert `↹`

Check failure on line 205 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Insert `↹`

Check failure on line 205 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Insert `↹`
* @function

Check failure on line 206 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Insert `↹`

Check failure on line 206 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Insert `↹`

Check failure on line 206 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Insert `↹`

Check failure on line 206 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Insert `↹`

Check failure on line 206 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Insert `↹`

Check failure on line 206 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Insert `↹`

Check failure on line 206 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Insert `↹`

Check failure on line 206 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Insert `↹`
* @param query MongoDB query to use when enabling

Check failure on line 207 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 6)

Insert `↹`

Check failure on line 207 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 4.4)

Insert `↹`

Check failure on line 207 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 3.6)

Insert `↹`

Check failure on line 207 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (14, 4.4)

Insert `↹`

Check failure on line 207 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 3.6)

Insert `↹`

Check failure on line 207 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 6)

Insert `↹`

Check failure on line 207 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (18, 5)

Insert `↹`

Check failure on line 207 in src/index.ts

View workflow job for this annotation

GitHub Actions / build (16, 5)

Insert `↹`
* @returns {Promise<number>} Resolved with the number of disabled job instances.
*/
async disable (
this: Agenda,
query: Filter<IJobParameters>
): Promise<number> {
log('attempting to disable all jobs matching query: %o', query);
try {
const modifiedCount = await this.db.setJobsDisabled(query, true);
log(`${modifiedCount} jobs disabled`);
return modifiedCount;
} catch (error) {
log('error trying to mark jobs as `disabled`');
throw error;
}
};

/**
* Enables any jobs matching the passed MongoDB query by setting the `disabled` flag to `false`
* @name Agenda#enable
* @function
* @param query MongoDB query to use when enabling
* @caller client code, Agenda.purge(), Job.remove()
* @returns {Promise<Number>} A promise that contains the number of removed documents when fulfilled.
*/
async enable (
this: Agenda,
query: Filter<IJobParameters> = {}
): Promise<number> {
log('attempting to enable all jobs matching query %o', query);
try {
const modifiedCount = await this.db.setJobsDisabled(query, false);
log(`${modifiedCount} jobs enabled`);
return modifiedCount;
} catch (error) {
log('error trying to mark jobs as `enabled`');
throw error;
}
};


/**
* Set name of queue
* @param name
Expand Down
99 changes: 99 additions & 0 deletions test/agenda.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,105 @@ describe('Agenda', () => {
});
});

describe('disable', () => {
beforeEach(async() => {
await Promise.all([
globalAgenda.create('sendEmail', {to: 'some guy'}).schedule('1 minute').save(),
globalAgenda.create('sendEmail', {from: 'some guy'}).schedule('1 minute').save(),
globalAgenda.create('some job').schedule('30 seconds').save()
]);
});

it('disables all jobs', async() => {
const ct = await globalAgenda.disable({});

expect(ct).to.be(3);
const disabledJobs = await globalAgenda.jobs({});

expect(disabledJobs).to.have.length(3);
disabledJobs.map(x => expect(x.attrs.disabled).to.be(true));
});

it('disables jobs when queried by name', async() => {
const ct = await globalAgenda.disable({name: 'sendEmail'});

expect(ct).to.be(2);
const disabledJobs = await globalAgenda.jobs({name: 'sendEmail'});

expect(disabledJobs).to.have.length(2);
disabledJobs.map(x => expect(x.attrs.disabled).to.be(true));
});

it('disables jobs when queried by data', async() => {
const ct = await globalAgenda.disable({'data.from': 'some guy'});

expect(ct).to.be(1);
const disabledJobs = await globalAgenda.jobs({'data.from': 'some guy', disabled: true});

expect(disabledJobs).to.have.length(1);
});

it('does not modify `nextRunAt`', async() => {
const js = await globalAgenda.jobs({name: 'some job'});
const ct = await globalAgenda.disable({name: 'some job'});

expect(ct).to.be(1);
const disabledJobs = await globalAgenda.jobs({name: 'some job', disabled: true});

expect(disabledJobs[0].attrs.nextRunAt.toString()).to.be(js[0].attrs.nextRunAt.toString());
});
});

describe('enable', () => {
beforeEach(async() => {
await Promise.all([
globalAgenda.create('sendEmail', {to: 'some guy'}).schedule('1 minute').save(),
globalAgenda.create('sendEmail', {from: 'some guy'}).schedule('1 minute').save(),
globalAgenda.create('some job').schedule('30 seconds').save()
]);
});

it('enables all jobs', async() => {
const ct = await globalAgenda.enable({});

expect(ct).to.be(3);
const enabledJobs = await globalAgenda.jobs({});

expect(enabledJobs).to.have.length(3);
enabledJobs.map(x => expect(x.attrs.disabled).to.be(false));
});

it('enables jobs when queried by name', async() => {
const ct = await globalAgenda.enable({name: 'sendEmail'});

expect(ct).to.be(2);
const enabledJobs = await globalAgenda.jobs({name: 'sendEmail'});

expect(enabledJobs).to.have.length(2);
enabledJobs.map(x => expect(x.attrs.disabled).to.be(false));
});

it('enables jobs when queried by data', async() => {
const ct = await globalAgenda.enable({'data.from': 'some guy'});

expect(ct).to.be(1);
const enabledJobs = await globalAgenda.jobs({'data.from': 'some guy', disabled: false});

expect(enabledJobs).to.have.length(1);
});

it('does not modify `nextRunAt`', async() => {
const js = await globalAgenda.jobs({name: 'some job'});
const ct = await globalAgenda.enable({name: 'some job'});

expect(ct).to.be(1);
const enabledJobs = await globalAgenda.jobs({name: 'some job', disabled: false});

expect(enabledJobs[0].attrs.nextRunAt.toString()).to.be(js[0].attrs.nextRunAt.toString());
});
});


describe('search', () => {
beforeEach(async () => {
await globalAgenda.create('jobA', 1).save();
Expand Down
Loading