agenda 4.4.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -8
- package/dist/agenda/create.d.ts +2 -2
- package/dist/agenda/create.d.ts.map +1 -1
- package/dist/agenda/create.js.map +1 -1
- package/dist/agenda/define.d.ts +2 -2
- package/dist/agenda/define.d.ts.map +1 -1
- package/dist/agenda/define.js.map +1 -1
- package/dist/agenda/every.d.ts +2 -1
- package/dist/agenda/every.d.ts.map +1 -1
- package/dist/agenda/every.js +1 -1
- package/dist/agenda/every.js.map +1 -1
- package/dist/agenda/find-and-lock-next-job.d.ts.map +1 -1
- package/dist/agenda/find-and-lock-next-job.js +3 -4
- package/dist/agenda/find-and-lock-next-job.js.map +1 -1
- package/dist/agenda/now.d.ts +2 -2
- package/dist/agenda/now.d.ts.map +1 -1
- package/dist/agenda/now.js.map +1 -1
- package/dist/agenda/schedule.d.ts +3 -3
- package/dist/agenda/schedule.d.ts.map +1 -1
- package/dist/agenda/schedule.js.map +1 -1
- package/dist/job/compute-next-run-at.js +2 -2
- package/dist/job/compute-next-run-at.js.map +1 -1
- package/dist/job/index.d.ts +6 -3
- package/dist/job/index.d.ts.map +1 -1
- package/dist/job/index.js.map +1 -1
- package/lib/agenda/cancel.ts +28 -0
- package/lib/agenda/close.ts +37 -0
- package/lib/agenda/create.ts +22 -0
- package/lib/agenda/database.ts +63 -0
- package/lib/agenda/db-init.ts +45 -0
- package/lib/agenda/default-concurrency.ts +19 -0
- package/lib/agenda/default-lock-lifetime.ts +17 -0
- package/lib/agenda/default-lock-limit.ts +17 -0
- package/lib/agenda/define.ts +85 -0
- package/lib/agenda/disable.ts +28 -0
- package/lib/agenda/drain.ts +30 -0
- package/lib/agenda/enable.ts +29 -0
- package/lib/agenda/every.ts +86 -0
- package/lib/agenda/find-and-lock-next-job.ts +78 -0
- package/lib/agenda/has-mongo-protocol.ts +8 -0
- package/lib/agenda/index.ts +227 -0
- package/lib/agenda/job-processing-queue.ts +99 -0
- package/lib/agenda/jobs.ts +31 -0
- package/lib/agenda/lock-limit.ts +17 -0
- package/lib/agenda/max-concurrency.ts +20 -0
- package/lib/agenda/mongo.ts +21 -0
- package/lib/agenda/name.ts +16 -0
- package/lib/agenda/now.ts +31 -0
- package/lib/agenda/process-every.ts +18 -0
- package/lib/agenda/purge.ts +19 -0
- package/lib/agenda/save-job.ts +185 -0
- package/lib/agenda/schedule.ts +79 -0
- package/lib/agenda/sort.ts +17 -0
- package/lib/agenda/start.ts +30 -0
- package/lib/agenda/stop.ts +49 -0
- package/lib/cjs.ts +5 -0
- package/lib/index.ts +11 -0
- package/lib/job/compute-next-run-at.ts +191 -0
- package/lib/job/disable.ts +11 -0
- package/lib/job/enable.ts +11 -0
- package/lib/job/fail.ts +29 -0
- package/lib/job/index.ts +221 -0
- package/lib/job/is-running.ts +29 -0
- package/lib/job/priority.ts +11 -0
- package/lib/job/remove.ts +10 -0
- package/lib/job/repeat-at.ts +12 -0
- package/lib/job/repeat-every.ts +40 -0
- package/lib/job/run.ts +125 -0
- package/lib/job/save.ts +11 -0
- package/lib/job/schedule.ts +15 -0
- package/lib/job/set-shouldsaveresult.ts +10 -0
- package/lib/job/to-json.ts +36 -0
- package/lib/job/touch.ts +11 -0
- package/lib/job/unique.ts +18 -0
- package/lib/utils/create-job.ts +13 -0
- package/lib/utils/index.ts +3 -0
- package/lib/utils/parse-priority.ts +37 -0
- package/lib/utils/process-jobs.ts +379 -0
- package/package.json +13 -11
- package/tsconfig.json +72 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Filter } from "mongodb";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
import { Job } from "../job";
|
|
4
|
+
import { createJob } from "../utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Finds all jobs matching 'query'
|
|
8
|
+
* @name Agenda#jobs
|
|
9
|
+
* @function
|
|
10
|
+
* @param [query] object for MongoDB
|
|
11
|
+
* @param [sort] object for MongoDB
|
|
12
|
+
* @param [limit] number of documents to return from MongoDB
|
|
13
|
+
* @param [number] of documents to skip in MongoDB
|
|
14
|
+
* @returns resolves when fails or passes
|
|
15
|
+
*/
|
|
16
|
+
export const jobs = async function (
|
|
17
|
+
this: Agenda,
|
|
18
|
+
query: Filter<any> = {},
|
|
19
|
+
sort = {},
|
|
20
|
+
limit = 0,
|
|
21
|
+
skip = 0
|
|
22
|
+
): Promise<Job[]> {
|
|
23
|
+
const result = await this._collection
|
|
24
|
+
.find(query) // eslint-disable-line
|
|
25
|
+
.sort(sort)
|
|
26
|
+
.limit(limit)
|
|
27
|
+
.skip(skip)
|
|
28
|
+
.toArray();
|
|
29
|
+
|
|
30
|
+
return result.map((job: any) => createJob(this, job));
|
|
31
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
|
|
4
|
+
const debug = createDebugger("agenda:locklimit");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Set the default amount jobs that are allowed to be locked at one time (GLOBAL)
|
|
8
|
+
* @name Agenda#locklimit
|
|
9
|
+
* @function
|
|
10
|
+
* @param limit num Lock limit
|
|
11
|
+
*/
|
|
12
|
+
export const lockLimit = function (this: Agenda, limit: number): Agenda {
|
|
13
|
+
// @NOTE: Is this different than max concurrency?
|
|
14
|
+
debug("Agenda.lockLimit(%d)", limit);
|
|
15
|
+
this._lockLimit = limit;
|
|
16
|
+
return this;
|
|
17
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
|
|
4
|
+
const debug = createDebugger("agenda:maxConcurrency");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Set the concurrency for jobs (globally), type does not matter
|
|
8
|
+
* @name Agenda#maxConcurrency
|
|
9
|
+
* @function
|
|
10
|
+
* @param concurrency max concurrency value
|
|
11
|
+
* @returns agenda instance
|
|
12
|
+
*/
|
|
13
|
+
export const maxConcurrency = function (
|
|
14
|
+
this: Agenda,
|
|
15
|
+
concurrency: number
|
|
16
|
+
): Agenda {
|
|
17
|
+
debug("Agenda.maxConcurrency(%d)", concurrency);
|
|
18
|
+
this._maxConcurrency = concurrency;
|
|
19
|
+
return this;
|
|
20
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AnyError, Collection, Db } from "mongodb";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Build method used to add MongoDB connection details
|
|
6
|
+
* @name Agenda#mongo
|
|
7
|
+
* @function
|
|
8
|
+
* @param mdb instance of MongoClient to use
|
|
9
|
+
* @param [collection] name collection we want to use ('agendaJobs')
|
|
10
|
+
* @param [cb] called when MongoDB connection fails or passes
|
|
11
|
+
*/
|
|
12
|
+
export const mongo = function (
|
|
13
|
+
this: Agenda,
|
|
14
|
+
mdb: Db,
|
|
15
|
+
collection?: string,
|
|
16
|
+
cb?: (error: AnyError | undefined, collection: Collection<any> | null) => void
|
|
17
|
+
): Agenda {
|
|
18
|
+
this._mdb = mdb;
|
|
19
|
+
this.db_init(collection, cb);
|
|
20
|
+
return this;
|
|
21
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
|
|
4
|
+
const debug = createDebugger("agenda:name");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Set name of queue
|
|
8
|
+
* @name Agenda#name
|
|
9
|
+
* @function
|
|
10
|
+
* @param name name of agenda instance
|
|
11
|
+
*/
|
|
12
|
+
export const name = function (this: Agenda, name: string): Agenda {
|
|
13
|
+
debug("Agenda.name(%s)", name);
|
|
14
|
+
this._name = name;
|
|
15
|
+
return this;
|
|
16
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
import { Job, JobAttributesData } from "../job";
|
|
4
|
+
|
|
5
|
+
const debug = createDebugger("agenda:now");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Create a job for this exact moment
|
|
9
|
+
* @name Agenda#now
|
|
10
|
+
* @function
|
|
11
|
+
* @param name name of job to schedule
|
|
12
|
+
* @param data data to pass to job
|
|
13
|
+
*/
|
|
14
|
+
export const now = async function<T extends JobAttributesData> (
|
|
15
|
+
this: Agenda,
|
|
16
|
+
name: string,
|
|
17
|
+
data: T
|
|
18
|
+
): Promise<Job> {
|
|
19
|
+
debug("Agenda.now(%s, [Object])", name);
|
|
20
|
+
try {
|
|
21
|
+
const job = this.create(name, data);
|
|
22
|
+
|
|
23
|
+
job.schedule(new Date());
|
|
24
|
+
await job.save();
|
|
25
|
+
|
|
26
|
+
return job;
|
|
27
|
+
} catch (error) {
|
|
28
|
+
debug("error trying to create a job for this exact moment");
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import humanInterval from "human-interval";
|
|
3
|
+
import { Agenda } from ".";
|
|
4
|
+
|
|
5
|
+
const debug = createDebugger("agenda:processEvery");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Set the default process interval
|
|
9
|
+
* @name Agenda#processEvery
|
|
10
|
+
* @function
|
|
11
|
+
* @param time - time to process, expressed in human interval
|
|
12
|
+
*/
|
|
13
|
+
export const processEvery = function (this: Agenda, time: string): Agenda {
|
|
14
|
+
debug("Agenda.processEvery(%d)", time);
|
|
15
|
+
// @ts-expect-error
|
|
16
|
+
this._processEvery = humanInterval(time);
|
|
17
|
+
return this;
|
|
18
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
|
|
4
|
+
const debug = createDebugger("agenda:purge");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Removes all jobs from queue
|
|
8
|
+
* @name Agenda#purge
|
|
9
|
+
* @function
|
|
10
|
+
* @returns resolved when job cancelling fails or passes
|
|
11
|
+
*/
|
|
12
|
+
export const purge = async function (
|
|
13
|
+
this: Agenda
|
|
14
|
+
): Promise<number | undefined> {
|
|
15
|
+
// @NOTE: Only use after defining your jobs
|
|
16
|
+
const definedNames = Object.keys(this._definitions);
|
|
17
|
+
debug("Agenda.purge(%o)", definedNames);
|
|
18
|
+
return this.cancel({ name: { $not: { $in: definedNames } } });
|
|
19
|
+
};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { ObjectId } from "mongodb";
|
|
3
|
+
import { Agenda } from ".";
|
|
4
|
+
import { Job } from "../job";
|
|
5
|
+
import { processJobs } from "../utils";
|
|
6
|
+
|
|
7
|
+
const debug = createDebugger("agenda:saveJob");
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Given a result for findOneAndUpdate() or insert() above, determine whether to process
|
|
11
|
+
* the job immediately or to let the processJobs() interval pick it up later
|
|
12
|
+
* @param job job instance
|
|
13
|
+
* @param result the data returned from the findOneAndUpdate() call or insertOne() call
|
|
14
|
+
* @access private
|
|
15
|
+
*/
|
|
16
|
+
const processDbResult = async function (this: Agenda, job: Job, result: any) {
|
|
17
|
+
debug(
|
|
18
|
+
"processDbResult() called with success, checking whether to process job immediately or not"
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
// We have a result from the above calls
|
|
22
|
+
// findOneAndUpdate() returns different results than insertOne() so check for that
|
|
23
|
+
let resultValue = result.insertedId ? result.insertedId : result.value;
|
|
24
|
+
|
|
25
|
+
if (resultValue) {
|
|
26
|
+
let _id: ObjectId;
|
|
27
|
+
let nextRunAt: Date | null | undefined;
|
|
28
|
+
|
|
29
|
+
if (result.insertedId) {
|
|
30
|
+
_id = result.insertedId;
|
|
31
|
+
// find the doc using _id
|
|
32
|
+
const _job = await this._collection.findOne({ _id });
|
|
33
|
+
|
|
34
|
+
if (_job) {
|
|
35
|
+
nextRunAt = _job.nextRunAt;
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
// If it is an array, grab the first job
|
|
39
|
+
if (Array.isArray(resultValue)) {
|
|
40
|
+
resultValue = resultValue[0];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
_id = resultValue._id;
|
|
44
|
+
nextRunAt = resultValue.nextRunAt;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Grab ID and nextRunAt from MongoDB and store it as an attribute on Job
|
|
48
|
+
job.attrs._id = _id;
|
|
49
|
+
job.attrs.nextRunAt = nextRunAt;
|
|
50
|
+
|
|
51
|
+
// If the current job would have been processed in an older scan, process the job immediately
|
|
52
|
+
if (job.attrs.nextRunAt && job.attrs.nextRunAt < this._nextScanAt) {
|
|
53
|
+
debug(
|
|
54
|
+
"[%s:%s] job would have ran by nextScanAt, processing the job immediately",
|
|
55
|
+
job.attrs.name,
|
|
56
|
+
resultValue._id
|
|
57
|
+
);
|
|
58
|
+
await processJobs.call(this, job);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Return the Job instance
|
|
63
|
+
return job;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Save the properties on a job to MongoDB
|
|
68
|
+
* @name Agenda#saveJob
|
|
69
|
+
* @function
|
|
70
|
+
* @param job job to save into MongoDB
|
|
71
|
+
* @returns resolves when job is saved or errors
|
|
72
|
+
*/
|
|
73
|
+
export const saveJob = async function (this: Agenda, job: Job): Promise<Job> {
|
|
74
|
+
try {
|
|
75
|
+
debug("attempting to save a job into Agenda instance");
|
|
76
|
+
|
|
77
|
+
// Grab information needed to save job but that we don't want to persist in MongoDB
|
|
78
|
+
const id = job.attrs._id;
|
|
79
|
+
const { unique, uniqueOpts } = job.attrs;
|
|
80
|
+
|
|
81
|
+
// Store job as JSON and remove props we don't want to store from object
|
|
82
|
+
const props = job.toJSON();
|
|
83
|
+
delete props._id;
|
|
84
|
+
delete props.unique;
|
|
85
|
+
delete props.uniqueOpts;
|
|
86
|
+
|
|
87
|
+
// Store name of agenda queue as last modifier in job data
|
|
88
|
+
props.lastModifiedBy = this._name;
|
|
89
|
+
debug("[job %s] set job props: \n%O", id, props);
|
|
90
|
+
|
|
91
|
+
// Grab current time and set default query options for MongoDB
|
|
92
|
+
const now = new Date();
|
|
93
|
+
const protect = {};
|
|
94
|
+
let update = { $set: props };
|
|
95
|
+
debug("current time stored as %s", now.toISOString());
|
|
96
|
+
|
|
97
|
+
// If the job already had an ID, then update the properties of the job
|
|
98
|
+
// i.e, who last modified it, etc
|
|
99
|
+
if (id) {
|
|
100
|
+
// Update the job and process the resulting data'
|
|
101
|
+
debug(
|
|
102
|
+
"job already has _id, calling findOneAndUpdate() using _id as query"
|
|
103
|
+
);
|
|
104
|
+
const result = await this._collection.findOneAndUpdate(
|
|
105
|
+
{ _id: id },
|
|
106
|
+
update,
|
|
107
|
+
{ returnDocument: "after" }
|
|
108
|
+
);
|
|
109
|
+
return await processDbResult.call(this, job, result);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (props.type === "single") {
|
|
113
|
+
// Job type set to 'single' so...
|
|
114
|
+
// NOTE: Again, not sure about difference between 'single' here and 'once' in job.js
|
|
115
|
+
debug('job with type of "single" found');
|
|
116
|
+
|
|
117
|
+
// If the nextRunAt time is older than the current time, "protect" that property, meaning, don't change
|
|
118
|
+
// a scheduled job's next run time!
|
|
119
|
+
if (props.nextRunAt && props.nextRunAt <= now) {
|
|
120
|
+
debug(
|
|
121
|
+
"job has a scheduled nextRunAt time, protecting that field from upsert"
|
|
122
|
+
);
|
|
123
|
+
// @ts-expect-error
|
|
124
|
+
protect.nextRunAt = props.nextRunAt;
|
|
125
|
+
delete props.nextRunAt;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// If we have things to protect, set them in MongoDB using $setOnInsert
|
|
129
|
+
if (Object.keys(protect).length > 0) {
|
|
130
|
+
// @ts-expect-error
|
|
131
|
+
update.$setOnInsert = protect;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Try an upsert
|
|
135
|
+
// NOTE: 'single' again, not exactly sure what it means
|
|
136
|
+
debug(
|
|
137
|
+
'calling findOneAndUpdate() with job name and type of "single" as query'
|
|
138
|
+
);
|
|
139
|
+
const result = await this._collection.findOneAndUpdate(
|
|
140
|
+
{
|
|
141
|
+
name: props.name,
|
|
142
|
+
type: "single",
|
|
143
|
+
},
|
|
144
|
+
update,
|
|
145
|
+
{
|
|
146
|
+
upsert: true,
|
|
147
|
+
returnDocument: "after",
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
return await processDbResult.call(this, job, result);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (unique) {
|
|
154
|
+
// If we want the job to be unique, then we can upsert based on the 'unique' query object that was passed in
|
|
155
|
+
const query = job.attrs.unique;
|
|
156
|
+
query.name = props.name;
|
|
157
|
+
if (uniqueOpts?.insertOnly) {
|
|
158
|
+
// @ts-expect-error
|
|
159
|
+
update = { $setOnInsert: props };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Use the 'unique' query object to find an existing job or create a new one
|
|
163
|
+
debug(
|
|
164
|
+
"calling findOneAndUpdate() with unique object as query: \n%O",
|
|
165
|
+
query
|
|
166
|
+
);
|
|
167
|
+
const result = await this._collection.findOneAndUpdate(query, update, {
|
|
168
|
+
upsert: true,
|
|
169
|
+
returnDocument: "after",
|
|
170
|
+
});
|
|
171
|
+
return await processDbResult.call(this, job, result);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// If all else fails, the job does not exist yet so we just insert it into MongoDB
|
|
175
|
+
debug(
|
|
176
|
+
"using default behavior, inserting new job via insertOne() with props that were set: \n%O",
|
|
177
|
+
props
|
|
178
|
+
);
|
|
179
|
+
const result = await this._collection.insertOne(props);
|
|
180
|
+
return await processDbResult.call(this, job, result);
|
|
181
|
+
} catch (error) {
|
|
182
|
+
debug("processDbResult() received an error, job was not updated/created");
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
import { Job, JobAttributesData } from "../job";
|
|
4
|
+
|
|
5
|
+
const debug = createDebugger("agenda:schedule");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Schedule a job or jobs at a specific time
|
|
9
|
+
* @name Agenda#schedule
|
|
10
|
+
* @function
|
|
11
|
+
* @param when when the job gets run
|
|
12
|
+
* @param names array of job names to run
|
|
13
|
+
* @param data data to send to job
|
|
14
|
+
* @returns job or jobs created
|
|
15
|
+
*/
|
|
16
|
+
export function schedule<T extends JobAttributesData>(this: Agenda, when: string | Date, names: string, data: T): Promise<Job>;
|
|
17
|
+
export function schedule<T extends JobAttributesData>(this: Agenda, when: string | Date, names: string[], data: T): Promise<Job[]>;
|
|
18
|
+
export function schedule<T extends JobAttributesData> (
|
|
19
|
+
this: Agenda,
|
|
20
|
+
when: string | Date,
|
|
21
|
+
names: string | string[],
|
|
22
|
+
data: T,
|
|
23
|
+
): Promise<Job | Job[]> {
|
|
24
|
+
/**
|
|
25
|
+
* Internal method that creates a job with given date
|
|
26
|
+
* @param when when the job gets run
|
|
27
|
+
* @param name of job to run
|
|
28
|
+
* @param data data to send to job
|
|
29
|
+
* @returns instance of new job
|
|
30
|
+
*/
|
|
31
|
+
const createJob = async (
|
|
32
|
+
when: string | Date,
|
|
33
|
+
name: string,
|
|
34
|
+
data: any
|
|
35
|
+
): Promise<Job> => {
|
|
36
|
+
const job = this.create(name, data);
|
|
37
|
+
|
|
38
|
+
await job.schedule(when).save();
|
|
39
|
+
|
|
40
|
+
return job;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Internal helper method that calls createJob on a names array
|
|
45
|
+
* @param when when the job gets run
|
|
46
|
+
* @param names names of jobs to run
|
|
47
|
+
* @param data data to send to job
|
|
48
|
+
* @returns jobs that were created
|
|
49
|
+
*/
|
|
50
|
+
const createJobs = async (
|
|
51
|
+
when: string | Date,
|
|
52
|
+
names: string[],
|
|
53
|
+
data: any
|
|
54
|
+
): Promise<Job[]> => {
|
|
55
|
+
try {
|
|
56
|
+
const createJobList: Array<Promise<Job>> = [];
|
|
57
|
+
names.map((name) => createJobList.push(createJob(when, name, data)));
|
|
58
|
+
debug("Agenda.schedule()::createJobs() -> all jobs created successfully");
|
|
59
|
+
return Promise.all(createJobList);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
debug(
|
|
62
|
+
"Agenda.schedule()::createJobs() -> error creating one or more of the jobs"
|
|
63
|
+
);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
if (typeof names === "string") {
|
|
69
|
+
debug("Agenda.schedule(%s, %O, [%O], cb)", when, names);
|
|
70
|
+
return createJob(when, names, data);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (Array.isArray(names)) {
|
|
74
|
+
debug("Agenda.schedule(%s, %O, [%O])", when, names);
|
|
75
|
+
return createJobs(when, names, data);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
throw new TypeError("Name must be string or array of strings")
|
|
79
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
|
|
4
|
+
const debug = createDebugger("agenda:sort");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Set the sort query for finding next job
|
|
8
|
+
* Default is { nextRunAt: 1, priority: -1 }
|
|
9
|
+
* @name Agenda#sort
|
|
10
|
+
* @function
|
|
11
|
+
* @param query sort query object for MongoDB
|
|
12
|
+
*/
|
|
13
|
+
export const sort = function (this: Agenda, query: any): Agenda {
|
|
14
|
+
debug("Agenda.sort([Object])");
|
|
15
|
+
this._sort = query;
|
|
16
|
+
return this;
|
|
17
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
import { processJobs } from "../utils";
|
|
4
|
+
|
|
5
|
+
const debug = createDebugger("agenda:start");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Starts processing jobs using processJobs() methods, storing an interval ID
|
|
9
|
+
* This method will only resolve if a db has been set up beforehand.
|
|
10
|
+
* @name Agenda#start
|
|
11
|
+
* @function
|
|
12
|
+
* @returns resolves if db set beforehand, returns undefined otherwise
|
|
13
|
+
*/
|
|
14
|
+
export const start = async function (this: Agenda): Promise<void | unknown> {
|
|
15
|
+
if (this._processInterval) {
|
|
16
|
+
debug("Agenda.start was already called, ignoring");
|
|
17
|
+
return this._ready;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
await this._ready;
|
|
21
|
+
debug(
|
|
22
|
+
"Agenda.start called, creating interval to call processJobs every [%dms]",
|
|
23
|
+
this._processEvery
|
|
24
|
+
);
|
|
25
|
+
this._processInterval = setInterval(
|
|
26
|
+
processJobs.bind(this),
|
|
27
|
+
this._processEvery
|
|
28
|
+
);
|
|
29
|
+
process.nextTick(processJobs.bind(this));
|
|
30
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import createDebugger from "debug";
|
|
2
|
+
import { Agenda } from ".";
|
|
3
|
+
|
|
4
|
+
const debug = createDebugger("agenda:stop");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Clear the interval that processes the jobs
|
|
8
|
+
* @name Agenda#stop
|
|
9
|
+
* @function
|
|
10
|
+
* @returns resolves when job unlocking fails or passes
|
|
11
|
+
*/
|
|
12
|
+
export const stop = async function (this: Agenda): Promise<void> {
|
|
13
|
+
/**
|
|
14
|
+
* Internal method to unlock jobs so that they can be re-run
|
|
15
|
+
* NOTE: May need to update what properties get set here, since job unlocking seems to fail
|
|
16
|
+
* @access private
|
|
17
|
+
* @returns resolves when job unlocking fails or passes
|
|
18
|
+
*/
|
|
19
|
+
const _unlockJobs = async (): Promise<void> => {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
debug("Agenda._unlockJobs()");
|
|
22
|
+
const jobIds = this._lockedJobs.map((job) => job.attrs._id);
|
|
23
|
+
|
|
24
|
+
if (jobIds.length === 0) {
|
|
25
|
+
debug("no jobs to unlock");
|
|
26
|
+
resolve();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
debug("about to unlock jobs with ids: %O", jobIds);
|
|
30
|
+
this._collection.updateMany(
|
|
31
|
+
{ _id: { $in: jobIds } },
|
|
32
|
+
{ $set: { lockedAt: null } },
|
|
33
|
+
(error) => {
|
|
34
|
+
if (error) {
|
|
35
|
+
reject(error);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this._lockedJobs = [];
|
|
39
|
+
resolve();
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
debug("Agenda.stop called, clearing interval for processJobs()");
|
|
46
|
+
clearInterval(this._processInterval);
|
|
47
|
+
this._processInterval = undefined;
|
|
48
|
+
return _unlockJobs();
|
|
49
|
+
};
|
package/lib/cjs.ts
ADDED
package/lib/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// module export, beware: cjs.ts is exported as main entry point!
|
|
2
|
+
export * from "./agenda";
|
|
3
|
+
export * from "./job";
|
|
4
|
+
|
|
5
|
+
export { DefineOptions, JobPriority, Processor } from "./agenda/define";
|
|
6
|
+
export { JobOptions } from "./job/repeat-every";
|
|
7
|
+
|
|
8
|
+
import { Agenda } from "./agenda";
|
|
9
|
+
export { Agenda };
|
|
10
|
+
|
|
11
|
+
export default Agenda;
|