@memberjunction/scheduling-engine 2.107.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/dist/BaseScheduledJob.d.ts +122 -0
- package/dist/BaseScheduledJob.d.ts.map +1 -0
- package/dist/BaseScheduledJob.js +105 -0
- package/dist/BaseScheduledJob.js.map +1 -0
- package/dist/CronExpressionHelper.d.ts +36 -0
- package/dist/CronExpressionHelper.d.ts.map +1 -0
- package/dist/CronExpressionHelper.js +106 -0
- package/dist/CronExpressionHelper.js.map +1 -0
- package/dist/NotificationManager.d.ts +19 -0
- package/dist/NotificationManager.d.ts.map +1 -0
- package/dist/NotificationManager.js +44 -0
- package/dist/NotificationManager.js.map +1 -0
- package/dist/ScheduledJobEngine.d.ts +188 -0
- package/dist/ScheduledJobEngine.d.ts.map +1 -0
- package/dist/ScheduledJobEngine.js +601 -0
- package/dist/ScheduledJobEngine.js.map +1 -0
- package/dist/drivers/ActionScheduledJobDriver.d.ts +40 -0
- package/dist/drivers/ActionScheduledJobDriver.d.ts.map +1 -0
- package/dist/drivers/ActionScheduledJobDriver.js +175 -0
- package/dist/drivers/ActionScheduledJobDriver.js.map +1 -0
- package/dist/drivers/AgentScheduledJobDriver.d.ts +40 -0
- package/dist/drivers/AgentScheduledJobDriver.d.ts.map +1 -0
- package/dist/drivers/AgentScheduledJobDriver.js +149 -0
- package/dist/drivers/AgentScheduledJobDriver.js.map +1 -0
- package/dist/drivers/index.d.ts +12 -0
- package/dist/drivers/index.d.ts.map +1 -0
- package/dist/drivers/index.js +35 -0
- package/dist/drivers/index.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Engine for managing and executing scheduled jobs
|
|
4
|
+
* @module @memberjunction/scheduling-engine
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.SchedulingEngine = void 0;
|
|
8
|
+
const core_1 = require("@memberjunction/core");
|
|
9
|
+
const global_1 = require("@memberjunction/global");
|
|
10
|
+
const scheduling_engine_base_1 = require("@memberjunction/scheduling-engine-base");
|
|
11
|
+
const BaseScheduledJob_1 = require("./BaseScheduledJob");
|
|
12
|
+
const CronExpressionHelper_1 = require("./CronExpressionHelper");
|
|
13
|
+
const NotificationManager_1 = require("./NotificationManager");
|
|
14
|
+
(0, scheduling_engine_base_1.LoadBaseSchedulingEngine)(); // Ensure extended entities are loaded
|
|
15
|
+
/**
|
|
16
|
+
* Engine for managing scheduled job execution
|
|
17
|
+
*
|
|
18
|
+
* This engine extends SchedulingEngineBase with execution capabilities:
|
|
19
|
+
* - Evaluates cron expressions to determine which jobs are due
|
|
20
|
+
* - Instantiates the appropriate plugin for each job type
|
|
21
|
+
* - Executes jobs and tracks results in ScheduledJobRun
|
|
22
|
+
* - Sends notifications based on job configuration
|
|
23
|
+
* - Updates job statistics (RunCount, SuccessCount, FailureCount)
|
|
24
|
+
* - Manages distributed locking for multi-server environments
|
|
25
|
+
*
|
|
26
|
+
* @description ONLY USE ON SERVER-SIDE. For metadata only, use SchedulingEngineBase which can be used anywhere.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const engine = SchedulingEngine.Instance;
|
|
31
|
+
* await engine.Config(false, contextUser);
|
|
32
|
+
* const runs = await engine.ExecuteScheduledJobs(contextUser);
|
|
33
|
+
* console.log(`Executed ${runs.length} scheduled jobs`);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
class SchedulingEngine extends scheduling_engine_base_1.SchedulingEngineBase {
|
|
37
|
+
constructor() {
|
|
38
|
+
super(...arguments);
|
|
39
|
+
this.isPolling = false;
|
|
40
|
+
this.hasInitialized = false;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get singleton instance
|
|
44
|
+
*/
|
|
45
|
+
static get Instance() {
|
|
46
|
+
return super.getInstance();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Start continuous polling for scheduled jobs
|
|
50
|
+
* Uses adaptive interval based on ActivePollingInterval
|
|
51
|
+
*
|
|
52
|
+
* @param contextUser - User context for execution
|
|
53
|
+
*/
|
|
54
|
+
StartPolling(contextUser) {
|
|
55
|
+
if (this.isPolling) {
|
|
56
|
+
this.log('Polling already started');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.isPolling = true;
|
|
60
|
+
const poll = async () => {
|
|
61
|
+
// Initialize NextRunAt and clean up stale locks on first poll only
|
|
62
|
+
if (!this.hasInitialized) {
|
|
63
|
+
await this.initializeNextRunTimes(contextUser);
|
|
64
|
+
await this.cleanupStaleLocks(contextUser);
|
|
65
|
+
// Force reload after cleaning locks to ensure we have fresh data
|
|
66
|
+
await this.Config(true, contextUser);
|
|
67
|
+
this.hasInitialized = true;
|
|
68
|
+
// Check if there are no jobs after initialization
|
|
69
|
+
if (this.ScheduledJobs.length === 0) {
|
|
70
|
+
console.log(`📅 Scheduled Jobs: No active jobs found, stopping polling`);
|
|
71
|
+
this.StopPolling();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const runs = await this.ExecuteScheduledJobs(contextUser);
|
|
77
|
+
// Only log if jobs were actually executed
|
|
78
|
+
if (runs.length > 0) {
|
|
79
|
+
console.log(`📅 Scheduled Jobs: Executed ${runs.length} job(s)`);
|
|
80
|
+
}
|
|
81
|
+
// Schedule next poll based on current ActivePollingInterval
|
|
82
|
+
if (this.isPolling) {
|
|
83
|
+
const interval = this.ActivePollingInterval;
|
|
84
|
+
// If interval is null (no jobs), stop polling
|
|
85
|
+
if (interval === null) {
|
|
86
|
+
console.log(`📅 Scheduled Jobs: All jobs removed, stopping polling`);
|
|
87
|
+
this.StopPolling();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.pollingTimer = setTimeout(poll, interval);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
this.logError('Error during polling', error);
|
|
95
|
+
// Continue polling even after errors
|
|
96
|
+
if (this.isPolling) {
|
|
97
|
+
this.pollingTimer = setTimeout(poll, 60000); // Fallback to 1 minute
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
// Start first poll immediately
|
|
102
|
+
poll();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Stop continuous polling
|
|
106
|
+
*/
|
|
107
|
+
StopPolling() {
|
|
108
|
+
if (!this.isPolling) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this.isPolling = false;
|
|
112
|
+
if (this.pollingTimer) {
|
|
113
|
+
clearTimeout(this.pollingTimer);
|
|
114
|
+
this.pollingTimer = undefined;
|
|
115
|
+
}
|
|
116
|
+
this.log('Stopped scheduled job polling');
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Check if polling is currently active
|
|
120
|
+
*/
|
|
121
|
+
get IsPolling() {
|
|
122
|
+
return this.isPolling;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Handle job changes (create, update, delete)
|
|
126
|
+
* Reloads job metadata and restarts polling if needed
|
|
127
|
+
*
|
|
128
|
+
* This method is called automatically by ScheduledJobEntityExtended.Save() and Delete()
|
|
129
|
+
*
|
|
130
|
+
* @param contextUser - User context for reloading metadata
|
|
131
|
+
*/
|
|
132
|
+
async OnJobChanged(contextUser) {
|
|
133
|
+
// Reload jobs from database
|
|
134
|
+
await this.Config(true, contextUser);
|
|
135
|
+
// Recalculate polling interval
|
|
136
|
+
this.UpdatePollingInterval();
|
|
137
|
+
// If polling is stopped and we now have jobs, restart it
|
|
138
|
+
if (!this.isPolling && this.ScheduledJobs.length > 0) {
|
|
139
|
+
console.log(`📅 Scheduled Jobs: Jobs detected, starting polling`);
|
|
140
|
+
this.StartPolling(contextUser);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Execute all scheduled jobs that are currently due
|
|
145
|
+
*
|
|
146
|
+
* Evaluates each active job's cron expression against the current time.
|
|
147
|
+
* Jobs that are due are executed via their plugin's Execute method.
|
|
148
|
+
*
|
|
149
|
+
* @param contextUser - User context for execution
|
|
150
|
+
* @param evalTime - Optional time to evaluate against (defaults to now)
|
|
151
|
+
* @returns Array of scheduled job run records
|
|
152
|
+
*/
|
|
153
|
+
async ExecuteScheduledJobs(contextUser, evalTime = new Date()) {
|
|
154
|
+
await this.Config(false, contextUser);
|
|
155
|
+
console.log(`📅 Polling: Checking ${this.ScheduledJobs.length} job(s) at ${evalTime.toISOString()}`);
|
|
156
|
+
const runs = [];
|
|
157
|
+
for (const job of this.ScheduledJobs) {
|
|
158
|
+
console.log(` - ${job.Name}: NextRunAt=${job.NextRunAt?.toISOString() || 'NULL'}, Status=${job.Status}`);
|
|
159
|
+
if (this.isJobDue(job, evalTime)) {
|
|
160
|
+
console.log(` ✓ Job is due, executing...`);
|
|
161
|
+
try {
|
|
162
|
+
const run = await this.executeJob(job, contextUser);
|
|
163
|
+
if (run) { // null if skipped
|
|
164
|
+
runs.push(run);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
console.log(` ⊘ Job was skipped (locked or queued)`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
this.logError(`Failed to execute job ${job.Name}`, error);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
console.log(` ⊗ Job is not due yet`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Recalculate polling interval after each poll cycle
|
|
179
|
+
// This ensures we adapt to the narrowest active job schedule
|
|
180
|
+
this.UpdatePollingInterval();
|
|
181
|
+
return runs;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Execute a specific scheduled job by ID
|
|
185
|
+
*
|
|
186
|
+
* @param jobId - ID of the job to execute
|
|
187
|
+
* @param contextUser - User context for execution
|
|
188
|
+
* @returns The scheduled job run record
|
|
189
|
+
*/
|
|
190
|
+
async ExecuteScheduledJob(jobId, contextUser) {
|
|
191
|
+
await this.Config(false, contextUser);
|
|
192
|
+
const job = this.ScheduledJobs.find(j => j.ID === jobId);
|
|
193
|
+
if (!job) {
|
|
194
|
+
throw new Error(`Scheduled job ${jobId} not found or not active`);
|
|
195
|
+
}
|
|
196
|
+
return await this.executeJob(job, contextUser);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Determine if a job is currently due for execution
|
|
200
|
+
*
|
|
201
|
+
* @param job - The scheduled job
|
|
202
|
+
* @param evalTime - Time to evaluate against
|
|
203
|
+
* @returns True if the job should execute now
|
|
204
|
+
* @private
|
|
205
|
+
*/
|
|
206
|
+
isJobDue(job, evalTime) {
|
|
207
|
+
// Check date range
|
|
208
|
+
if (job.StartAt && evalTime < job.StartAt) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
if (job.EndAt && evalTime > job.EndAt) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
// Check if NextRunAt is set and has passed
|
|
215
|
+
if (!job.NextRunAt) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
// Job is due if NextRunAt is in the past or very close to now (within 1 second tolerance)
|
|
219
|
+
return job.NextRunAt.getTime() <= evalTime.getTime() + 1000;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Execute a single scheduled job
|
|
223
|
+
*
|
|
224
|
+
* @param job - The job to execute
|
|
225
|
+
* @param contextUser - User context
|
|
226
|
+
* @returns The created job run record
|
|
227
|
+
* @private
|
|
228
|
+
*/
|
|
229
|
+
async executeJob(job, contextUser) {
|
|
230
|
+
// Try to acquire lock for this job
|
|
231
|
+
const lockAcquired = await this.tryAcquireLock(job);
|
|
232
|
+
if (!lockAcquired) {
|
|
233
|
+
// Handle based on concurrency mode
|
|
234
|
+
if (job.ConcurrencyMode === 'Skip') {
|
|
235
|
+
this.log(`Job ${job.Name} is locked, skipping (ConcurrencyMode=Skip)`);
|
|
236
|
+
return null; // Skip this execution
|
|
237
|
+
}
|
|
238
|
+
else if (job.ConcurrencyMode === 'Queue') {
|
|
239
|
+
this.log(`Job ${job.Name} is locked, queueing (ConcurrencyMode=Queue)`);
|
|
240
|
+
// Create a queued run record for future processing
|
|
241
|
+
return await this.createQueuedJobRun(job, contextUser);
|
|
242
|
+
}
|
|
243
|
+
// Concurrent mode: proceed without lock
|
|
244
|
+
}
|
|
245
|
+
// Create run record
|
|
246
|
+
const run = await this.createJobRun(job, contextUser);
|
|
247
|
+
try {
|
|
248
|
+
// Get job type
|
|
249
|
+
const jobType = this.ScheduledJobTypes.find(t => t.ID === job.JobTypeID);
|
|
250
|
+
if (!jobType) {
|
|
251
|
+
throw new Error(`Job type ${job.JobTypeID} not found`);
|
|
252
|
+
}
|
|
253
|
+
// Instantiate plugin using ClassFactory
|
|
254
|
+
const plugin = global_1.MJGlobal.Instance.ClassFactory.CreateInstance(BaseScheduledJob_1.BaseScheduledJob, jobType.DriverClass);
|
|
255
|
+
if (!plugin) {
|
|
256
|
+
throw new Error(`Failed to create plugin instance: ${jobType.DriverClass}`);
|
|
257
|
+
}
|
|
258
|
+
// Console log job start
|
|
259
|
+
console.log(` ▶️ Starting: ${job.Name}`);
|
|
260
|
+
// Build execution context
|
|
261
|
+
const context = {
|
|
262
|
+
Schedule: job,
|
|
263
|
+
Run: run,
|
|
264
|
+
ContextUser: contextUser
|
|
265
|
+
};
|
|
266
|
+
// Execute the job via plugin
|
|
267
|
+
const result = await plugin.Execute(context);
|
|
268
|
+
// Update run record with result
|
|
269
|
+
run.CompletedAt = new Date();
|
|
270
|
+
run.Status = result.Success ? 'Completed' : 'Failed';
|
|
271
|
+
run.Success = result.Success;
|
|
272
|
+
run.ErrorMessage = result.ErrorMessage || null;
|
|
273
|
+
run.Details = result.Details ? JSON.stringify(result.Details) : null;
|
|
274
|
+
await run.Save();
|
|
275
|
+
// Update job statistics
|
|
276
|
+
await this.updateJobStatistics(job, result.Success, run.ID);
|
|
277
|
+
// Send notifications if configured
|
|
278
|
+
await this.sendNotificationsIfNeeded(job, context, result, plugin);
|
|
279
|
+
// Console log job completion
|
|
280
|
+
const duration = run.CompletedAt.getTime() - run.StartedAt.getTime();
|
|
281
|
+
const status = result.Success ? '✅' : '❌';
|
|
282
|
+
console.log(` ${status} Completed: ${job.Name} (${duration}ms)`);
|
|
283
|
+
return run;
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
// Update run with failure
|
|
287
|
+
run.CompletedAt = new Date();
|
|
288
|
+
run.Status = 'Failed';
|
|
289
|
+
run.Success = false;
|
|
290
|
+
run.ErrorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
291
|
+
await run.Save();
|
|
292
|
+
// Update job failure count
|
|
293
|
+
await this.updateJobStatistics(job, false, run.ID);
|
|
294
|
+
this.logError(`Job failed: ${job.Name}`, error);
|
|
295
|
+
return run;
|
|
296
|
+
}
|
|
297
|
+
finally {
|
|
298
|
+
// Release lock if we acquired it
|
|
299
|
+
if (lockAcquired) {
|
|
300
|
+
await this.releaseLock(job);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Create a new ScheduledJobRun record
|
|
306
|
+
*
|
|
307
|
+
* @param job - The scheduled job
|
|
308
|
+
* @param contextUser - User context
|
|
309
|
+
* @returns The created run entity
|
|
310
|
+
* @private
|
|
311
|
+
*/
|
|
312
|
+
async createJobRun(job, contextUser) {
|
|
313
|
+
const md = new core_1.Metadata();
|
|
314
|
+
const run = await md.GetEntityObject('MJ: Scheduled Job Runs', contextUser);
|
|
315
|
+
run.ScheduledJobID = job.ID;
|
|
316
|
+
run.ExecutedByUserID = contextUser.ID;
|
|
317
|
+
run.Status = 'Running';
|
|
318
|
+
run.StartedAt = new Date();
|
|
319
|
+
await run.Save();
|
|
320
|
+
return run;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Update job statistics after execution
|
|
324
|
+
*
|
|
325
|
+
* @param job - The scheduled job
|
|
326
|
+
* @param success - Whether the run succeeded
|
|
327
|
+
* @param runId - The run ID
|
|
328
|
+
* @private
|
|
329
|
+
*/
|
|
330
|
+
async updateJobStatistics(job, success, runId) {
|
|
331
|
+
job.RunCount++;
|
|
332
|
+
if (success) {
|
|
333
|
+
job.SuccessCount++;
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
job.FailureCount++;
|
|
337
|
+
}
|
|
338
|
+
job.LastRunAt = new Date();
|
|
339
|
+
job.NextRunAt = CronExpressionHelper_1.CronExpressionHelper.GetNextRunTime(job.CronExpression, job.Timezone);
|
|
340
|
+
await job.Save();
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Send notifications if configured
|
|
344
|
+
*
|
|
345
|
+
* @param job - The scheduled job
|
|
346
|
+
* @param context - Execution context
|
|
347
|
+
* @param result - Execution result
|
|
348
|
+
* @param plugin - The job plugin
|
|
349
|
+
* @private
|
|
350
|
+
*/
|
|
351
|
+
async sendNotificationsIfNeeded(job, context, result, plugin) {
|
|
352
|
+
const shouldNotify = (result.Success && job.NotifyOnSuccess) ||
|
|
353
|
+
(!result.Success && job.NotifyOnFailure);
|
|
354
|
+
if (!shouldNotify) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const recipientUserId = job.NotifyUserID || job.OwnerUserID;
|
|
358
|
+
if (!recipientUserId) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const channels = [];
|
|
362
|
+
if (job.NotifyViaEmail)
|
|
363
|
+
channels.push('Email');
|
|
364
|
+
if (job.NotifyViaInApp)
|
|
365
|
+
channels.push('InApp');
|
|
366
|
+
if (channels.length === 0) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const content = plugin.FormatNotification(context, result);
|
|
370
|
+
await NotificationManager_1.NotificationManager.SendScheduledJobNotification(recipientUserId, content, channels);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Try to acquire a lock for job execution
|
|
374
|
+
* Uses atomic database update to prevent race conditions
|
|
375
|
+
*
|
|
376
|
+
* @param job - The job to lock
|
|
377
|
+
* @returns True if lock acquired, false if already locked
|
|
378
|
+
* @private
|
|
379
|
+
*/
|
|
380
|
+
async tryAcquireLock(job) {
|
|
381
|
+
// Check if already locked and not stale
|
|
382
|
+
console.log(` 🔒 tryAcquireLock: job.LockToken=${job.LockToken?.substring(0, 8) || 'NULL'}, ExpectedCompletionAt=${job.ExpectedCompletionAt?.toISOString() || 'NULL'}`);
|
|
383
|
+
if (job.LockToken != null) {
|
|
384
|
+
const now = new Date();
|
|
385
|
+
console.log(` Lock exists! Checking if stale: ExpectedCompletionAt=${job.ExpectedCompletionAt?.toISOString()}, now=${now.toISOString()}`);
|
|
386
|
+
if (job.ExpectedCompletionAt && now > job.ExpectedCompletionAt) {
|
|
387
|
+
console.log(` → Lock is STALE, cleaning up...`);
|
|
388
|
+
this.log(`Detected stale lock on job ${job.Name}, cleaning up`);
|
|
389
|
+
await this.cleanupStaleLock(job);
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
// Lock is active and not stale
|
|
393
|
+
console.log(` → Lock is ACTIVE (not stale), returning false`);
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
console.log(` → No lock exists, will try to acquire`);
|
|
399
|
+
}
|
|
400
|
+
// Try to acquire lock using BaseEntity Save for proper change tracking
|
|
401
|
+
const lockToken = this.generateGuid();
|
|
402
|
+
const instanceId = this.getInstanceIdentifier();
|
|
403
|
+
const expectedCompletion = new Date(Date.now() + 10 * 60 * 1000); // 10 minutes default
|
|
404
|
+
try {
|
|
405
|
+
// Reload job from database to ensure we have latest state and enable dirty checking
|
|
406
|
+
await job.Load(job.ID);
|
|
407
|
+
// Verify lock is still null after reload (race condition check)
|
|
408
|
+
if (job.LockToken != null) {
|
|
409
|
+
console.log(` ❌ Lock was acquired by another process during reload`);
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
// Set lock fields
|
|
413
|
+
job.LockToken = lockToken;
|
|
414
|
+
job.LockedAt = new Date();
|
|
415
|
+
job.LockedByInstance = instanceId;
|
|
416
|
+
job.ExpectedCompletionAt = expectedCompletion;
|
|
417
|
+
console.log(` → Attempting to save with lock: ${lockToken.substring(0, 8)}...`);
|
|
418
|
+
// Save will use optimistic concurrency - fails if another process updated the record
|
|
419
|
+
const saveResult = await job.Save();
|
|
420
|
+
if (saveResult) {
|
|
421
|
+
console.log(` ✅ Lock acquired successfully!`);
|
|
422
|
+
return true;
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
console.log(` ❌ Save failed - likely race condition with another server`);
|
|
426
|
+
// Clear lock state on failure
|
|
427
|
+
job.LockToken = null;
|
|
428
|
+
job.LockedAt = null;
|
|
429
|
+
job.LockedByInstance = null;
|
|
430
|
+
job.ExpectedCompletionAt = null;
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
this.logError(`Failed to acquire lock for job ${job.Name}`, error);
|
|
436
|
+
// Clear any partial lock state
|
|
437
|
+
job.LockToken = null;
|
|
438
|
+
job.LockedAt = null;
|
|
439
|
+
job.LockedByInstance = null;
|
|
440
|
+
job.ExpectedCompletionAt = null;
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Release a lock after job execution
|
|
446
|
+
*
|
|
447
|
+
* @param job - The job to unlock
|
|
448
|
+
* @private
|
|
449
|
+
*/
|
|
450
|
+
async releaseLock(job) {
|
|
451
|
+
try {
|
|
452
|
+
job.LockToken = null;
|
|
453
|
+
job.LockedAt = null;
|
|
454
|
+
job.LockedByInstance = null;
|
|
455
|
+
job.ExpectedCompletionAt = null;
|
|
456
|
+
await job.Save();
|
|
457
|
+
}
|
|
458
|
+
catch (error) {
|
|
459
|
+
this.logError(`Failed to release lock for job ${job.Name}`, error);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Clean up a stale lock (when ExpectedCompletionAt has passed)
|
|
464
|
+
*
|
|
465
|
+
* @param job - The job with stale lock
|
|
466
|
+
* @private
|
|
467
|
+
*/
|
|
468
|
+
async cleanupStaleLock(job) {
|
|
469
|
+
this.log(`Cleaning up stale lock on job ${job.Name} (locked by ${job.LockedByInstance})`);
|
|
470
|
+
await this.releaseLock(job);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Create a queued job run for later execution
|
|
474
|
+
*
|
|
475
|
+
* @param job - The job to queue
|
|
476
|
+
* @param contextUser - User context
|
|
477
|
+
* @returns The queued run entity
|
|
478
|
+
* @private
|
|
479
|
+
*/
|
|
480
|
+
async createQueuedJobRun(job, contextUser) {
|
|
481
|
+
const md = new core_1.Metadata();
|
|
482
|
+
const run = await md.GetEntityObject('MJ: Scheduled Job Runs', contextUser);
|
|
483
|
+
run.ScheduledJobID = job.ID;
|
|
484
|
+
run.ExecutedByUserID = contextUser.ID;
|
|
485
|
+
run.Status = 'Running'; // Will be picked up by queue processor
|
|
486
|
+
run.QueuedAt = new Date();
|
|
487
|
+
run.StartedAt = new Date();
|
|
488
|
+
await run.Save();
|
|
489
|
+
this.log(`Queued job ${job.Name} for later execution (Run ID: ${run.ID})`);
|
|
490
|
+
return run;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Get unique identifier for this server instance
|
|
494
|
+
*
|
|
495
|
+
* @returns Server instance identifier
|
|
496
|
+
* @private
|
|
497
|
+
*/
|
|
498
|
+
getInstanceIdentifier() {
|
|
499
|
+
// Use hostname + process ID for unique instance identification
|
|
500
|
+
const os = require('os');
|
|
501
|
+
return `${os.hostname()}-${process.pid}`;
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Generate a GUID for lock tokens
|
|
505
|
+
*
|
|
506
|
+
* @returns Generated GUID
|
|
507
|
+
* @private
|
|
508
|
+
*/
|
|
509
|
+
generateGuid() {
|
|
510
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
511
|
+
const r = (Math.random() * 16) | 0;
|
|
512
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
513
|
+
return v.toString(16);
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Initialize NextRunAt for jobs that don't have it set
|
|
518
|
+
* @param contextUser - User context
|
|
519
|
+
* @private
|
|
520
|
+
*/
|
|
521
|
+
async initializeNextRunTimes(contextUser) {
|
|
522
|
+
for (const job of this.ScheduledJobs) {
|
|
523
|
+
if (!job.NextRunAt) {
|
|
524
|
+
job.NextRunAt = CronExpressionHelper_1.CronExpressionHelper.GetNextRunTime(job.CronExpression, job.Timezone);
|
|
525
|
+
try {
|
|
526
|
+
await job.Save();
|
|
527
|
+
console.log(` ⚙️ Initialized NextRunAt for ${job.Name} -> ${job.NextRunAt.toISOString()}`);
|
|
528
|
+
}
|
|
529
|
+
catch (error) {
|
|
530
|
+
this.logError(`Failed to initialize NextRunAt for job ${job.Name}`, error);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Clean up stale locks on startup
|
|
537
|
+
* Releases any locks that have expired (ExpectedCompletionAt in the past)
|
|
538
|
+
* @param contextUser - User context
|
|
539
|
+
* @private
|
|
540
|
+
*/
|
|
541
|
+
async cleanupStaleLocks(contextUser) {
|
|
542
|
+
const now = new Date();
|
|
543
|
+
let cleanedCount = 0;
|
|
544
|
+
console.log(` 🔍 Checking for stale locks (current time: ${now.toISOString()})...`);
|
|
545
|
+
for (const job of this.ScheduledJobs) {
|
|
546
|
+
if (job.LockToken) {
|
|
547
|
+
console.log(` Job "${job.Name}": LockToken=${job.LockToken?.substring(0, 8)}..., ExpectedCompletionAt=${job.ExpectedCompletionAt?.toISOString() || 'NULL'}`);
|
|
548
|
+
if (job.ExpectedCompletionAt) {
|
|
549
|
+
const isStale = job.ExpectedCompletionAt < now;
|
|
550
|
+
console.log(` → Is stale? ${isStale} (${job.ExpectedCompletionAt.getTime()} < ${now.getTime()} = ${job.ExpectedCompletionAt.getTime() < now.getTime()})`);
|
|
551
|
+
if (isStale) {
|
|
552
|
+
console.log(` 🔓 Cleaning stale lock (locked by ${job.LockedByInstance})`);
|
|
553
|
+
job.LockToken = null;
|
|
554
|
+
job.LockedAt = null;
|
|
555
|
+
job.LockedByInstance = null;
|
|
556
|
+
job.ExpectedCompletionAt = null;
|
|
557
|
+
try {
|
|
558
|
+
await job.Save();
|
|
559
|
+
cleanedCount++;
|
|
560
|
+
}
|
|
561
|
+
catch (error) {
|
|
562
|
+
this.logError(`Failed to clean stale lock for job ${job.Name}`, error);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
console.log(` ⚠️ Lock exists but no ExpectedCompletionAt - clearing anyway`);
|
|
568
|
+
job.LockToken = null;
|
|
569
|
+
job.LockedAt = null;
|
|
570
|
+
job.LockedByInstance = null;
|
|
571
|
+
job.ExpectedCompletionAt = null;
|
|
572
|
+
try {
|
|
573
|
+
await job.Save();
|
|
574
|
+
cleanedCount++;
|
|
575
|
+
}
|
|
576
|
+
catch (error) {
|
|
577
|
+
this.logError(`Failed to clean stale lock for job ${job.Name}`, error);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
if (cleanedCount > 0) {
|
|
583
|
+
console.log(` ✅ Cleaned ${cleanedCount} stale lock(s)`);
|
|
584
|
+
}
|
|
585
|
+
else {
|
|
586
|
+
console.log(` ✓ No stale locks found`);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
log(message) {
|
|
590
|
+
(0, core_1.LogStatusEx)({
|
|
591
|
+
message: `[ScheduledJobEngine] ${message}`,
|
|
592
|
+
verboseOnly: false,
|
|
593
|
+
isVerboseEnabled: () => false
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
logError(message, error) {
|
|
597
|
+
(0, core_1.LogError)(`[ScheduledJobEngine] ${message}`, undefined, error);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
exports.SchedulingEngine = SchedulingEngine;
|
|
601
|
+
//# sourceMappingURL=ScheduledJobEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScheduledJobEngine.js","sourceRoot":"","sources":["../src/ScheduledJobEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Driver for executing scheduled Action jobs
|
|
3
|
+
* @module @memberjunction/scheduling-engine
|
|
4
|
+
*/
|
|
5
|
+
import { BaseScheduledJob, ScheduledJobExecutionContext } from '../BaseScheduledJob';
|
|
6
|
+
import { ValidationResult } from '@memberjunction/core';
|
|
7
|
+
import { ScheduledJobResult, NotificationContent } from '@memberjunction/scheduling-base-types';
|
|
8
|
+
/**
|
|
9
|
+
* Driver for executing scheduled Action jobs
|
|
10
|
+
*
|
|
11
|
+
* Configuration schema (stored in ScheduledJob.Configuration):
|
|
12
|
+
* {
|
|
13
|
+
* ActionID: string,
|
|
14
|
+
* Params?: Array<{
|
|
15
|
+
* ActionParamID: string,
|
|
16
|
+
* ValueType: 'Static' | 'SQL Statement',
|
|
17
|
+
* Value: string
|
|
18
|
+
* }>
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* Execution result details (stored in ScheduledJobRun.Details):
|
|
22
|
+
* {
|
|
23
|
+
* ResultCode: string,
|
|
24
|
+
* IsSuccess: boolean,
|
|
25
|
+
* OutputParams?: any
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
export declare class ActionScheduledJobDriver extends BaseScheduledJob {
|
|
29
|
+
Execute(context: ScheduledJobExecutionContext): Promise<ScheduledJobResult>;
|
|
30
|
+
ValidateConfiguration(schedule: any): ValidationResult;
|
|
31
|
+
FormatNotification(context: ScheduledJobExecutionContext, result: ScheduledJobResult): NotificationContent;
|
|
32
|
+
private processParams;
|
|
33
|
+
private executeSQL;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Loader function to ensure this driver is registered
|
|
37
|
+
* Prevents tree-shaking from removing the class
|
|
38
|
+
*/
|
|
39
|
+
export declare function LoadActionScheduledJobDriver(): void;
|
|
40
|
+
//# sourceMappingURL=ActionScheduledJobDriver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionScheduledJobDriver.d.ts","sourceRoot":"","sources":["../../src/drivers/ActionScheduledJobDriver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAgE,MAAM,sBAAsB,CAAC;AAGtH,OAAO,EACH,kBAAkB,EAClB,mBAAmB,EAEtB,MAAM,uCAAuC,CAAC;AAG/C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBACa,wBAAyB,SAAQ,gBAAgB;IAC7C,OAAO,CAAC,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAmCjF,qBAAqB,CAAC,QAAQ,EAAE,GAAG,GAAG,gBAAgB;IA6DtD,kBAAkB,CACrB,OAAO,EAAE,4BAA4B,EACrC,MAAM,EAAE,kBAAkB,GAC3B,mBAAmB;YAyBR,aAAa;YA0Cb,UAAU;CAU3B;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD"}
|