@memberjunction/scheduling-engine 6.1.0-edge.0 → 6.1.0-edge.2

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/README.md +26 -0
  2. package/dist/MissedRunPolicy.d.ts +51 -0
  3. package/dist/MissedRunPolicy.d.ts.map +1 -0
  4. package/dist/MissedRunPolicy.js +39 -0
  5. package/dist/MissedRunPolicy.js.map +1 -0
  6. package/dist/NotificationManager.d.ts +68 -7
  7. package/dist/NotificationManager.d.ts.map +1 -1
  8. package/dist/NotificationManager.js +126 -26
  9. package/dist/NotificationManager.js.map +1 -1
  10. package/dist/ScheduledJobEngine.d.ts +52 -1
  11. package/dist/ScheduledJobEngine.d.ts.map +1 -1
  12. package/dist/ScheduledJobEngine.js +153 -4
  13. package/dist/ScheduledJobEngine.js.map +1 -1
  14. package/dist/drivers/ActionLogRetentionScheduledJobDriver.d.ts +106 -0
  15. package/dist/drivers/ActionLogRetentionScheduledJobDriver.d.ts.map +1 -0
  16. package/dist/drivers/ActionLogRetentionScheduledJobDriver.js +224 -0
  17. package/dist/drivers/ActionLogRetentionScheduledJobDriver.js.map +1 -0
  18. package/dist/drivers/AgentScheduledJobDriver.d.ts.map +1 -1
  19. package/dist/drivers/AgentScheduledJobDriver.js +16 -0
  20. package/dist/drivers/AgentScheduledJobDriver.js.map +1 -1
  21. package/dist/drivers/UserRoutineDispatcherDriver.d.ts +1 -1
  22. package/dist/drivers/UserRoutineDispatcherDriver.d.ts.map +1 -1
  23. package/dist/drivers/UserRoutineDispatcherDriver.js +1 -1
  24. package/dist/drivers/UserRoutineDispatcherDriver.js.map +1 -1
  25. package/dist/drivers/index.d.ts +1 -0
  26. package/dist/drivers/index.d.ts.map +1 -1
  27. package/dist/drivers/index.js +1 -0
  28. package/dist/drivers/index.js.map +1 -1
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -0
  32. package/dist/index.js.map +1 -1
  33. package/package.json +17 -16
package/README.md CHANGED
@@ -133,6 +133,32 @@ Abstract base class for all job drivers. Provides:
133
133
  |--------|----------|-------------|
134
134
  | `AgentScheduledJobDriver` | Agent | Executes AI agents with configurable conversations and payloads |
135
135
  | `ActionScheduledJobDriver` | Action | Executes MJ Actions with static or SQL-based parameter values |
136
+ | `RecordProcessScheduledJobDriver` | Run Record Process | Runs a `MJ: Record Processes` definition over its scoped record set |
137
+ | `IntegrationSyncScheduledJobDriver` | Integration Sync | Runs an integration's sync on a schedule |
138
+ | `IntegrationDiscoveryScheduledJobDriver` | Integration Discovery | Discovers new integration entities on a schedule |
139
+ | `UserRoutineDispatcherDriver` | User Routine Dispatcher | Dispatches due user routines |
140
+ | `AgentRunSweepScheduledJobDriver` | Agent Run Sweep | Force-fails agent runs orphaned by a dead process |
141
+ | `ActionLogRetentionScheduledJobDriver` | Action Log Retention | Purges expired `MJ: Action Execution Logs` rows, bounded per run |
142
+
143
+ #### Action Log Retention
144
+
145
+ `Action.RetentionPeriod` (days; `NULL` = indefinite) is stamped onto each execution-log row **when the
146
+ run starts**, so retention is decided at write time — editing an action's retention changes what is
147
+ kept going forward rather than retroactively deleting history written under the previous policy.
148
+
149
+ This driver enforces it. It is opt-in like the sweep: shipping the job type activates nothing until
150
+ someone creates a `MJ: Scheduled Job` of it with a cron expression.
151
+
152
+ ```json
153
+ { "DefaultRetentionDays": 90, "MaxDeletesPerRun": 5000 }
154
+ ```
155
+
156
+ Both fields are optional. Omitting `DefaultRetentionDays` means rows with **no** retention are kept
157
+ indefinitely — `NULL` is what the schema calls indefinite, and a purge job that invented a lifetime
158
+ for it would destroy history with nothing left to notice by. `MaxDeletesPerRun` defaults to 5000 so a
159
+ first run against a long-neglected table cannot become an unbounded transaction; the run drains
160
+ oldest-first over successive runs and reports `ReachedCap: true` when it stopped at the ceiling rather
161
+ than because it was finished.
136
162
 
137
163
  ### CronExpressionHelper
138
164
 
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @fileoverview What a scheduled job does about fire times that passed while nothing was running.
3
+ *
4
+ * A scheduler is down sometimes — a deploy, a crash, a machine that slept. When it comes back, a
5
+ * job whose `NextRunAt` is in the past has to answer a question the schema never asked: *should the
6
+ * missed occurrences happen now?* The right answer depends entirely on what the job does, and only
7
+ * its author knows:
8
+ *
9
+ * - A **nightly digest** wants one catch-up run. The latest state is the whole point; running it
10
+ * five times because the server was down five days sends five identical emails.
11
+ * - A **per-period billing snapshot** wants every occurrence. Each period is its own unit of work,
12
+ * and skipping one loses data nothing else will recreate.
13
+ * - A **cache warm** wants none of them. Whatever it was warming is stale anyway; the next scheduled
14
+ * run will do the job.
15
+ *
16
+ * @module @memberjunction/scheduling-engine
17
+ */
18
+ import { MJScheduledJobEntity } from '@memberjunction/core-entities';
19
+ /**
20
+ * Derived from the entity rather than restated, so a CHECK-constraint change flows through instead
21
+ * of silently drifting from a hand-copied union.
22
+ */
23
+ export type MissedRunPolicy = MJScheduledJobEntity['MissedRunPolicy'];
24
+ /** What the engine should do with a job this tick. */
25
+ export type MissedRunDecision =
26
+ /** Run it now. Either it is normally due, or its policy says to catch up. */
27
+ {
28
+ Action: 'Run'; /** Base date for computing the following `NextRunAt`. */
29
+ AdvanceFrom: 'Now' | 'MissedOccurrence';
30
+ }
31
+ /** Do not run; just move `NextRunAt` forward past the occurrences that were missed. */
32
+ | {
33
+ Action: 'SkipAndAdvance';
34
+ };
35
+ /**
36
+ * Decide what to do with a job whose `NextRunAt` has passed.
37
+ *
38
+ * **"Missed" is defined cron-relatively, not by a grace constant.** A run is missed only when
39
+ * *another* occurrence has already come due since the one we are looking at — i.e.
40
+ * `nextOccurrenceAfter(NextRunAt) <= now`. A job that simply came due a few seconds ago has not
41
+ * missed anything; it is just due, and every policy runs it. Defining it with a fixed grace window
42
+ * would misclassify both ends of the range: an every-minute job would look "missed" after a 90-second
43
+ * pause, and a monthly job would look "on time" a week late.
44
+ *
45
+ * @param policy the job's declared policy
46
+ * @param scheduledFor the occurrence being evaluated (`Job.NextRunAt`)
47
+ * @param nextOccurrenceAfterScheduled the following cron occurrence after `scheduledFor`
48
+ * @param now evaluation time
49
+ */
50
+ export declare function DecideMissedRun(policy: MissedRunPolicy, scheduledFor: Date, nextOccurrenceAfterScheduled: Date, now: Date): MissedRunDecision;
51
+ //# sourceMappingURL=MissedRunPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MissedRunPolicy.d.ts","sourceRoot":"","sources":["../src/MissedRunPolicy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;AAEtE,sDAAsD;AACtD,MAAM,MAAM,iBAAiB;AACzB,6EAA6E;AAC3E;IAAE,MAAM,EAAE,KAAK,CAAC,CAAC,yDAAyD;IAAC,WAAW,EAAE,KAAK,GAAG,kBAAkB,CAAA;CAAE;AACtH,uFAAuF;GACrF;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEnC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC3B,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,IAAI,EAClB,4BAA4B,EAAE,IAAI,EAClC,GAAG,EAAE,IAAI,GACV,iBAAiB,CA0BnB"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Decide what to do with a job whose `NextRunAt` has passed.
3
+ *
4
+ * **"Missed" is defined cron-relatively, not by a grace constant.** A run is missed only when
5
+ * *another* occurrence has already come due since the one we are looking at — i.e.
6
+ * `nextOccurrenceAfter(NextRunAt) <= now`. A job that simply came due a few seconds ago has not
7
+ * missed anything; it is just due, and every policy runs it. Defining it with a fixed grace window
8
+ * would misclassify both ends of the range: an every-minute job would look "missed" after a 90-second
9
+ * pause, and a monthly job would look "on time" a week late.
10
+ *
11
+ * @param policy the job's declared policy
12
+ * @param scheduledFor the occurrence being evaluated (`Job.NextRunAt`)
13
+ * @param nextOccurrenceAfterScheduled the following cron occurrence after `scheduledFor`
14
+ * @param now evaluation time
15
+ */
16
+ export function DecideMissedRun(policy, scheduledFor, nextOccurrenceAfterScheduled, now) {
17
+ const missedAnOccurrence = nextOccurrenceAfterScheduled.getTime() <= now.getTime();
18
+ if (!missedAnOccurrence) {
19
+ // Normally due. No policy has anything to say about this case — advancing from `now` is what
20
+ // the engine has always done.
21
+ return { Action: 'Run', AdvanceFrom: 'Now' };
22
+ }
23
+ switch (policy) {
24
+ case 'Skip':
25
+ return { Action: 'SkipAndAdvance' };
26
+ case 'RunAll':
27
+ // Advance from the occurrence just consumed, not from now, so the backlog is walked one
28
+ // occurrence per tick rather than collapsed. That is also what keeps a long outage from
29
+ // firing a week of runs simultaneously — the engine drains at its poll cadence.
30
+ return { Action: 'Run', AdvanceFrom: 'MissedOccurrence' };
31
+ case 'RunOnce':
32
+ default:
33
+ // The default, and what the engine did before this policy existed: run once, then jump
34
+ // to the next future occurrence. Kept as the fallback so an unrecognized value degrades
35
+ // to today's behavior rather than to silence.
36
+ return { Action: 'Run', AdvanceFrom: 'Now' };
37
+ }
38
+ }
39
+ //# sourceMappingURL=MissedRunPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MissedRunPolicy.js","sourceRoot":"","sources":["../src/MissedRunPolicy.ts"],"names":[],"mappings":"AAgCA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAC3B,MAAuB,EACvB,YAAkB,EAClB,4BAAkC,EAClC,GAAS;IAET,MAAM,kBAAkB,GAAG,4BAA4B,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;IAEnF,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACtB,6FAA6F;QAC7F,8BAA8B;QAC9B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IACjD,CAAC;IAED,QAAQ,MAAM,EAAE,CAAC;QACb,KAAK,MAAM;YACP,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QAExC,KAAK,QAAQ;YACT,wFAAwF;YACxF,wFAAwF;YACxF,gFAAgF;YAChF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;QAE9D,KAAK,SAAS,CAAC;QACf;YACI,uFAAuF;YACvF,wFAAwF;YACxF,8CAA8C;YAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IACrD,CAAC;AACL,CAAC"}
@@ -1,19 +1,80 @@
1
1
  /**
2
- * @fileoverview Notification delivery manager for scheduled jobs
2
+ * @fileoverview Notification delivery for scheduled jobs.
3
+ *
4
+ * **Two people have a say in how a job's notification is delivered**, and this class exists to
5
+ * compose them. The person who configured the job chose which channels it may use
6
+ * (`NotifyViaEmail` / `NotifyViaInApp` on the job row); the recipient chose which channels they
7
+ * want (their notification preferences). The delivered set is the intersection — a job cannot add
8
+ * a channel the recipient declined, and a type default cannot add a channel the job never asked
9
+ * for. `NotificationEngine` resolves the recipient's half; the job's half is handed down as
10
+ * `allowedDeliveryChannels`, a ceiling that can only subtract.
11
+ *
12
+ * **Nothing here may throw.** It runs at the tail of job completion, after the run record has been
13
+ * written and the lock released. A notification that fails is an annoyance; a notification that
14
+ * faults the completion path would corrupt run bookkeeping for a job that actually succeeded.
15
+ *
3
16
  * @module @memberjunction/scheduling-engine
4
17
  */
18
+ import { type IMetadataProvider, type UserInfo } from '@memberjunction/core';
5
19
  import { NotificationContent, NotificationChannel } from '@memberjunction/scheduling-base-types';
6
20
  /**
7
- * Manager for sending notifications about scheduled job execution
21
+ * The seeded `MJ: User Notification Types` row scheduled-job notifications are delivered under.
22
+ * Pinned by name rather than ID so an instance that re-seeded metadata still resolves; a rename
23
+ * would silently drop every job notification to the raw fallback, so the integration tier pins it.
24
+ */
25
+ export declare const SCHEDULED_JOB_NOTIFICATION_TYPE = "Scheduled Job";
26
+ /** Everything needed to deliver one job's completion notice. */
27
+ export type ScheduledJobNotificationParams = {
28
+ /** Who hears about it — the job's NotifyUser, or its owner. */
29
+ RecipientUserID: string;
30
+ /** Subject/body/priority, formatted by the job's own plugin via `FormatNotification`. */
31
+ Content: NotificationContent;
32
+ /** The channels the JOB asked for. Acts as a ceiling, never an escalation. */
33
+ Channels: NotificationChannel[];
34
+ ContextUser: UserInfo;
35
+ /** Deep-link context, so clicking the notification lands on the job that produced it. */
36
+ ScheduledJobID?: string;
37
+ ScheduledJobRunID?: string;
38
+ /**
39
+ * The provider the job ran under. Threaded rather than resolved globally so a server hosting
40
+ * more than one connection notifies through the same one the job read its data from.
41
+ */
42
+ Provider?: IMetadataProvider;
43
+ };
44
+ /**
45
+ * Delivers notifications about scheduled job execution.
8
46
  */
9
47
  export declare class NotificationManager {
10
48
  /**
11
- * Send a notification about a scheduled job completion
49
+ * Send a notification about a scheduled job completion.
50
+ *
51
+ * Delivery goes through `NotificationEngine`, which honors the recipient's per-type
52
+ * preferences and handles email/SMS templating. When the engine cannot deliver at all — the
53
+ * type is not seeded in this instance, the engine is unavailable — an in-app notification is
54
+ * written directly, but only if the job asked for in-app; falling back onto a channel the job
55
+ * did not request would be worse than not delivering.
56
+ *
57
+ * A recipient who has *opted out* is not a failure and does not trigger the fallback.
12
58
  *
13
- * @param recipientUserId - User to notify
14
- * @param content - Notification content
15
- * @param channels - Delivery channels (Email, InApp)
59
+ * @returns true when at least one channel actually delivered.
60
+ */
61
+ static SendScheduledJobNotification(params: ScheduledJobNotificationParams): Promise<boolean>;
62
+ /**
63
+ * Translate the job's channel toggles into a ceiling.
64
+ *
65
+ * A channel the job did not list is explicitly `false` — the ceiling has to be closed, not
66
+ * merely silent, or a type default would deliver on a channel nobody asked for. SMS is always
67
+ * closed: a scheduled job has no way to request it today, so leaving it open would let a type
68
+ * default text someone about a nightly sync.
69
+ */
70
+ private static channelCeiling;
71
+ /** Deep-link context stored on the notification, so it can navigate back to the run. */
72
+ private static buildResourceConfiguration;
73
+ /**
74
+ * Write an in-app notification row directly — the minimal, always-available path when the
75
+ * engine is not usable. Deliberately does not set `NotificationTypeID`: the reason we are here
76
+ * is that the type could not be resolved.
16
77
  */
17
- static SendScheduledJobNotification(recipientUserId: string, content: NotificationContent, channels: NotificationChannel[]): Promise<void>;
78
+ private static deliverInAppDirect;
18
79
  }
19
80
  //# sourceMappingURL=NotificationManager.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"NotificationManager.d.ts","sourceRoot":"","sources":["../src/NotificationManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAiC,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAG5G,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAEjG;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,kBAAkB,CAAC;AAE/D,gEAAgE;AAChE,MAAM,MAAM,8BAA8B,GAAG;IACzC,+DAA+D;IAC/D,eAAe,EAAE,MAAM,CAAC;IACxB,yFAAyF;IACzF,OAAO,EAAE,mBAAmB,CAAC;IAC7B,8EAA8E;IAC9E,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,WAAW,EAAE,QAAQ,CAAC;IACtB,yFAAyF;IACzF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAEF;;GAEG;AACH,qBAAa,mBAAmB;IAC5B;;;;;;;;;;;;OAYG;WACiB,4BAA4B,CAAC,MAAM,EAAE,8BAA8B,GAAG,OAAO,CAAC,OAAO,CAAC;IAmD1G;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAQ7B,wFAAwF;IACxF,OAAO,CAAC,MAAM,CAAC,0BAA0B;IAWzC;;;;OAIG;mBACkB,kBAAkB;CA8B1C"}
@@ -1,39 +1,139 @@
1
1
  /**
2
- * @fileoverview Notification delivery manager for scheduled jobs
2
+ * @fileoverview Notification delivery for scheduled jobs.
3
+ *
4
+ * **Two people have a say in how a job's notification is delivered**, and this class exists to
5
+ * compose them. The person who configured the job chose which channels it may use
6
+ * (`NotifyViaEmail` / `NotifyViaInApp` on the job row); the recipient chose which channels they
7
+ * want (their notification preferences). The delivered set is the intersection — a job cannot add
8
+ * a channel the recipient declined, and a type default cannot add a channel the job never asked
9
+ * for. `NotificationEngine` resolves the recipient's half; the job's half is handed down as
10
+ * `allowedDeliveryChannels`, a ceiling that can only subtract.
11
+ *
12
+ * **Nothing here may throw.** It runs at the tail of job completion, after the run record has been
13
+ * written and the lock released. A notification that fails is an annoyance; a notification that
14
+ * faults the completion path would corrupt run bookkeeping for a job that actually succeeded.
15
+ *
3
16
  * @module @memberjunction/scheduling-engine
4
17
  */
5
- import { LogStatus } from '@memberjunction/core';
18
+ import { LogError, LogStatus, Metadata } from '@memberjunction/core';
19
+ import { NotificationEngine } from '@memberjunction/notifications';
6
20
  /**
7
- * Manager for sending notifications about scheduled job execution
21
+ * The seeded `MJ: User Notification Types` row scheduled-job notifications are delivered under.
22
+ * Pinned by name rather than ID so an instance that re-seeded metadata still resolves; a rename
23
+ * would silently drop every job notification to the raw fallback, so the integration tier pins it.
24
+ */
25
+ export const SCHEDULED_JOB_NOTIFICATION_TYPE = 'Scheduled Job';
26
+ /**
27
+ * Delivers notifications about scheduled job execution.
8
28
  */
9
29
  export class NotificationManager {
10
30
  /**
11
- * Send a notification about a scheduled job completion
31
+ * Send a notification about a scheduled job completion.
32
+ *
33
+ * Delivery goes through `NotificationEngine`, which honors the recipient's per-type
34
+ * preferences and handles email/SMS templating. When the engine cannot deliver at all — the
35
+ * type is not seeded in this instance, the engine is unavailable — an in-app notification is
36
+ * written directly, but only if the job asked for in-app; falling back onto a channel the job
37
+ * did not request would be worse than not delivering.
12
38
  *
13
- * @param recipientUserId - User to notify
14
- * @param content - Notification content
15
- * @param channels - Delivery channels (Email, InApp)
39
+ * A recipient who has *opted out* is not a failure and does not trigger the fallback.
40
+ *
41
+ * @returns true when at least one channel actually delivered.
16
42
  */
17
- static async SendScheduledJobNotification(recipientUserId, content, channels) {
18
- // TODO: Implement actual notification delivery
19
- // This will integrate with MJ's notification system once available
20
- LogStatus(`[NotificationManager] Would send notification to user ${recipientUserId}`);
21
- LogStatus(` Subject: ${content.Subject}`);
22
- LogStatus(` Channels: ${channels.join(', ')}`);
23
- LogStatus(` Priority: ${content.Priority}`);
24
- // Placeholder for future implementation:
25
- // - Email: Use CommunicationEngine with email provider
26
- // - InApp: Create InAppNotification entity record
27
- // For now, just log that we would send it
28
- for (const channel of channels) {
29
- switch (channel) {
30
- case 'Email':
31
- LogStatus(` [Email] Body: ${content.Body.substring(0, 100)}...`);
32
- break;
33
- case 'InApp':
34
- LogStatus(` [InApp] Notification created`);
35
- break;
43
+ static async SendScheduledJobNotification(params) {
44
+ const { RecipientUserID, Content, Channels, ContextUser } = params;
45
+ if (!RecipientUserID || !Channels?.length) {
46
+ return false;
47
+ }
48
+ const ceiling = this.channelCeiling(Channels);
49
+ const resourceConfiguration = this.buildResourceConfiguration(params);
50
+ try {
51
+ await NotificationEngine.Instance.Config(false, ContextUser, params.Provider);
52
+ const result = await NotificationEngine.Instance.SendNotification({
53
+ userId: RecipientUserID,
54
+ typeNameOrId: SCHEDULED_JOB_NOTIFICATION_TYPE,
55
+ title: Content.Subject,
56
+ message: Content.Body,
57
+ resourceConfiguration,
58
+ templateData: {
59
+ subject: Content.Subject,
60
+ body: Content.Body,
61
+ priority: Content.Priority,
62
+ scheduledJobId: params.ScheduledJobID ?? '',
63
+ scheduledJobRunId: params.ScheduledJobRunID ?? '',
64
+ ...(Content.Metadata ?? {}),
65
+ },
66
+ allowedDeliveryChannels: ceiling,
67
+ }, ContextUser);
68
+ if (result.success) {
69
+ const { inApp, email, sms } = result.deliveryChannels;
70
+ // All-false here means the recipient opted out (or the type disables every
71
+ // channel). That is a decision, not a failure — no fallback.
72
+ return inApp || email || sms;
36
73
  }
74
+ LogStatus(`[NotificationManager] NotificationEngine could not deliver "${Content.Subject}" ` +
75
+ `(${(result.errors ?? []).join('; ') || 'no detail'})${ceiling.inApp ? ' — writing an in-app notification directly' : ''}`);
76
+ }
77
+ catch (error) {
78
+ const message = error instanceof Error ? error.message : String(error);
79
+ LogStatus(`[NotificationManager] NotificationEngine unavailable (${message})` +
80
+ `${ceiling.inApp ? ' — writing an in-app notification directly' : ''}`);
81
+ }
82
+ // Only in-app has a fallback: it is a single row this class can write itself. Email and SMS
83
+ // need a configured communication provider, which is exactly what was unavailable above.
84
+ return ceiling.inApp ? this.deliverInAppDirect(params, resourceConfiguration) : false;
85
+ }
86
+ /**
87
+ * Translate the job's channel toggles into a ceiling.
88
+ *
89
+ * A channel the job did not list is explicitly `false` — the ceiling has to be closed, not
90
+ * merely silent, or a type default would deliver on a channel nobody asked for. SMS is always
91
+ * closed: a scheduled job has no way to request it today, so leaving it open would let a type
92
+ * default text someone about a nightly sync.
93
+ */
94
+ static channelCeiling(channels) {
95
+ return {
96
+ inApp: channels.includes('InApp'),
97
+ email: channels.includes('Email'),
98
+ sms: false,
99
+ };
100
+ }
101
+ /** Deep-link context stored on the notification, so it can navigate back to the run. */
102
+ static buildResourceConfiguration(params) {
103
+ const config = { type: 'ScheduledJob' };
104
+ if (params.ScheduledJobID) {
105
+ config.scheduledJobId = params.ScheduledJobID;
106
+ }
107
+ if (params.ScheduledJobRunID) {
108
+ config.scheduledJobRunId = params.ScheduledJobRunID;
109
+ }
110
+ return config;
111
+ }
112
+ /**
113
+ * Write an in-app notification row directly — the minimal, always-available path when the
114
+ * engine is not usable. Deliberately does not set `NotificationTypeID`: the reason we are here
115
+ * is that the type could not be resolved.
116
+ */
117
+ static async deliverInAppDirect(params, resourceConfiguration) {
118
+ try {
119
+ const provider = params.Provider ?? Metadata.Provider;
120
+ const notification = await provider.GetEntityObject('MJ: User Notifications', params.ContextUser);
121
+ notification.NewRecord();
122
+ notification.UserID = params.RecipientUserID;
123
+ notification.Title = params.Content.Subject;
124
+ notification.Message = params.Content.Body;
125
+ notification.Unread = true;
126
+ notification.ResourceConfiguration = JSON.stringify(resourceConfiguration);
127
+ if (await notification.Save()) {
128
+ return true;
129
+ }
130
+ LogError(`[NotificationManager] Direct in-app notification failed for user ${params.RecipientUserID}: ` +
131
+ `${notification.LatestResult?.CompleteMessage ?? 'unknown error'}`);
132
+ return false;
133
+ }
134
+ catch (error) {
135
+ LogError(`[NotificationManager] Direct in-app notification threw for user ${params.RecipientUserID}`, undefined, error);
136
+ return false;
37
137
  }
38
138
  }
39
139
  }
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationManager.js","sourceRoot":"","sources":["../src/NotificationManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAY,MAAM,sBAAsB,CAAC;AAG3D;;GAEG;AACH,MAAM,OAAO,mBAAmB;IAC5B;;;;;;OAMG;IACI,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAC5C,eAAuB,EACvB,OAA4B,EAC5B,QAA+B;QAE/B,+CAA+C;QAC/C,mEAAmE;QAEnE,SAAS,CAAC,yDAAyD,eAAe,EAAE,CAAC,CAAC;QACtF,SAAS,CAAC,cAAc,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3C,SAAS,CAAC,eAAe,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChD,SAAS,CAAC,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,SAAS,CAAC,mBAAmB,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;oBAClE,MAAM;gBACV,KAAK,OAAO;oBACR,SAAS,CAAC,gCAAgC,CAAC,CAAC;oBAC5C,MAAM;YACd,CAAC;QACL,CAAC;IACL,CAAC;CACJ"}
1
+ {"version":3,"file":"NotificationManager.js","sourceRoot":"","sources":["../src/NotificationManager.ts"],"names":[],"mappings":"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"}
@@ -352,7 +352,58 @@ export declare class SchedulingEngine extends BaseSingleton<SchedulingEngine> {
352
352
  */
353
353
  private updateJobStatistics;
354
354
  /**
355
- * Send notifications if configured
355
+ * Apply the job's missed-run policy, advancing past the missed occurrences when it says Skip.
356
+ *
357
+ * Only reached for a job that is already due, so the "merely due" case costs one cron
358
+ * computation and always runs. Whether anything was actually *missed* is decided
359
+ * cron-relatively — a later occurrence has also come due — rather than against a grace window,
360
+ * which would misjudge a per-minute job after a short pause and a monthly job that is a week
361
+ * late in opposite directions.
362
+ *
363
+ * **Synchronous on purpose.** It runs inside the dispatch loop, immediately before lock
364
+ * acquisition; making it async would insert a microtask exactly where ordering against the
365
+ * sweep's fire-and-forget cleanup matters. The decision needs no I/O — only the skip branch
366
+ * writes, and that is awaited separately once the answer is known.
367
+ *
368
+ * @returns true when the job should NOT run this tick.
369
+ */
370
+ private shouldSkipMissedRun;
371
+ /**
372
+ * Move a skipped job past the occurrences it missed, so it rejoins its schedule instead of
373
+ * being re-evaluated as missed on every subsequent poll.
374
+ *
375
+ * Best-effort: a failed advance is logged and retried next tick, never propagated.
376
+ */
377
+ private advancePastMissedRuns;
378
+ /**
379
+ * Move jobs past their `EndAt` to `Status='Expired'`.
380
+ *
381
+ * **`Expired` has always been a declared status that nothing ever set.** `isJobDue` already
382
+ * refuses a job whose `EndAt` has passed, so such a job stops running on its own — but it stays
383
+ * `Active` forever, permanently inert, and keeps counting toward `UpdatePollingInterval`. A
384
+ * one-shot expressed as "cron at T plus `EndAt` just after T" therefore left the whole scheduler
385
+ * polling at that job's cadence for a job that will never run again.
386
+ *
387
+ * That makes this the one-shot story rather than a new schedule shape: "run once at T" is
388
+ * already expressible with the columns that exist, and what was missing was the retirement.
389
+ *
390
+ * Deliberately narrow. It only transitions `Active`/`Pending` — a `Paused` or `Disabled` job was
391
+ * put there by a person, and quietly rewriting their decision to `Expired` would lose it. And it
392
+ * only fires on `EndAt`, never on "the cron has no future occurrence": a cron always has one, so
393
+ * inferring exhaustion would be guessing.
394
+ *
395
+ * Best-effort: a failed transition is logged and retried on the next poll, never propagated —
396
+ * retiring a finished job must not be able to stop live ones from dispatching.
397
+ */
398
+ private expireFinishedJobs;
399
+ /**
400
+ * Send notifications if configured.
401
+ *
402
+ * Runs at the tail of job completion, after the run record is written — so a delivery problem
403
+ * is contained here rather than faulting the bookkeeping of a job that actually succeeded.
404
+ * `NotificationManager` already swallows its own errors; the guard covers the formatting call
405
+ * into plugin code, which does not carry that contract.
406
+ *
356
407
  * @private
357
408
  */
358
409
  private sendNotificationsIfNeeded;
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduledJobEngine.d.ts","sourceRoot":"","sources":["../src/ScheduledJobEngine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EACH,QAAQ,EAER,iBAAiB,EAOpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACxH,OAAO,EAAE,aAAa,EAAwB,MAAM,wBAAwB,CAAC;AAE7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAK9E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,gBAAiB,SAAQ,aAAa,CAAC,gBAAgB,CAAC;IACjE;;OAEG;IACH,WAAkB,QAAQ,IAAI,gBAAgB,CAE7C;IAED;;OAEG;IACH,SAAS,KAAK,IAAI,IAAI,oBAAoB,CAEzC;IAED,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,cAAc,CAAkB;IAExC;;;;;OAKG;IACH,OAAO,CAAC,wBAAwB,CAAC,CAAe;IAEhD;;;OAGG;IACH,OAAO,CAAC,mBAAmB,CAAC,CAAW;IAEvC,4EAA4E;IAC5E,OAAO,CAAC,yBAAyB,CAA0B;IAE3D,mFAAmF;IACnF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mCAAmC,CAAiB;IAO5E;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAiB;IAE9D;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAiB;IAM3D;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB,CAAa;IAEvC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,eAAe,CAA0B;IAEjD;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,mBAAmB,CAAmE;IAE9F;;;;OAIG;IACH,OAAO,CAAC,mBAAmB,CAAiB;IAM5C,oCAAoC;IACpC,IAAW,iBAAiB,IAAI,wBAAwB,EAAE,CAEzD;IAED,oDAAoD;IACpD,IAAW,aAAa,IAAI,oBAAoB,EAAE,CAEjD;IAED,sCAAsC;IACtC,IAAW,gBAAgB,IAAI,uBAAuB,EAAE,CAEvD;IAED,gEAAgE;IAChE,IAAW,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAEhD;IAED;;;OAGG;IACH,IAAW,iBAAiB,IAAI,MAAM,CAErC;IACD,IAAW,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAWzC;IAED;;;;OAIG;IACH,IAAW,cAAc,IAAI,MAAM,CAElC;IACD,IAAW,cAAc,CAAC,KAAK,EAAE,MAAM,EAUtC;IAED;;;;;OAKG;IACH,IAAW,mBAAmB,IAAI,MAAM,CAEvC;IACD,IAAW,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAK3C;IAED,+BAA+B;IACxB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS;IAI3E,uCAAuC;IAChC,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS;IAIzF,uCAAuC;IAChC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,oBAAoB,EAAE;IAI/D,mCAAmC;IAC5B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB,EAAE;IAI9D,wDAAwD;IACjD,qBAAqB,IAAI,IAAI;IAQpC;;;OAGG;IACU,MAAM,CACf,YAAY,CAAC,EAAE,OAAO,EACtB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,WAAW,GAAE,OAAe,EAC5B,cAAc,GAAE,OAAe,GAChC,OAAO,CAAC,OAAO,CAAC;IAQnB;;;;;;;;;;;;;OAaG;IACU,YAAY,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAyE/D;;;;;;;;;;;;OAYG;IACU,WAAW,CAAC,IAAI,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCjG;;OAEG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;;;;;;OAOG;IACU,YAAY,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B/D;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;IAUnC;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAOpC;;;;;;;OAOG;YACW,iBAAiB;IAa/B;;;;;;;OAOG;IACH,OAAO,CAAC,uBAAuB;IAgB/B;;;;;;;OAOG;IACH,OAAO,CAAC,0BAA0B;IA+DlC;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAkBtB;;;;;;;;;OASG;IACU,oBAAoB,CAC7B,WAAW,EAAE,QAAQ,EACrB,QAAQ,GAAE,IAAiB,GAC5B,OAAO,CAAC,uBAAuB,EAAE,CAAC;IA8CrC;;;;;;OAMG;IACU,mBAAmB,CAC5B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,uBAAuB,CAAC;IAmBnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACU,qBAAqB,CAC9B,WAAW,EAAE,QAAQ,EACrB,QAAQ,GAAE,IAAiB,GAC5B,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE,CAAC;IA8D/F;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ;IAkBhB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;YACW,kBAAkB;IA2GhC;;;OAGG;YACW,YAAY;IAoB1B;;;OAGG;YACW,mBAAmB;IAoEjC;;;OAGG;YACW,yBAAyB;IAmCvC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;;OAGG;IACH;;;;;;;;;;;;;OAaG;YACW,cAAc;IAqC5B;;;;;;;;;;OAUG;YACW,yBAAyB;IAsBvC;;;;;;;;;;;;;OAaG;YACW,yBAAyB;IAqBvC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,eAAe;IAqCvB;;;;;;;;;;OAUG;YACW,yBAAyB;IAyCvC;;;;;;;;;;;;;;;;;;;;;OAqBG;YACW,sBAAsB;IA6CpC;;;;;;;;;;;;;;;;;OAiBG;YACW,yBAAyB;IAoCvC;;;;;;;;;;;;;;;;;;;OAmBG;YACW,kBAAkB;IAwChC;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAI7B;;;;;;;;;;OAUG;YACW,sBAAsB;IAyBpC;;;;;;;;;;;;;;;OAeG;YACW,iBAAiB;IAiD/B;;;;;OAKG;IACH,OAAO,CAAC,GAAG;IAOX,OAAO,CAAC,QAAQ;CAGnB"}
1
+ {"version":3,"file":"ScheduledJobEngine.d.ts","sourceRoot":"","sources":["../src/ScheduledJobEngine.ts"],"names":[],"mappings":"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"}