@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.
Files changed (33) hide show
  1. package/dist/BaseScheduledJob.d.ts +122 -0
  2. package/dist/BaseScheduledJob.d.ts.map +1 -0
  3. package/dist/BaseScheduledJob.js +105 -0
  4. package/dist/BaseScheduledJob.js.map +1 -0
  5. package/dist/CronExpressionHelper.d.ts +36 -0
  6. package/dist/CronExpressionHelper.d.ts.map +1 -0
  7. package/dist/CronExpressionHelper.js +106 -0
  8. package/dist/CronExpressionHelper.js.map +1 -0
  9. package/dist/NotificationManager.d.ts +19 -0
  10. package/dist/NotificationManager.d.ts.map +1 -0
  11. package/dist/NotificationManager.js +44 -0
  12. package/dist/NotificationManager.js.map +1 -0
  13. package/dist/ScheduledJobEngine.d.ts +188 -0
  14. package/dist/ScheduledJobEngine.d.ts.map +1 -0
  15. package/dist/ScheduledJobEngine.js +601 -0
  16. package/dist/ScheduledJobEngine.js.map +1 -0
  17. package/dist/drivers/ActionScheduledJobDriver.d.ts +40 -0
  18. package/dist/drivers/ActionScheduledJobDriver.d.ts.map +1 -0
  19. package/dist/drivers/ActionScheduledJobDriver.js +175 -0
  20. package/dist/drivers/ActionScheduledJobDriver.js.map +1 -0
  21. package/dist/drivers/AgentScheduledJobDriver.d.ts +40 -0
  22. package/dist/drivers/AgentScheduledJobDriver.d.ts.map +1 -0
  23. package/dist/drivers/AgentScheduledJobDriver.js +149 -0
  24. package/dist/drivers/AgentScheduledJobDriver.js.map +1 -0
  25. package/dist/drivers/index.d.ts +12 -0
  26. package/dist/drivers/index.d.ts.map +1 -0
  27. package/dist/drivers/index.js +35 -0
  28. package/dist/drivers/index.js.map +1 -0
  29. package/dist/index.d.ts +15 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +38 -0
  32. package/dist/index.js.map +1 -0
  33. package/package.json +31 -0
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @fileoverview Base class for all scheduled job implementations
3
+ * @module @memberjunction/scheduling-engine
4
+ */
5
+ import { ValidationResult, UserInfo } from '@memberjunction/core';
6
+ import { ScheduledJobEntity, ScheduledJobRunEntity, ScheduledJobTypeEntity } from '@memberjunction/core-entities';
7
+ import { ScheduledJobResult, ScheduledJobConfiguration, NotificationContent } from '@memberjunction/scheduling-base-types';
8
+ /**
9
+ * Context passed to job execution
10
+ */
11
+ export interface ScheduledJobExecutionContext {
12
+ Schedule: ScheduledJobEntity;
13
+ Run: ScheduledJobRunEntity;
14
+ ContextUser: UserInfo;
15
+ }
16
+ /**
17
+ * Abstract base class for scheduled job implementations
18
+ *
19
+ * Each ScheduledJobType in the database has a corresponding DriverClass that extends this base.
20
+ * The plugin is responsible for:
21
+ * - Parsing job-specific configuration from the Configuration JSON field
22
+ * - Executing the job with appropriate domain logic
23
+ * - Formatting notifications in a job-appropriate way
24
+ * - Validating job-specific configuration
25
+ *
26
+ * @abstract
27
+ * @example
28
+ * ```typescript
29
+ * @RegisterClass(BaseScheduledJob, 'ScheduledJobAgent')
30
+ * export class ScheduledJobAgent extends BaseScheduledJob {
31
+ * async Execute(context: ScheduledJobExecutionContext): Promise<ScheduledJobResult> {
32
+ * const config = this.parseConfiguration<AgentJobConfiguration>(context.Schedule);
33
+ * const agentRun = await this.runAgent(config, context.ContextUser);
34
+ * return {
35
+ * Success: agentRun.Success ?? false,
36
+ * ErrorMessage: agentRun.ErrorMessage,
37
+ * Details: {
38
+ * AgentRunID: agentRun.ID,
39
+ * TokensUsed: agentRun.TotalTokensUsed,
40
+ * Cost: agentRun.TotalCost
41
+ * }
42
+ * };
43
+ * }
44
+ * }
45
+ * ```
46
+ */
47
+ export declare abstract class BaseScheduledJob {
48
+ /**
49
+ * Execute the scheduled job
50
+ *
51
+ * This is the main entry point for job execution. The plugin should:
52
+ * 1. Parse the Configuration JSON from context.Schedule
53
+ * 2. Perform the job-specific work
54
+ * 3. Return a ScheduledJobResult with Success, ErrorMessage, and Details
55
+ *
56
+ * The Details object will be serialized to JSON and stored in ScheduledJobRun.Details
57
+ *
58
+ * @param context - Execution context including schedule, run record, and user
59
+ * @returns Promise resolving to execution result
60
+ */
61
+ abstract Execute(context: ScheduledJobExecutionContext): Promise<ScheduledJobResult>;
62
+ /**
63
+ * Validate job-specific configuration
64
+ *
65
+ * Called when creating or updating a scheduled job to ensure the Configuration JSON
66
+ * is valid for this job type.
67
+ *
68
+ * @param schedule - The schedule being validated
69
+ * @returns Validation result with any errors or warnings
70
+ */
71
+ abstract ValidateConfiguration(schedule: ScheduledJobEntity): ValidationResult;
72
+ /**
73
+ * Format notification content for job completion
74
+ *
75
+ * Called by the engine when notifications are enabled and should be sent.
76
+ * The plugin can customize the notification based on the job type and execution result.
77
+ *
78
+ * @param context - Execution context
79
+ * @param result - The execution result
80
+ * @returns Notification content
81
+ */
82
+ abstract FormatNotification(context: ScheduledJobExecutionContext, result: ScheduledJobResult): NotificationContent;
83
+ /**
84
+ * Parse and validate the Configuration JSON field
85
+ *
86
+ * Helper method for plugins to parse their configuration with type safety.
87
+ * Throws if configuration is invalid.
88
+ *
89
+ * @template T - The configuration type
90
+ * @param schedule - The schedule containing the configuration
91
+ * @returns Parsed configuration
92
+ * @throws Error if configuration is missing or invalid
93
+ * @protected
94
+ */
95
+ protected parseConfiguration<T extends ScheduledJobConfiguration>(schedule: ScheduledJobEntity): T;
96
+ /**
97
+ * Get the job type entity for this plugin
98
+ *
99
+ * @param schedule - The schedule
100
+ * @param contextUser - User context
101
+ * @returns Promise resolving to the job type entity
102
+ * @protected
103
+ */
104
+ protected getJobType(schedule: ScheduledJobEntity, contextUser: UserInfo): Promise<ScheduledJobTypeEntity>;
105
+ /**
106
+ * Log execution progress
107
+ *
108
+ * @param message - Log message
109
+ * @param verboseOnly - Whether to only log in verbose mode
110
+ * @protected
111
+ */
112
+ protected log(message: string, verboseOnly?: boolean): void;
113
+ /**
114
+ * Log execution error
115
+ *
116
+ * @param message - Error message
117
+ * @param error - Optional error object
118
+ * @protected
119
+ */
120
+ protected logError(message: string, error?: any): void;
121
+ }
122
+ //# sourceMappingURL=BaseScheduledJob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseScheduledJob.d.ts","sourceRoot":"","sources":["../src/BaseScheduledJob.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAkD,gBAAgB,EAAE,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AAC5H,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAClH,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAE3H;;GAEG;AACH,MAAM,WAAW,4BAA4B;IACzC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,GAAG,EAAE,qBAAqB,CAAC;IAC3B,WAAW,EAAE,QAAQ,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,8BAAsB,gBAAgB;IAClC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAEpF;;;;;;;;OAQG;IACH,QAAQ,CAAC,qBAAqB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,gBAAgB;IAE9E;;;;;;;;;OASG;IACH,QAAQ,CAAC,kBAAkB,CACvB,OAAO,EAAE,4BAA4B,EACrC,MAAM,EAAE,kBAAkB,GAC3B,mBAAmB;IAEtB;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,kBAAkB,CAAC,CAAC,SAAS,yBAAyB,EAC5D,QAAQ,EAAE,kBAAkB,GAC7B,CAAC;IAaJ;;;;;;;OAOG;cACa,UAAU,CACtB,QAAQ,EAAE,kBAAkB,EAC5B,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,sBAAsB,CAAC;IAOlC;;;;;;OAMG;IACH,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,GAAE,OAAe,GAAG,IAAI;IAQlE;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,GAAG,IAAI;CAGzD"}
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Base class for all scheduled job implementations
4
+ * @module @memberjunction/scheduling-engine
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.BaseScheduledJob = void 0;
8
+ const core_1 = require("@memberjunction/core");
9
+ /**
10
+ * Abstract base class for scheduled job implementations
11
+ *
12
+ * Each ScheduledJobType in the database has a corresponding DriverClass that extends this base.
13
+ * The plugin is responsible for:
14
+ * - Parsing job-specific configuration from the Configuration JSON field
15
+ * - Executing the job with appropriate domain logic
16
+ * - Formatting notifications in a job-appropriate way
17
+ * - Validating job-specific configuration
18
+ *
19
+ * @abstract
20
+ * @example
21
+ * ```typescript
22
+ * @RegisterClass(BaseScheduledJob, 'ScheduledJobAgent')
23
+ * export class ScheduledJobAgent extends BaseScheduledJob {
24
+ * async Execute(context: ScheduledJobExecutionContext): Promise<ScheduledJobResult> {
25
+ * const config = this.parseConfiguration<AgentJobConfiguration>(context.Schedule);
26
+ * const agentRun = await this.runAgent(config, context.ContextUser);
27
+ * return {
28
+ * Success: agentRun.Success ?? false,
29
+ * ErrorMessage: agentRun.ErrorMessage,
30
+ * Details: {
31
+ * AgentRunID: agentRun.ID,
32
+ * TokensUsed: agentRun.TotalTokensUsed,
33
+ * Cost: agentRun.TotalCost
34
+ * }
35
+ * };
36
+ * }
37
+ * }
38
+ * ```
39
+ */
40
+ class BaseScheduledJob {
41
+ /**
42
+ * Parse and validate the Configuration JSON field
43
+ *
44
+ * Helper method for plugins to parse their configuration with type safety.
45
+ * Throws if configuration is invalid.
46
+ *
47
+ * @template T - The configuration type
48
+ * @param schedule - The schedule containing the configuration
49
+ * @returns Parsed configuration
50
+ * @throws Error if configuration is missing or invalid
51
+ * @protected
52
+ */
53
+ parseConfiguration(schedule) {
54
+ if (!schedule.Configuration) {
55
+ throw new Error(`Configuration is required for job type`);
56
+ }
57
+ try {
58
+ return JSON.parse(schedule.Configuration);
59
+ }
60
+ catch (error) {
61
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
62
+ throw new Error(`Invalid Configuration JSON: ${errorMessage}`);
63
+ }
64
+ }
65
+ /**
66
+ * Get the job type entity for this plugin
67
+ *
68
+ * @param schedule - The schedule
69
+ * @param contextUser - User context
70
+ * @returns Promise resolving to the job type entity
71
+ * @protected
72
+ */
73
+ async getJobType(schedule, contextUser) {
74
+ const md = new core_1.Metadata();
75
+ const jobType = await md.GetEntityObject('MJ: Scheduled Job Types', contextUser);
76
+ await jobType.Load(schedule.JobTypeID);
77
+ return jobType;
78
+ }
79
+ /**
80
+ * Log execution progress
81
+ *
82
+ * @param message - Log message
83
+ * @param verboseOnly - Whether to only log in verbose mode
84
+ * @protected
85
+ */
86
+ log(message, verboseOnly = false) {
87
+ (0, core_1.LogStatusEx)({
88
+ message: `[${this.constructor.name}] ${message}`,
89
+ verboseOnly,
90
+ isVerboseEnabled: () => (0, core_1.IsVerboseLoggingEnabled)()
91
+ });
92
+ }
93
+ /**
94
+ * Log execution error
95
+ *
96
+ * @param message - Error message
97
+ * @param error - Optional error object
98
+ * @protected
99
+ */
100
+ logError(message, error) {
101
+ (0, core_1.LogError)(`[${this.constructor.name}] ${message}`, undefined, error);
102
+ }
103
+ }
104
+ exports.BaseScheduledJob = BaseScheduledJob;
105
+ //# sourceMappingURL=BaseScheduledJob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseScheduledJob.js","sourceRoot":"","sources":["../src/BaseScheduledJob.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+CAA4H;AAa5H;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAsB,gBAAgB;IA0ClC;;;;;;;;;;;OAWG;IACO,kBAAkB,CACxB,QAA4B;QAE5B,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAM,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YAC9E,MAAM,IAAI,KAAK,CAAC,+BAA+B,YAAY,EAAE,CAAC,CAAC;QACnE,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACO,KAAK,CAAC,UAAU,CACtB,QAA4B,EAC5B,WAAqB;QAErB,MAAM,EAAE,GAAG,IAAI,eAAQ,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,eAAe,CAAyB,yBAAyB,EAAE,WAAW,CAAC,CAAC;QACzG,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;;;;OAMG;IACO,GAAG,CAAC,OAAe,EAAE,cAAuB,KAAK;QACvD,IAAA,kBAAW,EAAC;YACR,OAAO,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,OAAO,EAAE;YAChD,WAAW;YACX,gBAAgB,EAAE,GAAG,EAAE,CAAC,IAAA,8BAAuB,GAAE;SACpD,CAAC,CAAC;IACP,CAAC;IAED;;;;;;OAMG;IACO,QAAQ,CAAC,OAAe,EAAE,KAAW;QAC3C,IAAA,eAAQ,EAAC,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACxE,CAAC;CACJ;AAhHD,4CAgHC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @fileoverview Helper utilities for cron expression evaluation
3
+ * @module @memberjunction/scheduling-engine
4
+ */
5
+ import { ValidationResult } from '@memberjunction/core';
6
+ /**
7
+ * Utility class for cron expression parsing and evaluation
8
+ */
9
+ export declare class CronExpressionHelper {
10
+ /**
11
+ * Determine if a cron expression is currently due
12
+ *
13
+ * @param cronExpression - Cron expression string
14
+ * @param timezone - IANA timezone (e.g., 'America/Chicago')
15
+ * @param evalTime - Time to evaluate against
16
+ * @returns True if the expression is due at evalTime
17
+ */
18
+ static IsExpressionDue(cronExpression: string, timezone: string, evalTime: Date): boolean;
19
+ /**
20
+ * Get the next execution time for a cron expression
21
+ *
22
+ * @param cronExpression - Cron expression string
23
+ * @param timezone - IANA timezone
24
+ * @param fromDate - Optional date to calculate from (defaults to now)
25
+ * @returns Next execution date
26
+ */
27
+ static GetNextRunTime(cronExpression: string, timezone: string, fromDate?: Date): Date;
28
+ /**
29
+ * Validate a cron expression
30
+ *
31
+ * @param cronExpression - Cron expression to validate
32
+ * @returns Validation result
33
+ */
34
+ static ValidateExpression(cronExpression: string): ValidationResult;
35
+ }
36
+ //# sourceMappingURL=CronExpressionHelper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CronExpressionHelper.d.ts","sourceRoot":"","sources":["../src/CronExpressionHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAA4C,MAAM,sBAAsB,CAAC;AAElG;;GAEG;AACH,qBAAa,oBAAoB;IAC7B;;;;;;;OAOG;WACW,eAAe,CACzB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,IAAI,GACf,OAAO;IAkBV;;;;;;;OAOG;WACW,cAAc,CACxB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,IAAI,GAChB,IAAI;IAcP;;;;;OAKG;WACW,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB;CA4B7E"}
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Helper utilities for cron expression evaluation
4
+ * @module @memberjunction/scheduling-engine
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || function (mod) {
23
+ if (mod && mod.__esModule) return mod;
24
+ var result = {};
25
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
26
+ __setModuleDefault(result, mod);
27
+ return result;
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.CronExpressionHelper = void 0;
31
+ const cronParser = __importStar(require("cron-parser"));
32
+ const core_1 = require("@memberjunction/core");
33
+ /**
34
+ * Utility class for cron expression parsing and evaluation
35
+ */
36
+ class CronExpressionHelper {
37
+ /**
38
+ * Determine if a cron expression is currently due
39
+ *
40
+ * @param cronExpression - Cron expression string
41
+ * @param timezone - IANA timezone (e.g., 'America/Chicago')
42
+ * @param evalTime - Time to evaluate against
43
+ * @returns True if the expression is due at evalTime
44
+ */
45
+ static IsExpressionDue(cronExpression, timezone, evalTime) {
46
+ try {
47
+ const options = {
48
+ currentDate: evalTime,
49
+ tz: timezone
50
+ };
51
+ const interval = cronParser.parseExpression(cronExpression, options);
52
+ const nextExecution = interval.next().toDate();
53
+ // Job is due if next execution time is before or at current eval time
54
+ return nextExecution <= evalTime;
55
+ }
56
+ catch (error) {
57
+ console.error('Error evaluating cron expression:', error);
58
+ return false;
59
+ }
60
+ }
61
+ /**
62
+ * Get the next execution time for a cron expression
63
+ *
64
+ * @param cronExpression - Cron expression string
65
+ * @param timezone - IANA timezone
66
+ * @param fromDate - Optional date to calculate from (defaults to now)
67
+ * @returns Next execution date
68
+ */
69
+ static GetNextRunTime(cronExpression, timezone, fromDate) {
70
+ try {
71
+ const options = {
72
+ currentDate: fromDate || new Date(),
73
+ tz: timezone
74
+ };
75
+ const interval = cronParser.parseExpression(cronExpression, options);
76
+ return interval.next().toDate();
77
+ }
78
+ catch (error) {
79
+ throw new Error(`Failed to calculate next run time: ${error instanceof Error ? error.message : 'Unknown error'}`);
80
+ }
81
+ }
82
+ /**
83
+ * Validate a cron expression
84
+ *
85
+ * @param cronExpression - Cron expression to validate
86
+ * @returns Validation result
87
+ */
88
+ static ValidateExpression(cronExpression) {
89
+ const result = new core_1.ValidationResult();
90
+ if (!cronExpression || cronExpression.trim().length === 0) {
91
+ result.Errors.push(new core_1.ValidationErrorInfo('CronExpression', 'Cron expression is required', cronExpression, core_1.ValidationErrorType.Failure));
92
+ return result;
93
+ }
94
+ try {
95
+ cronParser.parseExpression(cronExpression);
96
+ result.Success = true;
97
+ }
98
+ catch (error) {
99
+ const errorMessage = error instanceof Error ? error.message : 'Invalid cron expression';
100
+ result.Errors.push(new core_1.ValidationErrorInfo('CronExpression', errorMessage, cronExpression, core_1.ValidationErrorType.Failure));
101
+ }
102
+ return result;
103
+ }
104
+ }
105
+ exports.CronExpressionHelper = CronExpressionHelper;
106
+ //# sourceMappingURL=CronExpressionHelper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CronExpressionHelper.js","sourceRoot":"","sources":["../src/CronExpressionHelper.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,wDAA0C;AAC1C,+CAAkG;AAElG;;GAEG;AACH,MAAa,oBAAoB;IAC7B;;;;;;;OAOG;IACI,MAAM,CAAC,eAAe,CACzB,cAAsB,EACtB,QAAgB,EAChB,QAAc;QAEd,IAAI,CAAC;YACD,MAAM,OAAO,GAAG;gBACZ,WAAW,EAAE,QAAQ;gBACrB,EAAE,EAAE,QAAQ;aACf,CAAC;YAEF,MAAM,QAAQ,GAAG,UAAU,CAAC,eAAe,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YACrE,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;YAE/C,sEAAsE;YACtE,OAAO,aAAa,IAAI,QAAQ,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;YAC1D,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,cAAc,CACxB,cAAsB,EACtB,QAAgB,EAChB,QAAe;QAEf,IAAI,CAAC;YACD,MAAM,OAAO,GAAG;gBACZ,WAAW,EAAE,QAAQ,IAAI,IAAI,IAAI,EAAE;gBACnC,EAAE,EAAE,QAAQ;aACf,CAAC;YAEF,MAAM,QAAQ,GAAG,UAAU,CAAC,eAAe,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YACrE,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,sCAAsC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACtH,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,kBAAkB,CAAC,cAAsB;QACnD,MAAM,MAAM,GAAG,IAAI,uBAAgB,EAAE,CAAC;QAEtC,IAAI,CAAC,cAAc,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,0BAAmB,CACtC,gBAAgB,EAChB,6BAA6B,EAC7B,cAAc,EACd,0BAAmB,CAAC,OAAO,CAC9B,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,IAAI,CAAC;YACD,UAAU,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;YACxF,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,0BAAmB,CACtC,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,0BAAmB,CAAC,OAAO,CAC9B,CAAC,CAAC;QACP,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ;AA3FD,oDA2FC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @fileoverview Notification delivery manager for scheduled jobs
3
+ * @module @memberjunction/scheduling-engine
4
+ */
5
+ import { NotificationContent, NotificationChannel } from '@memberjunction/scheduling-base-types';
6
+ /**
7
+ * Manager for sending notifications about scheduled job execution
8
+ */
9
+ export declare class NotificationManager {
10
+ /**
11
+ * Send a notification about a scheduled job completion
12
+ *
13
+ * @param recipientUserId - User to notify
14
+ * @param content - Notification content
15
+ * @param channels - Delivery channels (Email, InApp)
16
+ */
17
+ static SendScheduledJobNotification(recipientUserId: string, content: NotificationContent, channels: NotificationChannel[]): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=NotificationManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationManager.d.ts","sourceRoot":"","sources":["../src/NotificationManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAEjG;;GAEG;AACH,qBAAa,mBAAmB;IAC5B;;;;;;OAMG;WACiB,4BAA4B,CAC5C,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,mBAAmB,EAAE,GAChC,OAAO,CAAC,IAAI,CAAC;CAyBnB"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Notification delivery manager for scheduled jobs
4
+ * @module @memberjunction/scheduling-engine
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.NotificationManager = void 0;
8
+ const core_1 = require("@memberjunction/core");
9
+ /**
10
+ * Manager for sending notifications about scheduled job execution
11
+ */
12
+ class NotificationManager {
13
+ /**
14
+ * Send a notification about a scheduled job completion
15
+ *
16
+ * @param recipientUserId - User to notify
17
+ * @param content - Notification content
18
+ * @param channels - Delivery channels (Email, InApp)
19
+ */
20
+ static async SendScheduledJobNotification(recipientUserId, content, channels) {
21
+ // TODO: Implement actual notification delivery
22
+ // This will integrate with MJ's notification system once available
23
+ (0, core_1.LogStatus)(`[NotificationManager] Would send notification to user ${recipientUserId}`);
24
+ (0, core_1.LogStatus)(` Subject: ${content.Subject}`);
25
+ (0, core_1.LogStatus)(` Channels: ${channels.join(', ')}`);
26
+ (0, core_1.LogStatus)(` Priority: ${content.Priority}`);
27
+ // Placeholder for future implementation:
28
+ // - Email: Use CommunicationEngine with email provider
29
+ // - InApp: Create InAppNotification entity record
30
+ // For now, just log that we would send it
31
+ for (const channel of channels) {
32
+ switch (channel) {
33
+ case 'Email':
34
+ (0, core_1.LogStatus)(` [Email] Body: ${content.Body.substring(0, 100)}...`);
35
+ break;
36
+ case 'InApp':
37
+ (0, core_1.LogStatus)(` [InApp] Notification created`);
38
+ break;
39
+ }
40
+ }
41
+ }
42
+ }
43
+ exports.NotificationManager = NotificationManager;
44
+ //# sourceMappingURL=NotificationManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationManager.js","sourceRoot":"","sources":["../src/NotificationManager.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+CAA2D;AAG3D;;GAEG;AACH,MAAa,mBAAmB;IAC5B;;;;;;OAMG;IACI,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAC5C,eAAuB,EACvB,OAA4B,EAC5B,QAA+B;QAE/B,+CAA+C;QAC/C,mEAAmE;QAEnE,IAAA,gBAAS,EAAC,yDAAyD,eAAe,EAAE,CAAC,CAAC;QACtF,IAAA,gBAAS,EAAC,cAAc,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3C,IAAA,gBAAS,EAAC,eAAe,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChD,IAAA,gBAAS,EAAC,eAAe,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QAE7C,yCAAyC;QACzC,uDAAuD;QACvD,kDAAkD;QAElD,0CAA0C;QAC1C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC7B,QAAQ,OAAO,EAAE,CAAC;gBACd,KAAK,OAAO;oBACR,IAAA,gBAAS,EAAC,mBAAmB,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;oBAClE,MAAM;gBACV,KAAK,OAAO;oBACR,IAAA,gBAAS,EAAC,gCAAgC,CAAC,CAAC;oBAC5C,MAAM;YACd,CAAC;QACL,CAAC;IACL,CAAC;CACJ;AArCD,kDAqCC"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * @fileoverview Engine for managing and executing scheduled jobs
3
+ * @module @memberjunction/scheduling-engine
4
+ */
5
+ import { UserInfo } from '@memberjunction/core';
6
+ import { ScheduledJobRunEntity } from '@memberjunction/core-entities';
7
+ import { SchedulingEngineBase } from '@memberjunction/scheduling-engine-base';
8
+ /**
9
+ * Engine for managing scheduled job execution
10
+ *
11
+ * This engine extends SchedulingEngineBase with execution capabilities:
12
+ * - Evaluates cron expressions to determine which jobs are due
13
+ * - Instantiates the appropriate plugin for each job type
14
+ * - Executes jobs and tracks results in ScheduledJobRun
15
+ * - Sends notifications based on job configuration
16
+ * - Updates job statistics (RunCount, SuccessCount, FailureCount)
17
+ * - Manages distributed locking for multi-server environments
18
+ *
19
+ * @description ONLY USE ON SERVER-SIDE. For metadata only, use SchedulingEngineBase which can be used anywhere.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const engine = SchedulingEngine.Instance;
24
+ * await engine.Config(false, contextUser);
25
+ * const runs = await engine.ExecuteScheduledJobs(contextUser);
26
+ * console.log(`Executed ${runs.length} scheduled jobs`);
27
+ * ```
28
+ */
29
+ export declare class SchedulingEngine extends SchedulingEngineBase {
30
+ /**
31
+ * Get singleton instance
32
+ */
33
+ static get Instance(): SchedulingEngine;
34
+ private pollingTimer?;
35
+ private isPolling;
36
+ private hasInitialized;
37
+ /**
38
+ * Start continuous polling for scheduled jobs
39
+ * Uses adaptive interval based on ActivePollingInterval
40
+ *
41
+ * @param contextUser - User context for execution
42
+ */
43
+ StartPolling(contextUser: UserInfo): void;
44
+ /**
45
+ * Stop continuous polling
46
+ */
47
+ StopPolling(): void;
48
+ /**
49
+ * Check if polling is currently active
50
+ */
51
+ get IsPolling(): boolean;
52
+ /**
53
+ * Handle job changes (create, update, delete)
54
+ * Reloads job metadata and restarts polling if needed
55
+ *
56
+ * This method is called automatically by ScheduledJobEntityExtended.Save() and Delete()
57
+ *
58
+ * @param contextUser - User context for reloading metadata
59
+ */
60
+ OnJobChanged(contextUser: UserInfo): Promise<void>;
61
+ /**
62
+ * Execute all scheduled jobs that are currently due
63
+ *
64
+ * Evaluates each active job's cron expression against the current time.
65
+ * Jobs that are due are executed via their plugin's Execute method.
66
+ *
67
+ * @param contextUser - User context for execution
68
+ * @param evalTime - Optional time to evaluate against (defaults to now)
69
+ * @returns Array of scheduled job run records
70
+ */
71
+ ExecuteScheduledJobs(contextUser: UserInfo, evalTime?: Date): Promise<ScheduledJobRunEntity[]>;
72
+ /**
73
+ * Execute a specific scheduled job by ID
74
+ *
75
+ * @param jobId - ID of the job to execute
76
+ * @param contextUser - User context for execution
77
+ * @returns The scheduled job run record
78
+ */
79
+ ExecuteScheduledJob(jobId: string, contextUser: UserInfo): Promise<ScheduledJobRunEntity>;
80
+ /**
81
+ * Determine if a job is currently due for execution
82
+ *
83
+ * @param job - The scheduled job
84
+ * @param evalTime - Time to evaluate against
85
+ * @returns True if the job should execute now
86
+ * @private
87
+ */
88
+ private isJobDue;
89
+ /**
90
+ * Execute a single scheduled job
91
+ *
92
+ * @param job - The job to execute
93
+ * @param contextUser - User context
94
+ * @returns The created job run record
95
+ * @private
96
+ */
97
+ private executeJob;
98
+ /**
99
+ * Create a new ScheduledJobRun record
100
+ *
101
+ * @param job - The scheduled job
102
+ * @param contextUser - User context
103
+ * @returns The created run entity
104
+ * @private
105
+ */
106
+ private createJobRun;
107
+ /**
108
+ * Update job statistics after execution
109
+ *
110
+ * @param job - The scheduled job
111
+ * @param success - Whether the run succeeded
112
+ * @param runId - The run ID
113
+ * @private
114
+ */
115
+ private updateJobStatistics;
116
+ /**
117
+ * Send notifications if configured
118
+ *
119
+ * @param job - The scheduled job
120
+ * @param context - Execution context
121
+ * @param result - Execution result
122
+ * @param plugin - The job plugin
123
+ * @private
124
+ */
125
+ private sendNotificationsIfNeeded;
126
+ /**
127
+ * Try to acquire a lock for job execution
128
+ * Uses atomic database update to prevent race conditions
129
+ *
130
+ * @param job - The job to lock
131
+ * @returns True if lock acquired, false if already locked
132
+ * @private
133
+ */
134
+ private tryAcquireLock;
135
+ /**
136
+ * Release a lock after job execution
137
+ *
138
+ * @param job - The job to unlock
139
+ * @private
140
+ */
141
+ private releaseLock;
142
+ /**
143
+ * Clean up a stale lock (when ExpectedCompletionAt has passed)
144
+ *
145
+ * @param job - The job with stale lock
146
+ * @private
147
+ */
148
+ private cleanupStaleLock;
149
+ /**
150
+ * Create a queued job run for later execution
151
+ *
152
+ * @param job - The job to queue
153
+ * @param contextUser - User context
154
+ * @returns The queued run entity
155
+ * @private
156
+ */
157
+ private createQueuedJobRun;
158
+ /**
159
+ * Get unique identifier for this server instance
160
+ *
161
+ * @returns Server instance identifier
162
+ * @private
163
+ */
164
+ private getInstanceIdentifier;
165
+ /**
166
+ * Generate a GUID for lock tokens
167
+ *
168
+ * @returns Generated GUID
169
+ * @private
170
+ */
171
+ private generateGuid;
172
+ /**
173
+ * Initialize NextRunAt for jobs that don't have it set
174
+ * @param contextUser - User context
175
+ * @private
176
+ */
177
+ private initializeNextRunTimes;
178
+ /**
179
+ * Clean up stale locks on startup
180
+ * Releases any locks that have expired (ExpectedCompletionAt in the past)
181
+ * @param contextUser - User context
182
+ * @private
183
+ */
184
+ private cleanupStaleLocks;
185
+ private log;
186
+ private logError;
187
+ }
188
+ //# sourceMappingURL=ScheduledJobEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScheduledJobEngine.d.ts","sourceRoot":"","sources":["../src/ScheduledJobEngine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,QAAQ,EAKX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAsB,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAG1F,OAAO,EAAE,oBAAoB,EAA4B,MAAM,wCAAwC,CAAC;AAOxG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,gBAAiB,SAAQ,oBAAoB;IACtD;;OAEG;IACH,WAAkB,QAAQ,IAAI,gBAAgB,CAE7C;IAED,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,cAAc,CAAkB;IAExC;;;;;OAKG;IACI,YAAY,CAAC,WAAW,EAAE,QAAQ,GAAG,IAAI;IA0DhD;;OAEG;IACI,WAAW,IAAI,IAAI;IAa1B;;OAEG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;;;;;;OAOG;IACU,YAAY,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAc/D;;;;;;;;;OASG;IACU,oBAAoB,CAC7B,WAAW,EAAE,QAAQ,EACrB,QAAQ,GAAE,IAAiB,GAC5B,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAkCnC;;;;;;OAMG;IACU,mBAAmB,CAC5B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,qBAAqB,CAAC;IAWjC;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ;IAkBhB;;;;;;;OAOG;YACW,UAAU;IAgGxB;;;;;;;OAOG;YACW,YAAY;IAmB1B;;;;;;;OAOG;YACW,mBAAmB;IAoBjC;;;;;;;;OAQG;YACW,yBAAyB;IAmCvC;;;;;;;OAOG;YACW,cAAc;IAsE5B;;;;;OAKG;YACW,WAAW;IAYzB;;;;;OAKG;YACW,gBAAgB;IAK9B;;;;;;;OAOG;YACW,kBAAkB;IAqBhC;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAM7B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAQpB;;;;OAIG;YACW,sBAAsB;IAcpC;;;;;OAKG;YACW,iBAAiB;IAkD/B,OAAO,CAAC,GAAG;IAQX,OAAO,CAAC,QAAQ;CAGnB"}