@dbos-inc/dbos-sdk 4.9.6-preview → 4.9.9-preview

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 (50) hide show
  1. package/dist/schemas/system_db_schema.d.ts +9 -0
  2. package/dist/schemas/system_db_schema.d.ts.map +1 -1
  3. package/dist/schemas/system_db_schema.js.map +1 -1
  4. package/dist/src/client.d.ts +26 -0
  5. package/dist/src/client.d.ts.map +1 -1
  6. package/dist/src/client.js +59 -0
  7. package/dist/src/client.js.map +1 -1
  8. package/dist/src/conductor/conductor.d.ts.map +1 -1
  9. package/dist/src/conductor/conductor.js +105 -0
  10. package/dist/src/conductor/conductor.js.map +1 -1
  11. package/dist/src/conductor/protocol.d.ts +83 -1
  12. package/dist/src/conductor/protocol.d.ts.map +1 -1
  13. package/dist/src/conductor/protocol.js +119 -1
  14. package/dist/src/conductor/protocol.js.map +1 -1
  15. package/dist/src/config.d.ts +1 -0
  16. package/dist/src/config.d.ts.map +1 -1
  17. package/dist/src/config.js +3 -0
  18. package/dist/src/config.js.map +1 -1
  19. package/dist/src/datasource.js +1 -1
  20. package/dist/src/datasource.js.map +1 -1
  21. package/dist/src/dbos-executor.d.ts +4 -0
  22. package/dist/src/dbos-executor.d.ts.map +1 -1
  23. package/dist/src/dbos-executor.js +4 -2
  24. package/dist/src/dbos-executor.js.map +1 -1
  25. package/dist/src/dbos.d.ts +28 -4
  26. package/dist/src/dbos.d.ts.map +1 -1
  27. package/dist/src/dbos.js +134 -7
  28. package/dist/src/dbos.js.map +1 -1
  29. package/dist/src/index.d.ts +2 -1
  30. package/dist/src/index.d.ts.map +1 -1
  31. package/dist/src/index.js +2 -2
  32. package/dist/src/index.js.map +1 -1
  33. package/dist/src/scheduler/scheduler.d.ts +18 -35
  34. package/dist/src/scheduler/scheduler.d.ts.map +1 -1
  35. package/dist/src/scheduler/scheduler.js +193 -134
  36. package/dist/src/scheduler/scheduler.js.map +1 -1
  37. package/dist/src/scheduler/scheduler_decorator.d.ts +41 -0
  38. package/dist/src/scheduler/scheduler_decorator.d.ts.map +1 -0
  39. package/dist/src/scheduler/scheduler_decorator.js +172 -0
  40. package/dist/src/scheduler/scheduler_decorator.js.map +1 -0
  41. package/dist/src/sysdb_migrations/internal/migrations.d.ts +3 -1
  42. package/dist/src/sysdb_migrations/internal/migrations.d.ts.map +1 -1
  43. package/dist/src/sysdb_migrations/internal/migrations.js +21 -5
  44. package/dist/src/sysdb_migrations/internal/migrations.js.map +1 -1
  45. package/dist/src/system_database.d.ts +33 -2
  46. package/dist/src/system_database.d.ts.map +1 -1
  47. package/dist/src/system_database.js +145 -4
  48. package/dist/src/system_database.js.map +1 -1
  49. package/dist/tsconfig.tsbuildinfo +1 -1
  50. package/package.json +27 -1
@@ -1,172 +1,231 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ScheduledReceiver = exports.SchedulerMode = void 0;
3
+ exports.backfillSchedule = exports.triggerSchedule = exports.DynamicSchedulerLoop = exports.createScheduleId = exports.toWorkflowSchedule = void 0;
4
+ const serialization_1 = require("../serialization");
5
+ const crypto_1 = require("crypto");
4
6
  const __1 = require("..");
7
+ const decorators_1 = require("../decorators");
5
8
  const utils_1 = require("../utils");
6
9
  const crontab_1 = require("./crontab");
7
- ////
8
- // Configuration
9
- ////
10
- /**
11
- * Choices for scheduler mode for `@DBOS.scheduled` workflows
12
- */
13
- var SchedulerMode;
14
- (function (SchedulerMode) {
15
- /**
16
- * Using `ExactlyOncePerInterval` causes the scheduler to add "make-up work" for any
17
- * schedule slots that occurred when the app was not running
18
- */
19
- SchedulerMode["ExactlyOncePerInterval"] = "ExactlyOncePerInterval";
20
- /**
21
- * Using `ExactlyOncePerIntervalWhenActive` causes the scheduler to run the workflow once
22
- * per interval when the application is active. If the app is not running at a time
23
- * otherwise indicated by the schedule, no workflow will be run.
24
- */
25
- SchedulerMode["ExactlyOncePerIntervalWhenActive"] = "ExactlyOncePerIntervalWhenActive";
26
- })(SchedulerMode || (exports.SchedulerMode = SchedulerMode = {}));
27
- ///////////////////////////
28
- // Scheduler Management
29
- ///////////////////////////
30
- const SCHEDULER_EVENT_SERVICE_NAME = 'dbos.scheduler';
31
- class ScheduledReceiver {
32
- #controller = new AbortController();
33
- #disposables = new Array();
34
- constructor() {
10
+ const dbos_executor_1 = require("../dbos-executor");
11
+ const error_1 = require("../error");
12
+ const workflow_1 = require("../workflow");
13
+ function toWorkflowSchedule(internal, serializer) {
14
+ const context = serializer.parse(internal.context);
15
+ return {
16
+ scheduleId: internal.scheduleId,
17
+ scheduleName: internal.scheduleName,
18
+ workflowName: internal.workflowName,
19
+ workflowClassName: internal.workflowClassName,
20
+ schedule: internal.schedule,
21
+ status: internal.status,
22
+ context,
23
+ };
24
+ }
25
+ exports.toWorkflowSchedule = toWorkflowSchedule;
26
+ function createScheduleId() {
27
+ return (0, crypto_1.randomUUID)();
28
+ }
29
+ exports.createScheduleId = createScheduleId;
30
+ class DynamicSchedulerLoop {
31
+ #mainController = new AbortController();
32
+ #pollingPromise;
33
+ #scheduleLoops = new Map();
34
+ #pollingIntervalMs;
35
+ constructor(pollingIntervalMs) {
36
+ this.#pollingIntervalMs = pollingIntervalMs ?? 30000;
35
37
  __1.DBOS.registerLifecycleCallback(this);
36
38
  }
37
- // eslint-disable-next-line @typescript-eslint/require-await
38
39
  async initialize() {
39
- for (const regOp of __1.DBOS.getAssociatedInfo(SCHEDULER_EVENT_SERVICE_NAME)) {
40
- if (regOp.methodReg.registeredFunction === undefined) {
41
- __1.DBOS.logger.warn(`Scheduled workflow ${regOp.methodReg.className}.${regOp.methodReg.name} is missing registered function; skipping`);
42
- continue;
43
- }
44
- const { crontab, mode, queueName } = regOp.methodConfig;
45
- if (!crontab) {
46
- __1.DBOS.logger.warn(`Scheduled workflow ${regOp.methodReg.className}.${regOp.methodReg.name} is missing crontab; skipping`);
47
- continue;
48
- }
49
- const timeMatcher = new crontab_1.TimeMatcher(crontab);
50
- const promise = ScheduledReceiver.#schedulerLoop(regOp.methodReg, timeMatcher, mode ?? SchedulerMode.ExactlyOncePerIntervalWhenActive, queueName, this.#controller.signal);
51
- this.#disposables.push(promise);
52
- }
40
+ this.#pollingPromise = this.#pollingLoop(this.#mainController.signal);
41
+ await Promise.resolve();
53
42
  }
54
43
  async destroy() {
55
- this.#controller.abort();
56
- const promises = this.#disposables.splice(0);
57
- await Promise.allSettled(promises);
44
+ this.#mainController.abort();
45
+ // Abort all per-schedule loops
46
+ for (const entry of this.#scheduleLoops.values()) {
47
+ entry.controller.abort();
48
+ }
49
+ const allPromises = [];
50
+ if (this.#pollingPromise) {
51
+ allPromises.push(this.#pollingPromise);
52
+ }
53
+ for (const entry of this.#scheduleLoops.values()) {
54
+ allPromises.push(entry.promise);
55
+ }
56
+ await Promise.allSettled(allPromises);
57
+ this.#scheduleLoops.clear();
58
58
  }
59
- logRegisteredEndpoints() {
60
- __1.DBOS.logger.info('Scheduled endpoints:');
61
- for (const regOp of __1.DBOS.getAssociatedInfo(SCHEDULER_EVENT_SERVICE_NAME)) {
62
- const name = `${regOp.methodReg.className}.${regOp.methodReg.name}`;
63
- const { crontab, mode } = regOp.methodConfig;
64
- if (crontab) {
65
- __1.DBOS.logger.info(` ${name} @ ${crontab}; ${mode ?? SchedulerMode.ExactlyOncePerIntervalWhenActive}`);
59
+ async #pollingLoop(signal) {
60
+ while (!signal.aborted) {
61
+ let schedules;
62
+ try {
63
+ const executor = dbos_executor_1.DBOSExecutor.globalInstance;
64
+ schedules = await executor.systemDatabase.listSchedules();
65
+ }
66
+ catch (e) {
67
+ __1.DBOS.logger.warn(`Dynamic scheduler: error listing schedules: ${e.message}`);
68
+ await DynamicSchedulerLoop.#cancellableSleep(this.#pollingIntervalMs, signal);
69
+ continue;
70
+ }
71
+ // Build set of current schedule names
72
+ const currentNames = new Set(schedules.map((s) => s.scheduleName));
73
+ // Stop loops for deleted schedules
74
+ for (const [name, entry] of this.#scheduleLoops) {
75
+ if (!currentNames.has(name)) {
76
+ entry.controller.abort();
77
+ this.#scheduleLoops.delete(name);
78
+ }
66
79
  }
67
- else {
68
- __1.DBOS.logger.info(` ${name} is missing crontab; skipping`);
80
+ // Process each schedule
81
+ for (const sched of schedules) {
82
+ const existing = this.#scheduleLoops.get(sched.scheduleName);
83
+ if (sched.status === 'PAUSED' && existing) {
84
+ // Paused but has a running loop — stop it
85
+ existing.controller.abort();
86
+ this.#scheduleLoops.delete(sched.scheduleName);
87
+ }
88
+ else if (sched.status === 'ACTIVE') {
89
+ // If schedule was replaced (different scheduleId), restart the loop
90
+ if (existing && existing.scheduleId !== sched.scheduleId) {
91
+ existing.controller.abort();
92
+ this.#scheduleLoops.delete(sched.scheduleName);
93
+ }
94
+ if (!this.#scheduleLoops.has(sched.scheduleName)) {
95
+ // Active and no running loop — start one
96
+ const controller = new AbortController();
97
+ const executor = dbos_executor_1.DBOSExecutor.globalInstance;
98
+ const promise = DynamicSchedulerLoop.#scheduleLoop(sched.scheduleName, sched.workflowName, sched.workflowClassName, sched.schedule, sched.context, executor.serializer, controller.signal);
99
+ this.#scheduleLoops.set(sched.scheduleName, { controller, promise, scheduleId: sched.scheduleId });
100
+ }
101
+ }
69
102
  }
103
+ await DynamicSchedulerLoop.#cancellableSleep(this.#pollingIntervalMs, signal);
70
104
  }
71
105
  }
72
- static async #schedulerLoop(methodReg, timeMatcher, mode, queueName, signal) {
73
- const name = `${methodReg.className}.${methodReg.name}`;
74
- let lastExec = new Date().setMilliseconds(0);
75
- if (mode === SchedulerMode.ExactlyOncePerInterval) {
76
- const lastState = await __1.DBOS.getEventDispatchState(SCHEDULER_EVENT_SERVICE_NAME, name, 'lastState');
77
- if (lastState?.value) {
78
- lastExec = parseFloat(lastState.value);
79
- }
106
+ static async #scheduleLoop(scheduleName, workflowName, workflowClassName, cronExpression, serializedContext, serializer, signal) {
107
+ // Look up the registered workflow function
108
+ const methReg = (0, decorators_1.getFunctionRegistrationByName)(workflowClassName, workflowName);
109
+ if (!methReg || !methReg.registeredFunction) {
110
+ __1.DBOS.logger.warn(`Dynamic scheduler: workflow ${workflowClassName}.${workflowName} for schedule "${scheduleName}" is not registered; skipping`);
111
+ return;
80
112
  }
113
+ const timeMatcher = new crontab_1.TimeMatcher(cronExpression);
114
+ let lastExec = new Date().setMilliseconds(0);
81
115
  while (!signal.aborted) {
82
116
  const nextExec = timeMatcher.nextWakeupTime(lastExec).getTime();
83
117
  let sleepTime = nextExec - Date.now();
84
- // To prevent a "thundering herd" problem in a distributed setting,
85
- // apply jitter of up to 10% the sleep time, capped at 10 seconds
118
+ // Apply jitter to prevent thundering herd
86
119
  if (sleepTime > 0) {
87
120
  const maxJitter = Math.min(sleepTime / 10, 10000);
88
- const jitter = Math.random() * maxJitter;
89
- sleepTime += jitter;
121
+ sleepTime += Math.random() * maxJitter;
90
122
  }
91
123
  if (sleepTime > 0) {
92
- await new Promise((resolve, reject) => {
93
- // eslint-disable-next-line prefer-const
94
- let timeoutID;
95
- const onAbort = () => {
96
- clearTimeout(timeoutID);
97
- reject(new Error('Abort signal received'));
98
- };
99
- signal.addEventListener('abort', onAbort, { once: true });
100
- if (signal.aborted) {
101
- signal.removeEventListener('abort', onAbort);
102
- reject(new Error('Abort signal received'));
103
- }
104
- timeoutID = setTimeout(() => {
105
- signal.removeEventListener('abort', onAbort);
106
- resolve();
107
- }, sleepTime);
108
- });
124
+ await DynamicSchedulerLoop.#cancellableSleep(sleepTime, signal);
109
125
  }
110
126
  if (signal.aborted) {
111
127
  break;
112
128
  }
113
- if (!timeMatcher.match(nextExec)) {
114
- lastExec = nextExec;
115
- continue;
116
- }
117
129
  const date = new Date(nextExec);
118
- if (methodReg.workflowConfig && methodReg.registeredFunction) {
119
- const workflowID = `sched-${name}-${date.toISOString()}`;
120
- const wfParams = { workflowID, queueName: queueName ?? utils_1.INTERNAL_QUEUE_NAME };
121
- __1.DBOS.logger.debug(`Executing scheduled workflow ${workflowID}`);
122
- await __1.DBOS.startWorkflow(methodReg.registeredFunction, wfParams)(date, new Date());
130
+ const workflowID = `sched-${scheduleName}-${date.toISOString()}`;
131
+ try {
132
+ // Idempotency check -- for performance only, not needed for correctness
133
+ const existing = await __1.DBOS.getWorkflowStatus(workflowID);
134
+ if (existing) {
135
+ lastExec = nextExec;
136
+ continue;
137
+ }
138
+ const wfParams = { workflowID, queueName: utils_1.INTERNAL_QUEUE_NAME };
139
+ const context = serializer.parse(serializedContext);
140
+ await __1.DBOS.startWorkflow(methReg.registeredFunction, wfParams)(date, context);
123
141
  }
124
- else {
125
- __1.DBOS.logger.error(`${name} is @scheduled but not a workflow`);
142
+ catch (e) {
143
+ __1.DBOS.logger.warn(`Dynamic scheduler: error firing workflow for schedule "${scheduleName}": ${e.message}`);
126
144
  }
127
- lastExec = await ScheduledReceiver.#setLastExecTime(name, nextExec);
145
+ lastExec = nextExec;
128
146
  }
129
147
  }
130
- static async #setLastExecTime(name, time) {
131
- // Record the time of the wf kicked off
132
- try {
133
- const state = {
134
- service: SCHEDULER_EVENT_SERVICE_NAME,
135
- workflowFnName: name,
136
- key: 'lastState',
137
- value: `${time}`,
138
- updateTime: time,
148
+ static async #cancellableSleep(ms, signal) {
149
+ if (signal.aborted)
150
+ return;
151
+ await new Promise((resolve) => {
152
+ // eslint-disable-next-line prefer-const
153
+ let timeoutID;
154
+ const onAbort = () => {
155
+ clearTimeout(timeoutID);
156
+ resolve();
139
157
  };
140
- const newState = await __1.DBOS.upsertEventDispatchState(state);
141
- const dbTime = parseFloat(newState.value);
142
- if (dbTime && dbTime > time) {
143
- return dbTime;
158
+ signal.addEventListener('abort', onAbort, { once: true });
159
+ if (signal.aborted) {
160
+ signal.removeEventListener('abort', onAbort);
161
+ resolve();
162
+ return;
144
163
  }
145
- }
146
- catch (e) {
147
- // This write is not strictly essential and the scheduler is often the "canary in the coal mine"
148
- // We will simply continue after giving full details.
149
- const err = e;
150
- __1.DBOS.logger.warn(`Scheduler caught an error writing to system DB: ${err.message}`);
151
- __1.DBOS.logger.error(e);
152
- }
153
- return time;
154
- }
155
- // registerScheduled is static so it can be called before an instance is created during DBOS.launch.
156
- // This means we can't use the instance as the external info key for associateFunctionWithInfo below
157
- // or in getAssociatedInfo above...which means we can only have one scheduled receiver instance.
158
- // However, since this is an internal receiver, it's safe to assume there is ever only one instnace.
159
- static registerScheduled(func, config) {
160
- const { regInfo } = __1.DBOS.associateFunctionWithInfo(SCHEDULER_EVENT_SERVICE_NAME, func, {
161
- ctorOrProto: config.ctorOrProto,
162
- className: config.className,
163
- name: config.name ?? func.name,
164
+ timeoutID = setTimeout(() => {
165
+ signal.removeEventListener('abort', onAbort);
166
+ resolve();
167
+ }, ms);
164
168
  });
165
- const schedRegInfo = regInfo;
166
- schedRegInfo.crontab = config.crontab;
167
- schedRegInfo.mode = config.mode;
168
- schedRegInfo.queueName = config.queueName;
169
169
  }
170
170
  }
171
- exports.ScheduledReceiver = ScheduledReceiver;
171
+ exports.DynamicSchedulerLoop = DynamicSchedulerLoop;
172
+ function enqueueScheduledWorkflow(systemDatabase, serializer, sched, workflowID, scheduledDate, context) {
173
+ const serparam = (0, serialization_1.serializeArgs)([scheduledDate, context], undefined, serializer, undefined);
174
+ const internalStatus = {
175
+ workflowUUID: workflowID,
176
+ status: workflow_1.StatusString.ENQUEUED,
177
+ workflowName: sched.workflowName,
178
+ workflowClassName: sched.workflowClassName,
179
+ workflowConfigName: '',
180
+ queueName: utils_1.INTERNAL_QUEUE_NAME,
181
+ authenticatedUser: '',
182
+ output: null,
183
+ error: null,
184
+ assumedRole: '',
185
+ authenticatedRoles: [],
186
+ request: {},
187
+ executorId: '',
188
+ applicationID: '',
189
+ createdAt: Date.now(),
190
+ input: serparam.serializedValue,
191
+ deduplicationID: undefined,
192
+ priority: 0,
193
+ queuePartitionKey: undefined,
194
+ serialization: serparam.serialization,
195
+ };
196
+ return systemDatabase.initWorkflowStatus(internalStatus, null).then(() => { });
197
+ }
198
+ async function triggerSchedule(systemDatabase, serializer, name) {
199
+ const sched = await systemDatabase.getSchedule(name);
200
+ if (!sched) {
201
+ throw new error_1.DBOSError(`Schedule "${name}" not found`);
202
+ }
203
+ const context = serializer.parse(sched.context);
204
+ const now = new Date();
205
+ const workflowID = `sched-${name}-trigger-${now.toISOString()}`;
206
+ await enqueueScheduledWorkflow(systemDatabase, serializer, sched, workflowID, now, context);
207
+ return workflowID;
208
+ }
209
+ exports.triggerSchedule = triggerSchedule;
210
+ async function backfillSchedule(systemDatabase, serializer, name, start, end) {
211
+ const sched = await systemDatabase.getSchedule(name);
212
+ if (!sched) {
213
+ throw new error_1.DBOSError(`Schedule "${name}" not found`);
214
+ }
215
+ const context = serializer.parse(sched.context);
216
+ const timeMatcher = new crontab_1.TimeMatcher(sched.schedule);
217
+ const workflowIDs = [];
218
+ let current = start.getTime();
219
+ while (current < end.getTime()) {
220
+ const next = timeMatcher.nextWakeupTime(current);
221
+ if (next.getTime() >= end.getTime())
222
+ break;
223
+ const workflowID = `sched-${name}-${next.toISOString()}`;
224
+ await enqueueScheduledWorkflow(systemDatabase, serializer, sched, workflowID, next, context);
225
+ workflowIDs.push(workflowID);
226
+ current = next.getTime();
227
+ }
228
+ return workflowIDs;
229
+ }
230
+ exports.backfillSchedule = backfillSchedule;
172
231
  //# sourceMappingURL=scheduler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/scheduler/scheduler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/scheduler/scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { DBOSLifecycleCallback, FunctionName } from '../decorators';
2
+ /**
3
+ * Choices for scheduler mode for `@DBOS.scheduled` workflows
4
+ */
5
+ export declare enum SchedulerMode {
6
+ /**
7
+ * Using `ExactlyOncePerInterval` causes the scheduler to add "make-up work" for any
8
+ * schedule slots that occurred when the app was not running
9
+ */
10
+ ExactlyOncePerInterval = "ExactlyOncePerInterval",
11
+ /**
12
+ * Using `ExactlyOncePerIntervalWhenActive` causes the scheduler to run the workflow once
13
+ * per interval when the application is active. If the app is not running at a time
14
+ * otherwise indicated by the schedule, no workflow will be run.
15
+ */
16
+ ExactlyOncePerIntervalWhenActive = "ExactlyOncePerIntervalWhenActive"
17
+ }
18
+ /**
19
+ * Configuration for a `@DBOS.scheduled` workflow
20
+ */
21
+ export interface SchedulerConfig {
22
+ /** Schedule, in 5- or 6-spot crontab format */
23
+ crontab: string;
24
+ /**
25
+ * Indicates whether or not to retroactively start workflows that were scheduled during
26
+ * times when the app was not running. @see `SchedulerMode`.
27
+ */
28
+ mode?: SchedulerMode;
29
+ /** If set, workflows will be enqueued on the named queue, rather than being started immediately */
30
+ queueName?: string;
31
+ }
32
+ export type ScheduledArgs = [Date, Date];
33
+ export declare class ScheduledReceiver implements DBOSLifecycleCallback {
34
+ #private;
35
+ constructor();
36
+ initialize(): Promise<void>;
37
+ destroy(): Promise<void>;
38
+ logRegisteredEndpoints(): void;
39
+ static registerScheduled<This, Return>(func: (this: This, ...args: ScheduledArgs) => Promise<Return>, config: SchedulerConfig & FunctionName): void;
40
+ }
41
+ //# sourceMappingURL=scheduler_decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler_decorator.d.ts","sourceRoot":"","sources":["../../../src/scheduler/scheduler_decorator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAA0B,MAAM,eAAe,CAAC;AAQ5F;;GAEG;AACH,oBAAY,aAAa;IACvB;;;OAGG;IACH,sBAAsB,2BAA2B;IACjD;;;;OAIG;IACH,gCAAgC,qCAAqC;CACtE;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAOD,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AASzC,qBAAa,iBAAkB,YAAW,qBAAqB;;;IASvD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA6B3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B,sBAAsB,IAAI,IAAI;IAuH9B,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EACnC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,MAAM,CAAC,EAC7D,MAAM,EAAE,eAAe,GAAG,YAAY;CAazC"}
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScheduledReceiver = exports.SchedulerMode = void 0;
4
+ const __1 = require("..");
5
+ const utils_1 = require("../utils");
6
+ const crontab_1 = require("./crontab");
7
+ ////
8
+ // Configuration
9
+ ////
10
+ /**
11
+ * Choices for scheduler mode for `@DBOS.scheduled` workflows
12
+ */
13
+ var SchedulerMode;
14
+ (function (SchedulerMode) {
15
+ /**
16
+ * Using `ExactlyOncePerInterval` causes the scheduler to add "make-up work" for any
17
+ * schedule slots that occurred when the app was not running
18
+ */
19
+ SchedulerMode["ExactlyOncePerInterval"] = "ExactlyOncePerInterval";
20
+ /**
21
+ * Using `ExactlyOncePerIntervalWhenActive` causes the scheduler to run the workflow once
22
+ * per interval when the application is active. If the app is not running at a time
23
+ * otherwise indicated by the schedule, no workflow will be run.
24
+ */
25
+ SchedulerMode["ExactlyOncePerIntervalWhenActive"] = "ExactlyOncePerIntervalWhenActive";
26
+ })(SchedulerMode || (exports.SchedulerMode = SchedulerMode = {}));
27
+ ///////////////////////////
28
+ // Scheduler Management
29
+ ///////////////////////////
30
+ const SCHEDULER_EVENT_SERVICE_NAME = 'dbos.scheduler';
31
+ class ScheduledReceiver {
32
+ #controller = new AbortController();
33
+ #disposables = new Array();
34
+ constructor() {
35
+ __1.DBOS.registerLifecycleCallback(this);
36
+ }
37
+ // eslint-disable-next-line @typescript-eslint/require-await
38
+ async initialize() {
39
+ for (const regOp of __1.DBOS.getAssociatedInfo(SCHEDULER_EVENT_SERVICE_NAME)) {
40
+ if (regOp.methodReg.registeredFunction === undefined) {
41
+ __1.DBOS.logger.warn(`Scheduled workflow ${regOp.methodReg.className}.${regOp.methodReg.name} is missing registered function; skipping`);
42
+ continue;
43
+ }
44
+ const { crontab, mode, queueName } = regOp.methodConfig;
45
+ if (!crontab) {
46
+ __1.DBOS.logger.warn(`Scheduled workflow ${regOp.methodReg.className}.${regOp.methodReg.name} is missing crontab; skipping`);
47
+ continue;
48
+ }
49
+ const timeMatcher = new crontab_1.TimeMatcher(crontab);
50
+ const promise = ScheduledReceiver.#schedulerLoop(regOp.methodReg, timeMatcher, mode ?? SchedulerMode.ExactlyOncePerIntervalWhenActive, queueName, this.#controller.signal);
51
+ this.#disposables.push(promise);
52
+ }
53
+ }
54
+ async destroy() {
55
+ this.#controller.abort();
56
+ const promises = this.#disposables.splice(0);
57
+ await Promise.allSettled(promises);
58
+ }
59
+ logRegisteredEndpoints() {
60
+ __1.DBOS.logger.info('Scheduled endpoints:');
61
+ for (const regOp of __1.DBOS.getAssociatedInfo(SCHEDULER_EVENT_SERVICE_NAME)) {
62
+ const name = `${regOp.methodReg.className}.${regOp.methodReg.name}`;
63
+ const { crontab, mode } = regOp.methodConfig;
64
+ if (crontab) {
65
+ __1.DBOS.logger.info(` ${name} @ ${crontab}; ${mode ?? SchedulerMode.ExactlyOncePerIntervalWhenActive}`);
66
+ }
67
+ else {
68
+ __1.DBOS.logger.info(` ${name} is missing crontab; skipping`);
69
+ }
70
+ }
71
+ }
72
+ static async #schedulerLoop(methodReg, timeMatcher, mode, queueName, signal) {
73
+ const name = `${methodReg.className}.${methodReg.name}`;
74
+ let lastExec = new Date().setMilliseconds(0);
75
+ if (mode === SchedulerMode.ExactlyOncePerInterval) {
76
+ const lastState = await __1.DBOS.getEventDispatchState(SCHEDULER_EVENT_SERVICE_NAME, name, 'lastState');
77
+ if (lastState?.value) {
78
+ lastExec = parseFloat(lastState.value);
79
+ }
80
+ }
81
+ while (!signal.aborted) {
82
+ const nextExec = timeMatcher.nextWakeupTime(lastExec).getTime();
83
+ let sleepTime = nextExec - Date.now();
84
+ // To prevent a "thundering herd" problem in a distributed setting,
85
+ // apply jitter of up to 10% the sleep time, capped at 10 seconds
86
+ if (sleepTime > 0) {
87
+ const maxJitter = Math.min(sleepTime / 10, 10000);
88
+ const jitter = Math.random() * maxJitter;
89
+ sleepTime += jitter;
90
+ }
91
+ if (sleepTime > 0) {
92
+ await new Promise((resolve, reject) => {
93
+ // eslint-disable-next-line prefer-const
94
+ let timeoutID;
95
+ const onAbort = () => {
96
+ clearTimeout(timeoutID);
97
+ reject(new Error('Abort signal received'));
98
+ };
99
+ signal.addEventListener('abort', onAbort, { once: true });
100
+ if (signal.aborted) {
101
+ signal.removeEventListener('abort', onAbort);
102
+ reject(new Error('Abort signal received'));
103
+ }
104
+ timeoutID = setTimeout(() => {
105
+ signal.removeEventListener('abort', onAbort);
106
+ resolve();
107
+ }, sleepTime);
108
+ });
109
+ }
110
+ if (signal.aborted) {
111
+ break;
112
+ }
113
+ if (!timeMatcher.match(nextExec)) {
114
+ lastExec = nextExec;
115
+ continue;
116
+ }
117
+ const date = new Date(nextExec);
118
+ if (methodReg.workflowConfig && methodReg.registeredFunction) {
119
+ const workflowID = `sched-${name}-${date.toISOString()}`;
120
+ const wfParams = { workflowID, queueName: queueName ?? utils_1.INTERNAL_QUEUE_NAME };
121
+ __1.DBOS.logger.debug(`Executing scheduled workflow ${workflowID}`);
122
+ await __1.DBOS.startWorkflow(methodReg.registeredFunction, wfParams)(date, new Date());
123
+ }
124
+ else {
125
+ __1.DBOS.logger.error(`${name} is @scheduled but not a workflow`);
126
+ }
127
+ lastExec = await ScheduledReceiver.#setLastExecTime(name, nextExec);
128
+ }
129
+ }
130
+ static async #setLastExecTime(name, time) {
131
+ // Record the time of the wf kicked off
132
+ try {
133
+ const state = {
134
+ service: SCHEDULER_EVENT_SERVICE_NAME,
135
+ workflowFnName: name,
136
+ key: 'lastState',
137
+ value: `${time}`,
138
+ updateTime: time,
139
+ };
140
+ const newState = await __1.DBOS.upsertEventDispatchState(state);
141
+ const dbTime = parseFloat(newState.value);
142
+ if (dbTime && dbTime > time) {
143
+ return dbTime;
144
+ }
145
+ }
146
+ catch (e) {
147
+ // This write is not strictly essential and the scheduler is often the "canary in the coal mine"
148
+ // We will simply continue after giving full details.
149
+ const err = e;
150
+ __1.DBOS.logger.warn(`Scheduler caught an error writing to system DB: ${err.message}`);
151
+ __1.DBOS.logger.error(e);
152
+ }
153
+ return time;
154
+ }
155
+ // registerScheduled is static so it can be called before an instance is created during DBOS.launch.
156
+ // This means we can't use the instance as the external info key for associateFunctionWithInfo below
157
+ // or in getAssociatedInfo above...which means we can only have one scheduled receiver instance.
158
+ // However, since this is an internal receiver, it's safe to assume there is ever only one instnace.
159
+ static registerScheduled(func, config) {
160
+ const { regInfo } = __1.DBOS.associateFunctionWithInfo(SCHEDULER_EVENT_SERVICE_NAME, func, {
161
+ ctorOrProto: config.ctorOrProto,
162
+ className: config.className,
163
+ name: config.name ?? func.name,
164
+ });
165
+ const schedRegInfo = regInfo;
166
+ schedRegInfo.crontab = config.crontab;
167
+ schedRegInfo.mode = config.mode;
168
+ schedRegInfo.queueName = config.queueName;
169
+ }
170
+ }
171
+ exports.ScheduledReceiver = ScheduledReceiver;
172
+ //# sourceMappingURL=scheduler_decorator.js.map