agenda 4.3.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.
Files changed (89) hide show
  1. package/History.md +12 -3
  2. package/README.md +38 -9
  3. package/dist/agenda/create.d.ts +2 -2
  4. package/dist/agenda/create.d.ts.map +1 -1
  5. package/dist/agenda/create.js.map +1 -1
  6. package/dist/agenda/define.d.ts +2 -2
  7. package/dist/agenda/define.d.ts.map +1 -1
  8. package/dist/agenda/define.js.map +1 -1
  9. package/dist/agenda/drain.d.ts +9 -0
  10. package/dist/agenda/drain.d.ts.map +1 -0
  11. package/dist/agenda/drain.js +46 -0
  12. package/dist/agenda/drain.js.map +1 -0
  13. package/dist/agenda/every.d.ts +2 -1
  14. package/dist/agenda/every.d.ts.map +1 -1
  15. package/dist/agenda/every.js +1 -1
  16. package/dist/agenda/every.js.map +1 -1
  17. package/dist/agenda/find-and-lock-next-job.d.ts.map +1 -1
  18. package/dist/agenda/find-and-lock-next-job.js +3 -4
  19. package/dist/agenda/find-and-lock-next-job.js.map +1 -1
  20. package/dist/agenda/index.d.ts +2 -0
  21. package/dist/agenda/index.d.ts.map +1 -1
  22. package/dist/agenda/index.js +2 -0
  23. package/dist/agenda/index.js.map +1 -1
  24. package/dist/agenda/now.d.ts +2 -2
  25. package/dist/agenda/now.d.ts.map +1 -1
  26. package/dist/agenda/now.js.map +1 -1
  27. package/dist/agenda/schedule.d.ts +3 -3
  28. package/dist/agenda/schedule.d.ts.map +1 -1
  29. package/dist/agenda/schedule.js.map +1 -1
  30. package/dist/job/compute-next-run-at.js +2 -2
  31. package/dist/job/compute-next-run-at.js.map +1 -1
  32. package/dist/job/index.d.ts +6 -3
  33. package/dist/job/index.d.ts.map +1 -1
  34. package/dist/job/index.js.map +1 -1
  35. package/lib/agenda/cancel.ts +28 -0
  36. package/lib/agenda/close.ts +37 -0
  37. package/lib/agenda/create.ts +22 -0
  38. package/lib/agenda/database.ts +63 -0
  39. package/lib/agenda/db-init.ts +45 -0
  40. package/lib/agenda/default-concurrency.ts +19 -0
  41. package/lib/agenda/default-lock-lifetime.ts +17 -0
  42. package/lib/agenda/default-lock-limit.ts +17 -0
  43. package/lib/agenda/define.ts +85 -0
  44. package/lib/agenda/disable.ts +28 -0
  45. package/lib/agenda/drain.ts +30 -0
  46. package/lib/agenda/enable.ts +29 -0
  47. package/lib/agenda/every.ts +86 -0
  48. package/lib/agenda/find-and-lock-next-job.ts +78 -0
  49. package/lib/agenda/has-mongo-protocol.ts +8 -0
  50. package/lib/agenda/index.ts +227 -0
  51. package/lib/agenda/job-processing-queue.ts +99 -0
  52. package/lib/agenda/jobs.ts +31 -0
  53. package/lib/agenda/lock-limit.ts +17 -0
  54. package/lib/agenda/max-concurrency.ts +20 -0
  55. package/lib/agenda/mongo.ts +21 -0
  56. package/lib/agenda/name.ts +16 -0
  57. package/lib/agenda/now.ts +31 -0
  58. package/lib/agenda/process-every.ts +18 -0
  59. package/lib/agenda/purge.ts +19 -0
  60. package/lib/agenda/save-job.ts +185 -0
  61. package/lib/agenda/schedule.ts +79 -0
  62. package/lib/agenda/sort.ts +17 -0
  63. package/lib/agenda/start.ts +30 -0
  64. package/lib/agenda/stop.ts +49 -0
  65. package/lib/cjs.ts +5 -0
  66. package/lib/index.ts +11 -0
  67. package/lib/job/compute-next-run-at.ts +191 -0
  68. package/lib/job/disable.ts +11 -0
  69. package/lib/job/enable.ts +11 -0
  70. package/lib/job/fail.ts +29 -0
  71. package/lib/job/index.ts +221 -0
  72. package/lib/job/is-running.ts +29 -0
  73. package/lib/job/priority.ts +11 -0
  74. package/lib/job/remove.ts +10 -0
  75. package/lib/job/repeat-at.ts +12 -0
  76. package/lib/job/repeat-every.ts +40 -0
  77. package/lib/job/run.ts +125 -0
  78. package/lib/job/save.ts +11 -0
  79. package/lib/job/schedule.ts +15 -0
  80. package/lib/job/set-shouldsaveresult.ts +10 -0
  81. package/lib/job/to-json.ts +36 -0
  82. package/lib/job/touch.ts +11 -0
  83. package/lib/job/unique.ts +18 -0
  84. package/lib/utils/create-job.ts +13 -0
  85. package/lib/utils/index.ts +3 -0
  86. package/lib/utils/parse-priority.ts +37 -0
  87. package/lib/utils/process-jobs.ts +379 -0
  88. package/package.json +14 -12
  89. package/tsconfig.json +72 -0
@@ -0,0 +1,10 @@
1
+ import { Job } from ".";
2
+
3
+ /**
4
+ * Remove the job from MongoDB
5
+ * @name Job#remove
6
+ * @function
7
+ */
8
+ export const remove = async function (this: Job): Promise<number | undefined> {
9
+ return this.agenda.cancel({ _id: this.attrs._id });
10
+ };
@@ -0,0 +1,12 @@
1
+ import { Job } from ".";
2
+
3
+ /**
4
+ * Sets a job to repeat at a specific time
5
+ * @name Job#repeatAt
6
+ * @function
7
+ * @param time time to repeat job at (human readable or number)
8
+ */
9
+ export const repeatAt = function (this: Job, time: string): Job {
10
+ this.attrs.repeatAt = time;
11
+ return this;
12
+ };
@@ -0,0 +1,40 @@
1
+ import { Job } from ".";
2
+
3
+ export interface JobOptions {
4
+ timezone?: string;
5
+ startDate?: Date | number;
6
+ endDate?: Date | number;
7
+ skipDays?: string;
8
+ skipImmediate?: boolean;
9
+ }
10
+
11
+ /**
12
+ * Sets a job to repeat every X amount of time
13
+ * @name Job#repeatEvery
14
+ * @function
15
+ * @param interval repeat every X
16
+ * @param options options to use for job
17
+ */
18
+ export const repeatEvery = function (
19
+ this: Job,
20
+ interval: string,
21
+ options: JobOptions = {}
22
+ ): Job {
23
+ this.attrs.repeatInterval = interval;
24
+ this.attrs.repeatTimezone = options.timezone ? options.timezone : null;
25
+ // Following options are added to handle start day
26
+ // and cases like run job every x days (skip some days)
27
+ this.attrs.startDate = options.startDate ?? null;
28
+ this.attrs.endDate = options.endDate ?? null;
29
+ this.attrs.skipDays = options.skipDays ?? null;
30
+ if (options.skipImmediate) {
31
+ // Set the lastRunAt time to the nextRunAt so that the new nextRunAt will be computed in reference to the current value.
32
+ this.attrs.lastRunAt = this.attrs.nextRunAt || new Date();
33
+ this.computeNextRunAt();
34
+ this.attrs.lastRunAt = undefined;
35
+ } else {
36
+ this.computeNextRunAt();
37
+ }
38
+
39
+ return this;
40
+ };
package/lib/job/run.ts ADDED
@@ -0,0 +1,125 @@
1
+ import createDebugger from "debug";
2
+ import { Job } from ".";
3
+
4
+ const debug = createDebugger("agenda:job");
5
+
6
+ /**
7
+ * Internal method (RUN)
8
+ * @name Job#run
9
+ * @function
10
+ */
11
+ export const run = async function (this: Job): Promise<Job> {
12
+ const { agenda } = this;
13
+ const definition = agenda._definitions[this.attrs.name];
14
+
15
+ // @TODO: this lint issue should be looked into: https://eslint.org/docs/rules/no-async-promise-executor
16
+ // eslint-disable-next-line no-async-promise-executor
17
+ return new Promise(async (resolve, reject) => {
18
+ this.attrs.lastRunAt = new Date();
19
+ debug(
20
+ "[%s:%s] setting lastRunAt to: %s",
21
+ this.attrs.name,
22
+ this.attrs._id,
23
+ this.attrs.lastRunAt.toISOString()
24
+ );
25
+ this.computeNextRunAt();
26
+ await this.save();
27
+
28
+ let finished = false;
29
+ const jobCallback = async (error?: Error, result?: unknown) => {
30
+ // We don't want to complete the job multiple times
31
+ if (finished) {
32
+ return;
33
+ }
34
+
35
+ finished = true;
36
+
37
+ if (error) {
38
+ this.fail(error);
39
+ } else {
40
+ this.attrs.lastFinishedAt = new Date();
41
+
42
+ if(this.attrs.shouldSaveResult && result) {
43
+ this.attrs.result = result;
44
+ }
45
+ }
46
+
47
+ this.attrs.lockedAt = null;
48
+
49
+ await this.save().catch((error: Error) => {
50
+ debug(
51
+ "[%s:%s] failed to be saved to MongoDB",
52
+ this.attrs.name,
53
+ this.attrs._id
54
+ );
55
+ reject(error);
56
+ });
57
+ debug(
58
+ "[%s:%s] was saved successfully to MongoDB",
59
+ this.attrs.name,
60
+ this.attrs._id
61
+ );
62
+
63
+ if (error) {
64
+ agenda.emit("fail", error, this);
65
+ agenda.emit("fail:" + this.attrs.name, error, this);
66
+ debug(
67
+ "[%s:%s] has failed [%s]",
68
+ this.attrs.name,
69
+ this.attrs._id,
70
+ error.message
71
+ );
72
+ } else {
73
+ agenda.emit("success", this);
74
+ agenda.emit("success:" + this.attrs.name, this);
75
+ debug("[%s:%s] has succeeded", this.attrs.name, this.attrs._id);
76
+ }
77
+
78
+ agenda.emit("complete", this);
79
+ agenda.emit("complete:" + this.attrs.name, this);
80
+ debug(
81
+ "[%s:%s] job finished at [%s] and was unlocked",
82
+ this.attrs.name,
83
+ this.attrs._id,
84
+ this.attrs.lastFinishedAt
85
+ );
86
+ // Curiously, we still resolve successfully if the job processor failed.
87
+ // Agenda is not equipped to handle errors originating in user code, so, we leave them to inspect the side-effects of job.fail()
88
+ resolve(this);
89
+ };
90
+
91
+ try {
92
+ agenda.emit("start", this);
93
+ agenda.emit("start:" + this.attrs.name, this);
94
+ debug("[%s:%s] starting job", this.attrs.name, this.attrs._id);
95
+ if (!definition) {
96
+ debug(
97
+ "[%s:%s] has no definition, can not run",
98
+ this.attrs.name,
99
+ this.attrs._id
100
+ );
101
+ throw new Error("Undefined job");
102
+ }
103
+
104
+ if (definition.fn.length === 2) {
105
+ debug(
106
+ "[%s:%s] process function being called",
107
+ this.attrs.name,
108
+ this.attrs._id
109
+ );
110
+ await definition.fn(this, jobCallback);
111
+ } else {
112
+ debug(
113
+ "[%s:%s] process function being called",
114
+ this.attrs.name,
115
+ this.attrs._id
116
+ );
117
+ const result = await definition.fn(this);
118
+ await jobCallback(undefined, result);
119
+ }
120
+ } catch (error) {
121
+ debug("[%s:%s] unknown error occurred", this.attrs.name, this.attrs._id);
122
+ await jobCallback(error as Error);
123
+ }
124
+ });
125
+ };
@@ -0,0 +1,11 @@
1
+ import { Job } from ".";
2
+
3
+ /**
4
+ * Saves a job into the MongoDB
5
+ * @name Job#
6
+ * @function
7
+ * @returns instance of Job resolved after job is saved or errors
8
+ */
9
+ export const save = async function (this: Job): Promise<Job> {
10
+ return this.agenda.saveJob(this);
11
+ };
@@ -0,0 +1,15 @@
1
+ // @ts-expect-error
2
+ import date from "date.js";
3
+ import { Job } from ".";
4
+
5
+ /**
6
+ * Schedules a job to run at specified time
7
+ * @name Job#schedule
8
+ * @function
9
+ * @param time schedule a job to run "then"
10
+ */
11
+ export const schedule = function (this: Job, time: string | Date): Job {
12
+ const d = new Date(time);
13
+ this.attrs.nextRunAt = Number.isNaN(d.getTime()) ? date(time) : d;
14
+ return this;
15
+ };
@@ -0,0 +1,10 @@
1
+ import { Job } from ".";
2
+
3
+ /**
4
+ * Sets the flag if the return value of the job should be persisted
5
+ * @param shouldSaveResult flag if the return value of the job should be persisted
6
+ */
7
+ export const setShouldSaveResult = function (this: Job, shouldSaveResult: boolean): Job {
8
+ this.attrs.shouldSaveResult = shouldSaveResult;
9
+ return this;
10
+ };
@@ -0,0 +1,36 @@
1
+ import { Job, JobAttributes } from ".";
2
+
3
+ /**
4
+ * Given a job, turn it into an object we can store in Mongo
5
+ * @name Job#toJSON
6
+ * @function
7
+ * @returns json object from Job
8
+ */
9
+ export const toJson = function (this: Job): Partial<JobAttributes> {
10
+ const attrs = this.attrs || {};
11
+ const result = {};
12
+
13
+ for (const prop in attrs) {
14
+ if ({}.hasOwnProperty.call(attrs, prop)) {
15
+ // @ts-expect-error index signature missing
16
+ result[prop] = attrs[prop];
17
+ }
18
+ }
19
+
20
+ const dates = [
21
+ "lastRunAt",
22
+ "lastFinishedAt",
23
+ "nextRunAt",
24
+ "failedAt",
25
+ "lockedAt",
26
+ ];
27
+ dates.forEach((d) => {
28
+ // @ts-expect-error index signature missing
29
+ if (result[d]) {
30
+ // @ts-expect-error index signature missing
31
+ result[d] = new Date(result[d]);
32
+ }
33
+ });
34
+
35
+ return result;
36
+ };
@@ -0,0 +1,11 @@
1
+ import { Job } from ".";
2
+
3
+ /**
4
+ * Updates "lockedAt" time so the job does not get picked up again
5
+ * @name Job#touch
6
+ * @function
7
+ */
8
+ export const touch = async function (this: Job): Promise<Job> {
9
+ this.attrs.lockedAt = new Date();
10
+ return this.save();
11
+ };
@@ -0,0 +1,18 @@
1
+ import { Job } from ".";
2
+
3
+ /**
4
+ * Data to ensure is unique for job to be created
5
+ * @name Job#unique
6
+ * @function
7
+ * @param unique mongo data query for unique
8
+ * @param options unique options
9
+ */
10
+ export const unique = function (
11
+ this: Job,
12
+ unique: any,
13
+ options?: { insertOnly: boolean }
14
+ ): Job {
15
+ this.attrs.unique = unique;
16
+ this.attrs.uniqueOpts = options;
17
+ return this;
18
+ };
@@ -0,0 +1,13 @@
1
+ import { Agenda } from "../agenda";
2
+ import { Job, JobAttributes } from "../job";
3
+
4
+ /**
5
+ * Create Job object from data
6
+ * @param {Object} agenda instance of Agenda
7
+ * @param {Object} jobData job data
8
+ * @returns {Job} returns created job
9
+ */
10
+ export const createJob = (agenda: Agenda, jobData: JobAttributes): Job => {
11
+ jobData.agenda = agenda;
12
+ return new Job(jobData);
13
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./create-job";
2
+ export * from "./parse-priority";
3
+ export * from "./process-jobs";
@@ -0,0 +1,37 @@
1
+ import { JobPriority } from "../agenda/define";
2
+
3
+ /**
4
+ * Internal method to turn priority into a number
5
+ * @param priority string to parse into number
6
+ */
7
+ export const parsePriority = (priority: string | number): number => {
8
+ if (typeof priority === "number") {
9
+ return priority;
10
+ }
11
+
12
+ switch (priority) {
13
+ case "lowest": {
14
+ return JobPriority.lowest;
15
+ }
16
+
17
+ case "low": {
18
+ return JobPriority.low;
19
+ }
20
+
21
+ case "normal": {
22
+ return JobPriority.normal;
23
+ }
24
+
25
+ case "high": {
26
+ return JobPriority.high;
27
+ }
28
+
29
+ case "highest": {
30
+ return JobPriority.highest;
31
+ }
32
+
33
+ default: {
34
+ return JobPriority.normal;
35
+ }
36
+ }
37
+ };