@cocreate/cron-jobs 1.0.0 → 1.1.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/CHANGELOG.md +12 -0
- package/package.json +1 -1
- package/src/index.js +346 -72
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [1.1.0](https://github.com/CoCreate-app/CoCreate-cron-jobs/compare/v1.0.0...v1.1.0) (2024-09-21)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* improved handling of platform db and organization db ([8edf03d](https://github.com/CoCreate-app/CoCreate-cron-jobs/commit/8edf03d83689dc7bbfe884e8db8c655934a3e36f))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* getNextExecutionTime ([4ffc1aa](https://github.com/CoCreate-app/CoCreate-cron-jobs/commit/4ffc1aa899942b63b80fa281a6d687947cb8b50d))
|
|
12
|
+
|
|
1
13
|
# 1.0.0 (2024-09-08)
|
|
2
14
|
|
|
3
15
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -20,131 +20,405 @@
|
|
|
20
20
|
// you must obtain a commercial license from CoCreate LLC.
|
|
21
21
|
// For details, visit <https://cocreate.app/licenses/> or contact us at sales@cocreate.app.
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* CoCreateCronJobs class is responsible for managing cron jobs for organizations.
|
|
25
|
+
* It listens to CRUD events and polls the platform DB to schedule and execute cron jobs.
|
|
26
|
+
*
|
|
27
|
+
* Example Object:
|
|
28
|
+
*
|
|
29
|
+
* @typedef {Object} CronJobEvent
|
|
30
|
+
* @property {string} organization_id - The ID of the organization for which the cron job is scheduled.
|
|
31
|
+
* @property {string} nextExecutionTime - The ISO 8601 timestamp for the next time the cron job is scheduled to execute.
|
|
32
|
+
* @property {Object} [schedule] - The scheduling information, including cronExpression, interval, and time-related settings.
|
|
33
|
+
* @property {string} [status] - The current status of the cron job, e.g., 'assigned', 'completed', 'failed'.
|
|
34
|
+
* @property {boolean} [active] - Whether the cron job is active or paused.
|
|
35
|
+
* @property {Object} [job] - The job that is to be executed, which could be $crud, $api, or other specific operations.
|
|
36
|
+
* @property {Object} [retryPolicy] - Retry settings for failed jobs, including retries and backoff strategy.
|
|
37
|
+
* @property {Object} [log] - An optional log of the cron job's last execution details, including status and message.
|
|
38
|
+
*
|
|
39
|
+
* Example Object:
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* {
|
|
43
|
+
* "organization_id": "652c8d62679eca03e0b116a7",
|
|
44
|
+
* "nextExecutionTime": "2024-09-10T02:00:00Z",
|
|
45
|
+
* "active": true, // Whether the cron job is active or paused
|
|
46
|
+
* "status": "assigned",
|
|
47
|
+
* "schedule": {
|
|
48
|
+
* "cronExpression": "0 2 * * *", // Standard cron expression (for Unix-based scheduling)
|
|
49
|
+
* "startBoundary": "2024-09-10T02:00:00Z", // The first scheduled execution time
|
|
50
|
+
* "endBoundary": "2025-09-10T02:00:00Z", // The end time after which no further executions will occur
|
|
51
|
+
* "interval": "P1D", // ISO 8601 format for repeating interval (e.g., repeat every day)
|
|
52
|
+
* "daysOfWeek": ["Monday", "Wednesday"], // Days of the week when the job should run
|
|
53
|
+
* "daysOfMonth": [1, 15], // Specific days of the month for execution
|
|
54
|
+
* "months": ["January", "July"], // Specific months for execution
|
|
55
|
+
* "skipDates": ["2024-12-25"], // Dates to skip execution
|
|
56
|
+
* "timezone": "UTC", // Timezone for scheduling
|
|
57
|
+
* "time": "02:00:00" // Specific time of day when the job should run
|
|
58
|
+
* },
|
|
59
|
+
* "job": {
|
|
60
|
+
* "$crud": {
|
|
61
|
+
* "method": "object.update",
|
|
62
|
+
* "array": "users",
|
|
63
|
+
* "query": { "stripe.account_id": "acc_123456" },
|
|
64
|
+
* "object": { "stripe.balance": 1000 }
|
|
65
|
+
* }
|
|
66
|
+
* },
|
|
67
|
+
* "retryPolicy": {
|
|
68
|
+
* "retries": 3, // Number of retries for failed jobs
|
|
69
|
+
* "retryInterval": "PT10M" // Interval between retries in ISO 8601 format
|
|
70
|
+
* },
|
|
71
|
+
* "backoffStrategy": {
|
|
72
|
+
* "type": "exponential", // Type of backoff strategy (exponential, linear, etc.)
|
|
73
|
+
* "initialDelay": "PT5M" // Initial delay before the first retry
|
|
74
|
+
* },
|
|
75
|
+
* "executionTimeout": "PT2H", // Timeout for job execution (ISO 8601 format)
|
|
76
|
+
* "log": {
|
|
77
|
+
* "timestamp": "2024-09-09T02:00:00Z",
|
|
78
|
+
* "status": "completed",
|
|
79
|
+
* "message": "Job executed successfully"
|
|
80
|
+
* }
|
|
81
|
+
* }
|
|
82
|
+
*
|
|
83
|
+
* @class CoCreateCronJobs
|
|
84
|
+
*/
|
|
23
85
|
class CoCreateCronJobs {
|
|
86
|
+
/**
|
|
87
|
+
* Creates an instance of CoCreateCronJobs.
|
|
88
|
+
* @param {Object} crud - The CRUD module used to handle data operations.
|
|
89
|
+
*/
|
|
24
90
|
constructor(crud) {
|
|
25
|
-
this.crud = crud;
|
|
26
|
-
this.scheduledJobs = {};
|
|
91
|
+
this.crud = crud;
|
|
92
|
+
this.scheduledJobs = {};
|
|
27
93
|
|
|
28
|
-
// Listen to
|
|
29
|
-
|
|
94
|
+
// Listen for CRUD events related to cron jobs
|
|
95
|
+
process.on('crud-event', (event) => {
|
|
30
96
|
this.handleCrudEvent(event);
|
|
31
97
|
});
|
|
32
98
|
|
|
33
99
|
// Start polling every 5 minutes
|
|
34
100
|
setInterval(() => {
|
|
35
101
|
this.pollForCronJobs();
|
|
36
|
-
}, 5 * 60 * 1000);
|
|
102
|
+
}, 5 * 60 * 1000);
|
|
37
103
|
}
|
|
38
104
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Handles CRUD events to schedule cron jobs.
|
|
107
|
+
* @param {Object} data - The data object emitted from CRUD operations.
|
|
108
|
+
*/
|
|
109
|
+
handleCrudEvent(data) {
|
|
110
|
+
// Check if the array is 'cron-job'
|
|
111
|
+
if (data.array !== 'cron-job') {
|
|
112
|
+
return; // Ignore non-cron-job events
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Iterate over the jobs in the data.object array
|
|
116
|
+
for (let i = 0; i < data.object.length; i++) {
|
|
117
|
+
if (data.method === 'object.delete' || data.object[i].active === false) {
|
|
118
|
+
const timeoutId = this.scheduledJobs[data.object[i]._id];
|
|
42
119
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
120
|
+
if (timeoutId) {
|
|
121
|
+
clearTimeout(timeoutId); // Cancel the timeout if it exists
|
|
122
|
+
delete this.scheduledJobs[data.object[i]._id]; // Remove the reference
|
|
123
|
+
}
|
|
46
124
|
|
|
47
|
-
|
|
48
|
-
|
|
125
|
+
data.object.splice(i, 1);
|
|
126
|
+
i--; // Adjust the index after removal
|
|
49
127
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const nextExecutionTime = this.getNextExecutionTime(data.object[i].schedule);
|
|
132
|
+
|
|
133
|
+
if (nextExecutionTime) {
|
|
134
|
+
// TODO: Compare executionTime if equal continue
|
|
135
|
+
if (this.scheduledJobs[data.object[i]._id])
|
|
136
|
+
continue
|
|
137
|
+
|
|
138
|
+
const timeUntilExecution = new Date(nextExecutionTime) - new Date();
|
|
139
|
+
|
|
140
|
+
data.object[i].nextExecutionTime = nextExecutionTime
|
|
141
|
+
|
|
142
|
+
// If the next execution is within the next 5 minutes, schedule the job
|
|
143
|
+
if (timeUntilExecution <= 5 * 60 * 1000 && timeUntilExecution > 0) {
|
|
144
|
+
data.object[i].status = 'assigned'
|
|
145
|
+
this.scheduleCronJob(data.object[i]);
|
|
146
|
+
}
|
|
53
147
|
} else {
|
|
54
|
-
|
|
55
|
-
|
|
148
|
+
data.object.splice(i, 1);
|
|
149
|
+
i--; // Adjust the index after removal
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
this.updateCronJob(data.object);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Parses the schedule object and calculates the next execution time.
|
|
158
|
+
* Takes into account cronExpression, startTime, skipDates, time, daysOfWeek, daysOfMonth, months, endTime, etc.
|
|
159
|
+
*
|
|
160
|
+
* @param {Object} schedule - The schedule object containing cronExpression, startTime, etc.
|
|
161
|
+
* @returns {string|null} nextExecutionTime - The calculated next execution time in ISO 8601 format, or null if endTime has passed.
|
|
162
|
+
*/
|
|
163
|
+
getNextExecutionTime(schedule) {
|
|
164
|
+
const now = new Date();
|
|
165
|
+
let currentDateTime = now;
|
|
166
|
+
|
|
167
|
+
// Use startTime if it's greater than now, otherwise use now
|
|
168
|
+
if (schedule.startTime && new Date(schedule.startTime) > now) {
|
|
169
|
+
currentDateTime = new Date(schedule.startTime);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Apply skipDates: Skip the date if it matches any in skipDates
|
|
173
|
+
if (schedule.skipDates && schedule.skipDates.includes(currentDateTime.toISOString().split('T')[0])) {
|
|
174
|
+
currentDateTime = new Date(currentDateTime.getTime() + 24 * 60 * 60 * 1000); // Skip to the next day
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Apply daysOfWeek: If the current day is not in the allowed days, skip to the next valid day
|
|
178
|
+
if (schedule.daysOfWeek) {
|
|
179
|
+
const dayOfWeek = currentDateTime.toLocaleString('en-US', { weekday: 'long', timeZone: schedule.timezone || 'UTC' });
|
|
180
|
+
|
|
181
|
+
while (!schedule.daysOfWeek.includes(dayOfWeek)) {
|
|
182
|
+
currentDateTime.setDate(currentDateTime.getDate() + 1); // Move to the next day
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Apply daysOfMonth: Ensure the next execution is on a valid day of the month
|
|
187
|
+
if (schedule.daysOfMonth) {
|
|
188
|
+
while (!schedule.daysOfMonth.includes(currentDateTime.getDate())) {
|
|
189
|
+
currentDateTime.setDate(currentDateTime.getDate() + 1); // Move to the next day
|
|
56
190
|
}
|
|
57
191
|
}
|
|
192
|
+
|
|
193
|
+
// Apply months: Ensure the next execution falls within one of the allowed months
|
|
194
|
+
if (schedule.months) {
|
|
195
|
+
const monthName = currentDateTime.toLocaleString('en-US', { month: 'long', timeZone: schedule.timezone || 'UTC' });
|
|
196
|
+
|
|
197
|
+
while (!schedule.months.includes(monthName)) {
|
|
198
|
+
currentDateTime.setMonth(currentDateTime.getMonth() + 1); // Move to the next month
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Apply time: Set the execution time of day if specified
|
|
203
|
+
if (schedule.time) {
|
|
204
|
+
const [hours, minutes, seconds] = schedule.time.split(':');
|
|
205
|
+
currentDateTime.setHours(hours, minutes, seconds);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Apply endTime: Ensure the next execution time does not exceed the endTime
|
|
209
|
+
if (schedule.endTime && new Date(currentDateTime) > new Date(schedule.endTime)) {
|
|
210
|
+
return null; // No further executions after endTime
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Now run the cronParser to handle cronExpression (if present) or fallback to currentDateTime
|
|
214
|
+
if (schedule.cronExpression) {
|
|
215
|
+
const interval = cronParser.parseExpression(schedule.cronExpression, {
|
|
216
|
+
currentDate: currentDateTime,
|
|
217
|
+
tz: schedule.timezone || 'UTC'
|
|
218
|
+
});
|
|
219
|
+
return interval.next().toISOString();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return currentDateTime.toISOString();
|
|
58
223
|
}
|
|
59
224
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
225
|
+
/**
|
|
226
|
+
* Schedules a cron job to be executed at a specific datetime.
|
|
227
|
+
*
|
|
228
|
+
* @param {string} organization_id - The organization ID.
|
|
229
|
+
* @param {string} datetime - The time at which the job should be executed.
|
|
230
|
+
*/
|
|
231
|
+
scheduleCronJob(object) {
|
|
232
|
+
const delay = new Date(object.nextExecutionTime) - new Date();
|
|
64
233
|
|
|
65
234
|
if (delay <= 0) {
|
|
66
|
-
|
|
235
|
+
this.executeCronJob(object);
|
|
67
236
|
return;
|
|
68
237
|
}
|
|
69
238
|
|
|
70
|
-
console.log(`Scheduling cron job for org ${organization_id} in ${delay / 1000} seconds`);
|
|
239
|
+
console.log(`Scheduling cron job for org ${object.organization_id} in ${delay / 1000} seconds`);
|
|
71
240
|
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
241
|
+
// TODO: get clusterId, serverId and workerId
|
|
242
|
+
object = {
|
|
243
|
+
_id: object._id,
|
|
244
|
+
nextExecutionTime: object.nextExecutionTime,
|
|
245
|
+
status: object.status,
|
|
246
|
+
clusterId: 'id',
|
|
247
|
+
severId: 'id',
|
|
248
|
+
workerId: 'id',
|
|
249
|
+
organization_id: object.organization_id
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
this.scheduledJobs[object._id] = setTimeout(() => {
|
|
253
|
+
this.executeCronJob(object);
|
|
75
254
|
}, delay);
|
|
76
255
|
}
|
|
77
256
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Executes the scheduled cron job.
|
|
259
|
+
*
|
|
260
|
+
* @param {Object} schedule - The cron-job object containing job, schedule, etc.
|
|
261
|
+
*/
|
|
262
|
+
async executeCronJob(object) {
|
|
263
|
+
console.log(`Executing cron job for org ${object.organization_id}`);
|
|
81
264
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}).catch(error => {
|
|
93
|
-
console.error(`Error fetching cron job for org ${organization_id}:`, error);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
265
|
+
if (!object.job) {
|
|
266
|
+
let data = await this.crud.send({
|
|
267
|
+
method: 'object.read',
|
|
268
|
+
array: 'cron-job',
|
|
269
|
+
object: { _id: object._id },
|
|
270
|
+
organization_id: object.organization_id
|
|
271
|
+
})
|
|
272
|
+
object = data.object[0]
|
|
273
|
+
console.log('Fetched cron job data:', object);
|
|
274
|
+
}
|
|
96
275
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
276
|
+
// TODO: execute cron using lazyloader.webhook()
|
|
277
|
+
object.nextExecutionTime = this.getNextExecutionTime(object.schedule);
|
|
278
|
+
if (!object.nextExecutionTime) {
|
|
279
|
+
object.active = false
|
|
280
|
+
object.status = 'completed'
|
|
281
|
+
}
|
|
100
282
|
|
|
101
|
-
this.
|
|
102
|
-
collection: 'organizations',
|
|
103
|
-
query: { _id: organization_id },
|
|
104
|
-
update: { nextCronExecutionTime: datetime },
|
|
105
|
-
}).then(() => {
|
|
106
|
-
console.log(`Platform DB updated for org ${organization_id}`);
|
|
107
|
-
}).catch(error => {
|
|
108
|
-
console.error(`Error updating platform DB for org ${organization_id}:`, error);
|
|
109
|
-
});
|
|
283
|
+
this.updateCronJob(object);
|
|
110
284
|
}
|
|
111
285
|
|
|
112
|
-
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Polls the platform DB for cron jobs that are scheduled or potentially failed.
|
|
289
|
+
*/
|
|
113
290
|
pollForCronJobs() {
|
|
114
291
|
console.log('Polling for cron jobs...');
|
|
115
292
|
|
|
116
|
-
// Query the platform DB for organizations with a nextCronExecutionTime within 5 minutes
|
|
117
293
|
const now = new Date();
|
|
118
294
|
const fiveMinutesFromNow = new Date(now.getTime() + 5 * 60 * 1000);
|
|
295
|
+
const oneMinuteAgo = new Date(now.getTime() - 1 * 60 * 1000); // 1 minute past due jobs
|
|
119
296
|
|
|
120
|
-
this.crud.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
297
|
+
this.crud.send({
|
|
298
|
+
method: 'object.read',
|
|
299
|
+
array: 'organizations',
|
|
300
|
+
filter: {
|
|
301
|
+
query: {
|
|
302
|
+
$or: [
|
|
303
|
+
{
|
|
304
|
+
$and: [
|
|
305
|
+
{ 'cron-jobs.nextExecutionTime': { $elemMatch: { $lte: fiveMinutesFromNow, $gte: now } } }, // Match jobs in array within 5 minutes
|
|
306
|
+
{ 'cron-jobs.status': { $elemMatch: { $ne: 'assigned' } } }, // Not already assigned
|
|
307
|
+
{ 'cron-jobs.active': { $elemMatch: { $ne: false } } } // Is active
|
|
308
|
+
]
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
$and: [
|
|
312
|
+
{ 'cron-jobs.nextExecutionTime': { $elemMatch: { $lt: oneMinuteAgo } } }, // Past due by 1 minute
|
|
313
|
+
{ 'cron-jobs.status': { $elemMatch: { $eq: 'assigned' } } }, // Assigned but not started
|
|
314
|
+
{ 'cron-jobs.active': { $elemMatch: { $ne: false } } } // Is active
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
]
|
|
318
|
+
}
|
|
124
319
|
},
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
320
|
+
organization_id: process.env.organization_id
|
|
321
|
+
}).then(data => {
|
|
322
|
+
for (let i = 0; i < data.object.length; i++) {
|
|
323
|
+
const cronJobs = data.object[i].cronJobs;
|
|
324
|
+
if (!cronJobs)
|
|
325
|
+
return
|
|
326
|
+
|
|
327
|
+
// Check each cron job in the organization's `cron-jobs` array
|
|
328
|
+
for (let j = 0; j < cronJobs; j++) {
|
|
329
|
+
if (this.scheduledJobs[cronJobs[j]._id])
|
|
330
|
+
return
|
|
128
331
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
332
|
+
cronJobs[j].status = 'assigned'
|
|
333
|
+
|
|
334
|
+
// TODO: get clusterId, serverId and workerId
|
|
335
|
+
cronJobs[j].clusterId = 'id'
|
|
336
|
+
cronJobs[j].severId = 'id'
|
|
337
|
+
cronJobs[j].workerId = 'id'
|
|
338
|
+
cronJobs[j].organization_id = data.object[i].organization_id
|
|
339
|
+
|
|
340
|
+
this.scheduleCronJob(cronJobs[j]);
|
|
132
341
|
}
|
|
133
|
-
|
|
342
|
+
|
|
343
|
+
this.updateCronJob(cronJobs);
|
|
344
|
+
}
|
|
134
345
|
}).catch(error => {
|
|
135
346
|
console.error('Error polling for cron jobs:', error);
|
|
136
347
|
});
|
|
137
348
|
}
|
|
138
349
|
|
|
139
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Marks the cron job as failed after it is detected as past due and not started.
|
|
352
|
+
*/
|
|
353
|
+
updateCronJob(object) {
|
|
354
|
+
if (!Array.isArray(object))
|
|
355
|
+
object = [object]
|
|
356
|
+
|
|
357
|
+
for (let i = 0; i < object.length; i++) {
|
|
358
|
+
this.crud.send({
|
|
359
|
+
method: 'object.update',
|
|
360
|
+
array: 'cron-jobs',
|
|
361
|
+
object,
|
|
362
|
+
upsert: true,
|
|
363
|
+
organization_id: object.organization_id
|
|
364
|
+
}).then(() => {
|
|
365
|
+
console.log(`Cron job for org ${object.organization_id} updated.`);
|
|
366
|
+
}).catch(error => {
|
|
367
|
+
console.error(`Error updating cron job for org ${object.organization_id}:`, error);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const cronJobs = object
|
|
373
|
+
this.crud.send({
|
|
374
|
+
method: 'object.update',
|
|
375
|
+
array: 'organizations',
|
|
376
|
+
object: {
|
|
377
|
+
_id: object.organization_id,
|
|
378
|
+
cronJobs
|
|
379
|
+
},
|
|
380
|
+
organization_id: process.env.organization_id
|
|
381
|
+
}).then(() => {
|
|
382
|
+
console.log(`Cron job for org ${object.organization_id} updated.`);
|
|
383
|
+
}).catch(error => {
|
|
384
|
+
console.error(`Error updating cron job for org ${object.organization_id}:`, error);
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Adds a cron job reference to the platform database.
|
|
390
|
+
*
|
|
391
|
+
* @param {string} organization_id - The organization ID.
|
|
392
|
+
* @param {string} datetime - The datetime of the cron job to add to the platform DB.
|
|
393
|
+
*/
|
|
394
|
+
addToPlatformDB(organization_id, datetime) {
|
|
395
|
+
console.log(`Adding cron job reference to platform DB for org ${organization_id}`);
|
|
396
|
+
|
|
397
|
+
this.crud.send({
|
|
398
|
+
method: 'object.read',
|
|
399
|
+
array: 'organizations',
|
|
400
|
+
object: { _id: organization_id, nextCron: datetime },
|
|
401
|
+
organization_id: process.env.organization_id
|
|
402
|
+
}).then(() => {
|
|
403
|
+
console.log(`Platform DB updated for org ${organization_id}`);
|
|
404
|
+
}).catch(error => {
|
|
405
|
+
console.error(`Error updating platform DB for org ${organization_id}:`, error);
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Finds and schedules the next cron job for the organization after one is executed.
|
|
411
|
+
*
|
|
412
|
+
* @param {string} organization_id - The organization ID.
|
|
413
|
+
*/
|
|
140
414
|
findNextCronJob(organization_id) {
|
|
141
415
|
console.log(`Finding next cron job for org ${organization_id}`);
|
|
142
416
|
|
|
143
417
|
this.crud.read({
|
|
144
418
|
collection: 'cron-job',
|
|
145
419
|
query: { organization_id },
|
|
146
|
-
sort: { datetime: 1 },
|
|
147
|
-
limit: 1
|
|
420
|
+
sort: { datetime: 1 },
|
|
421
|
+
limit: 1
|
|
148
422
|
}).then(nextJob => {
|
|
149
423
|
if (nextJob.length > 0) {
|
|
150
424
|
const { datetime } = nextJob[0];
|