@zukhruf/sqlite-queue 0.0.0-stage → 0.3.42

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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -2
  3. package/dist/activity.d.ts +10 -0
  4. package/dist/activity.d.ts.map +1 -0
  5. package/dist/activity.js +93 -0
  6. package/dist/activity.js.map +1 -0
  7. package/dist/attorney.d.ts +35 -0
  8. package/dist/attorney.d.ts.map +1 -0
  9. package/dist/attorney.js +367 -0
  10. package/dist/attorney.js.map +1 -0
  11. package/dist/claim-timer.d.ts +8 -0
  12. package/dist/claim-timer.d.ts.map +1 -0
  13. package/dist/claim-timer.js +80 -0
  14. package/dist/claim-timer.js.map +1 -0
  15. package/dist/completion-data.d.ts +6 -0
  16. package/dist/completion-data.d.ts.map +1 -0
  17. package/dist/completion-data.js +36 -0
  18. package/dist/completion-data.js.map +1 -0
  19. package/dist/database-error.d.ts +6 -0
  20. package/dist/database-error.d.ts.map +1 -0
  21. package/dist/database-error.js +12 -0
  22. package/dist/database-error.js.map +1 -0
  23. package/dist/database.d.ts +7 -0
  24. package/dist/database.d.ts.map +1 -0
  25. package/dist/database.js +28 -0
  26. package/dist/database.js.map +1 -0
  27. package/dist/in-flight.d.ts +7 -0
  28. package/dist/in-flight.d.ts.map +1 -0
  29. package/dist/in-flight.js +24 -0
  30. package/dist/in-flight.js.map +1 -0
  31. package/dist/index.d.ts +54 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +1069 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/job-fetcher.d.ts +16 -0
  36. package/dist/job-fetcher.d.ts.map +1 -0
  37. package/dist/job-fetcher.js +227 -0
  38. package/dist/job-fetcher.js.map +1 -0
  39. package/dist/job-queue.d.ts +27 -0
  40. package/dist/job-queue.d.ts.map +1 -0
  41. package/dist/job-queue.js +2 -0
  42. package/dist/job-queue.js.map +1 -0
  43. package/dist/job-rows.d.ts +49 -0
  44. package/dist/job-rows.d.ts.map +1 -0
  45. package/dist/job-rows.js +155 -0
  46. package/dist/job-rows.js.map +1 -0
  47. package/dist/job-settler.d.ts +24 -0
  48. package/dist/job-settler.d.ts.map +1 -0
  49. package/dist/job-settler.js +240 -0
  50. package/dist/job-settler.js.map +1 -0
  51. package/dist/jsonb.d.ts +7 -0
  52. package/dist/jsonb.d.ts.map +1 -0
  53. package/dist/jsonb.js +85 -0
  54. package/dist/jsonb.js.map +1 -0
  55. package/dist/local-groups.d.ts +16 -0
  56. package/dist/local-groups.d.ts.map +1 -0
  57. package/dist/local-groups.js +113 -0
  58. package/dist/local-groups.js.map +1 -0
  59. package/dist/naive-timestamp.d.ts +6 -0
  60. package/dist/naive-timestamp.d.ts.map +1 -0
  61. package/dist/naive-timestamp.js +21 -0
  62. package/dist/naive-timestamp.js.map +1 -0
  63. package/dist/queue-cache.d.ts +9 -0
  64. package/dist/queue-cache.d.ts.map +1 -0
  65. package/dist/queue-cache.js +27 -0
  66. package/dist/queue-cache.js.map +1 -0
  67. package/dist/queue-rows.d.ts +25 -0
  68. package/dist/queue-rows.d.ts.map +1 -0
  69. package/dist/queue-rows.js +44 -0
  70. package/dist/queue-rows.js.map +1 -0
  71. package/dist/recurrence.d.ts +11 -0
  72. package/dist/recurrence.d.ts.map +1 -0
  73. package/dist/recurrence.js +226 -0
  74. package/dist/recurrence.js.map +1 -0
  75. package/dist/rows.d.ts +10 -0
  76. package/dist/rows.d.ts.map +1 -0
  77. package/dist/rows.js +46 -0
  78. package/dist/rows.js.map +1 -0
  79. package/dist/schema.d.ts +3 -0
  80. package/dist/schema.d.ts.map +1 -0
  81. package/dist/schema.js +139 -0
  82. package/dist/schema.js.map +1 -0
  83. package/dist/sql-values.d.ts +9 -0
  84. package/dist/sql-values.d.ts.map +1 -0
  85. package/dist/sql-values.js +26 -0
  86. package/dist/sql-values.js.map +1 -0
  87. package/dist/start-after.d.ts +10 -0
  88. package/dist/start-after.d.ts.map +1 -0
  89. package/dist/start-after.js +125 -0
  90. package/dist/start-after.js.map +1 -0
  91. package/dist/supervisor.d.ts +16 -0
  92. package/dist/supervisor.d.ts.map +1 -0
  93. package/dist/supervisor.js +288 -0
  94. package/dist/supervisor.js.map +1 -0
  95. package/dist/throttle.d.ts +6 -0
  96. package/dist/throttle.d.ts.map +1 -0
  97. package/dist/throttle.js +35 -0
  98. package/dist/throttle.js.map +1 -0
  99. package/dist/timekeeper.d.ts +36 -0
  100. package/dist/timekeeper.d.ts.map +1 -0
  101. package/dist/timekeeper.js +305 -0
  102. package/dist/timekeeper.js.map +1 -0
  103. package/dist/timers.d.ts +9 -0
  104. package/dist/timers.d.ts.map +1 -0
  105. package/dist/timers.js +50 -0
  106. package/dist/timers.js.map +1 -0
  107. package/dist/uuid.d.ts +7 -0
  108. package/dist/uuid.d.ts.map +1 -0
  109. package/dist/uuid.js +36 -0
  110. package/dist/uuid.js.map +1 -0
  111. package/dist/worker.d.ts +35 -0
  112. package/dist/worker.d.ts.map +1 -0
  113. package/dist/worker.js +147 -0
  114. package/dist/worker.js.map +1 -0
  115. package/package.json +53 -4
@@ -0,0 +1,125 @@
1
+ // A startAfter string pg-boss would hand to Postgres's own timestamp or
2
+ // interval grammar, outside the subset this queue resolves itself.
3
+ export class UnsupportedStartAfterError extends Error {
4
+ name = 'UnsupportedStartAfterError';
5
+ startAfter;
6
+ constructor(startAfter) {
7
+ super(`startAfter "${startAfter}" is outside the supported forms: a Date, seconds, an ISO 8601 date time or duration, or Postgres interval units with integer amounts`);
8
+ this.startAfter = startAfter;
9
+ }
10
+ }
11
+ // pg-boss normalizes startAfter in Attorney.checkSendArgs
12
+ // (node_modules/pg-boss/dist/attorney.js:108-116, 140-146), then casts a
13
+ // date time string as timestamptz and anything else as an interval added to
14
+ // now (plans.js:2228-2230, 2299-2302). This resolves the same normalization
15
+ // and a cited subset of what Postgres then parses; every supported form is
16
+ // proven equal to pg-boss in the parity suite (src/parity).
17
+ export class StartAfter {
18
+ static #isoDate = /^\d{4}-\d{2}-\d{2}/;
19
+ static #zonelessTime = /^(?:[T ]\d{2}(?::\d{2}(?::\d{2}(?:[.,]\d+)?)?)?)?$/;
20
+ static #dateTime = /^(\d{4}-\d{2}-\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?)?(Z|[+-]\d{2}(?::?\d{2})?)$/;
21
+ static #seconds = /^[+-]?\d+(?:\.\d+)?$/;
22
+ static #isoDuration = /^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/;
23
+ static #unitsShape = /^(?:\d+\s*[a-z]+\s*)+$/i;
24
+ static #unitPairs = /(\d+)\s*([a-z]+)/gi;
25
+ // Postgres interval units with integer amounts, as the field they add to.
26
+ static #unitScales = new Map([
27
+ ...['second', 'seconds', 'sec', 'secs'].map((unit) => [unit, { field: 'milliseconds', size: 1000 }]),
28
+ ...['minute', 'minutes', 'min', 'mins'].map((unit) => [unit, { field: 'milliseconds', size: 60_000 }]),
29
+ ...['hour', 'hours', 'hr', 'hrs'].map((unit) => [unit, { field: 'milliseconds', size: 3_600_000 }]),
30
+ ...['day', 'days'].map((unit) => [unit, { field: 'days', size: 1 }]),
31
+ ...['week', 'weeks'].map((unit) => [unit, { field: 'days', size: 7 }]),
32
+ ...['month', 'months', 'mon', 'mons'].map((unit) => [unit, { field: 'months', size: 1 }]),
33
+ ...['year', 'years', 'yr', 'yrs'].map((unit) => [unit, { field: 'months', size: 12 }]),
34
+ ]);
35
+ static resolve(value, now) {
36
+ const normalized = StartAfter.#normalize(value);
37
+ if (normalized === undefined) {
38
+ return now;
39
+ }
40
+ // Errors name the caller's own value, not its normalized form.
41
+ const original = typeof value === 'string' ? value : normalized;
42
+ // plans.js:2228-2230: a string ending in Z or starting with a date is a
43
+ // timestamp, anything else an interval.
44
+ if (normalized.endsWith('Z') || StartAfter.#isoDate.test(normalized)) {
45
+ return StartAfter.#timestamp(normalized, original);
46
+ }
47
+ return StartAfter.#add(now, StartAfter.#interval(normalized, original));
48
+ }
49
+ // attorney.js:140-146
50
+ static #normalize(value) {
51
+ if (value instanceof Date) {
52
+ return value.toISOString();
53
+ }
54
+ if (Number(value) > 0) {
55
+ return String(value);
56
+ }
57
+ if (typeof value === 'string') {
58
+ // attorney.js:115-117, pinZonelessDateTime.
59
+ return StartAfter.#isoDate.test(value) &&
60
+ StartAfter.#zonelessTime.test(value.slice(10))
61
+ ? `${value}Z`
62
+ : value;
63
+ }
64
+ return undefined;
65
+ }
66
+ static #timestamp(value, original) {
67
+ const match = StartAfter.#dateTime.exec(value);
68
+ if (!match) {
69
+ throw new UnsupportedStartAfterError(original);
70
+ }
71
+ const [, date, hour = '00', minute = '00', second = '00', fraction, zone] = match;
72
+ const offset = zone === undefined || zone === 'Z'
73
+ ? 'Z'
74
+ : `${zone.slice(0, 3)}:${zone.slice(3).replace(':', '') || '00'}`;
75
+ const milliseconds = fraction === undefined ? '' : `.${fraction}`;
76
+ return new Date(`${date}T${hour}:${minute}:${second}${milliseconds}${offset}`);
77
+ }
78
+ static #interval(value, original) {
79
+ const trimmed = value.trim();
80
+ if (StartAfter.#seconds.test(trimmed)) {
81
+ return { months: 0, days: 0, milliseconds: Number(trimmed) * 1000 };
82
+ }
83
+ const duration = StartAfter.#isoDuration.exec(trimmed);
84
+ if (duration && trimmed !== 'P' && !trimmed.endsWith('T')) {
85
+ const [, years, months, weeks, days, hours, minutes, seconds] = duration;
86
+ return {
87
+ months: Number(years ?? 0) * 12 + Number(months ?? 0),
88
+ days: Number(weeks ?? 0) * 7 + Number(days ?? 0),
89
+ milliseconds: Number(hours ?? 0) * 3_600_000 +
90
+ Number(minutes ?? 0) * 60_000 +
91
+ Number(seconds ?? 0) * 1000,
92
+ };
93
+ }
94
+ return StartAfter.#units(trimmed, original);
95
+ }
96
+ static #units(trimmed, original) {
97
+ if (!StartAfter.#unitsShape.test(trimmed)) {
98
+ throw new UnsupportedStartAfterError(original);
99
+ }
100
+ const interval = { months: 0, days: 0, milliseconds: 0 };
101
+ for (const [, amount, unit] of trimmed.matchAll(StartAfter.#unitPairs)) {
102
+ const scale = StartAfter.#unitScales.get(String(unit).toLowerCase());
103
+ if (scale === undefined) {
104
+ throw new UnsupportedStartAfterError(original);
105
+ }
106
+ interval[scale.field] += Number(amount) * scale.size;
107
+ }
108
+ return interval;
109
+ }
110
+ // Postgres adds an interval's months (clamped to the target month's last
111
+ // day), then its days, then its time part.
112
+ static #add(now, interval) {
113
+ const result = new Date(now.getTime());
114
+ if (interval.months !== 0) {
115
+ const day = result.getUTCDate();
116
+ result.setUTCDate(1);
117
+ result.setUTCMonth(result.getUTCMonth() + interval.months);
118
+ const lastDay = new Date(Date.UTC(result.getUTCFullYear(), result.getUTCMonth() + 1, 0)).getUTCDate();
119
+ result.setUTCDate(Math.min(day, lastDay));
120
+ }
121
+ result.setUTCDate(result.getUTCDate() + interval.days);
122
+ return new Date(result.getTime() + interval.milliseconds);
123
+ }
124
+ }
125
+ //# sourceMappingURL=start-after.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-after.js","sourceRoot":"","sources":["../src/start-after.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { DatabaseSync } from 'node:sqlite';
3
+ import type { Clock, PgBossEventMap } from 'pg-boss';
4
+ import type { Activity } from './activity.ts';
5
+ import type { SuperviseIntervals } from './attorney.ts';
6
+ export type SupervisorConfig = SuperviseIntervals & {
7
+ supervise: boolean | undefined;
8
+ warningQueueSize: number | undefined;
9
+ };
10
+ export declare class Supervisor extends EventEmitter<Pick<PgBossEventMap, 'error' | 'warning'>> {
11
+ #private;
12
+ constructor(clock: Clock, activity: Activity, config: SupervisorConfig);
13
+ start(database: DatabaseSync): void;
14
+ stop(): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=supervisor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAKrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AA4BxD,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG;IAClD,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC,CAAC;AAoBF,qBAAa,UAAW,SAAQ,YAAY,CAC1C,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,SAAS,CAAC,CAC1C;;gBAUa,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB;IAUtE,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAa7B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAuU5B"}
@@ -0,0 +1,288 @@
1
+ import assert from 'node:assert';
2
+ import { EventEmitter } from 'node:events';
3
+ import { policies } from 'pg-boss';
4
+ import { transaction } from '@zukhruf/sqlite-transaction';
5
+ import { ClaimTimer } from "./claim-timer.js";
6
+ import { InFlight } from "./in-flight.js";
7
+ import { JobSettler } from "./job-settler.js";
8
+ import { Row } from "./rows.js";
9
+ import { SqlValues } from "./sql-values.js";
10
+ // node_modules/pg-boss/dist/boss.js:14
11
+ const LARGE_QUEUE = { size: 10_000, message: 'Warning: large queue backlog' };
12
+ // The outputs failJobsByTimeout and failJobsByHeartbeat store (plans.js:2376,
13
+ // 2384).
14
+ const TIMED_OUT = JSON.stringify({ value: { message: 'job timed out' } });
15
+ const HEARTBEAT_TIMED_OUT = JSON.stringify({
16
+ value: { message: 'job heartbeat timeout' },
17
+ });
18
+ // A pass works on at most this many queues at a time (boss.js:269).
19
+ const CHUNK = 100;
20
+ // pg-boss's Boss (node_modules/pg-boss/dist/boss.js) for one job table: a
21
+ // pass every superviseIntervalSeconds claims each queue's monitor and
22
+ // maintenance when due, refreshes the monitored queues' counts, warns about
23
+ // backlogs and fails expired and heartbeat-lost jobs, then deletes what the
24
+ // maintained queues no longer keep. Each statement is one Activity.query, so
25
+ // an attached TestClock waits the whole pass out. The pass's Postgres tail
26
+ // (vacuum backoff and check, warning and stats retention, reindex) and
27
+ // cleanupDependencies (no job_dependency table) have no counterpart here.
28
+ export class Supervisor extends EventEmitter {
29
+ #clock;
30
+ #activity;
31
+ #config;
32
+ // boss.js:121
33
+ #largeQueueSize;
34
+ #phase = { kind: 'unstarted' };
35
+ // pg-boss's #maintaining: the pass in flight.
36
+ #pass = null;
37
+ constructor(clock, activity, config) {
38
+ super();
39
+ this.#clock = clock;
40
+ this.#activity = activity;
41
+ this.#config = config;
42
+ this.#largeQueueSize = config.warningQueueSize || LARGE_QUEUE.size;
43
+ }
44
+ // boss.js:128-137: started whether or not supervise is set, which only
45
+ // decides whether the timer is armed.
46
+ start(database) {
47
+ if (this.#phase.kind === 'supervising') {
48
+ return;
49
+ }
50
+ const timer = this.#config.supervise
51
+ ? new ClaimTimer(this.#clock, this.#config.superviseIntervalSeconds, () => this.#onSupervise())
52
+ : null;
53
+ this.#phase = { kind: 'supervising', database, timer };
54
+ }
55
+ // boss.js:138-148, which polls its pass flag every 10 ms of real time.
56
+ async stop() {
57
+ const phase = this.#phase;
58
+ if (phase.kind !== 'supervising') {
59
+ return;
60
+ }
61
+ phase.timer?.stop();
62
+ this.#phase = { kind: 'stopped', database: phase.database };
63
+ await this.#pass?.settled();
64
+ }
65
+ get #stopped() {
66
+ return this.#phase.kind !== 'supervising';
67
+ }
68
+ // boss.js:173-199
69
+ async #onSupervise() {
70
+ if (this.#stopped || this.#pass) {
71
+ return;
72
+ }
73
+ const pass = this.#supervise();
74
+ this.#pass = new InFlight(pass);
75
+ try {
76
+ await pass;
77
+ }
78
+ finally {
79
+ this.#pass = null;
80
+ }
81
+ }
82
+ async #supervise() {
83
+ try {
84
+ const names = await this.#query((db) => Supervisor.#queueNames(db));
85
+ if (!this.#stopped) {
86
+ await this.#supervisePass(names);
87
+ }
88
+ }
89
+ catch (error) {
90
+ this.emit('error', error instanceof Error ? error : new Error(String(error)));
91
+ }
92
+ }
93
+ // boss.js:239-279: the next pass is anchored once every claim is stamped.
94
+ async #supervisePass(names) {
95
+ for (let start = 0; start < names.length; start += CHUNK) {
96
+ if (this.#stopped) {
97
+ return;
98
+ }
99
+ const chunk = names.slice(start, start + CHUNK);
100
+ await this.#monitor(chunk);
101
+ await this.#maintain(chunk);
102
+ }
103
+ if (this.#phase.kind === 'supervising') {
104
+ this.#phase.timer?.anchor();
105
+ }
106
+ }
107
+ // boss.js:293-381. Nothing here backs off the stats, so every claimed
108
+ // queue's counts are refreshed (refreshStats, plans.js:987).
109
+ async #monitor(names) {
110
+ if (this.#stopped) {
111
+ return;
112
+ }
113
+ const claimed = await this.#query((db, now) => Supervisor.#claim(db, names, 'monitor_claim_on', 'COALESCE(monitor_claim_on, monitor_on)', this.#config.monitorIntervalSeconds, now));
114
+ if (this.#stopped || claimed.length === 0) {
115
+ return;
116
+ }
117
+ const stats = await this.#query((db, now) => Supervisor.#cacheQueueStats(db, claimed, now));
118
+ if (this.#stopped) {
119
+ return;
120
+ }
121
+ // boss.js:352-358
122
+ for (const row of stats) {
123
+ const threshold = row.warningQueueSize || this.#largeQueueSize;
124
+ if (row.queuedCount > threshold) {
125
+ this.emit('warning', {
126
+ message: `${LARGE_QUEUE.message}: queue "${row.name}" has ${row.queuedCount} jobs in the ` +
127
+ `created or retry state, over its warning threshold of ${threshold}. Your queue should be reviewed`,
128
+ data: row,
129
+ });
130
+ }
131
+ }
132
+ if (this.#stopped) {
133
+ return;
134
+ }
135
+ const queues = JSON.stringify(claimed);
136
+ // failJobsByTimeout (plans.js:2372-2378)
137
+ await this.#query((db, now) => JobSettler.failJobs(db, [
138
+ `state = 'active'
139
+ AND ${SqlValues.plusSecondsSql('started_on', 'expire_seconds')} < ?
140
+ AND queue_name IN (SELECT value FROM json_each(?))`,
141
+ SqlValues.asIso(now),
142
+ queues,
143
+ ], TIMED_OUT, now));
144
+ if (this.#stopped) {
145
+ return;
146
+ }
147
+ // failJobsByHeartbeat (plans.js:2379-2386)
148
+ await this.#query((db, now) => JobSettler.failJobs(db, [
149
+ `state = 'active'
150
+ AND heartbeat_seconds IS NOT NULL
151
+ AND ${SqlValues.plusSecondsSql('heartbeat_on', 'heartbeat_seconds')} < ?
152
+ AND queue_name IN (SELECT value FROM json_each(?))`,
153
+ SqlValues.asIso(now),
154
+ queues,
155
+ ], HEARTBEAT_TIMED_OUT, now));
156
+ }
157
+ // boss.js:382-396
158
+ async #maintain(names) {
159
+ if (this.#stopped) {
160
+ return;
161
+ }
162
+ const claimed = await this.#query((db, now) => Supervisor.#claim(db, names, 'maintain_on', 'maintain_on', this.#config.maintenanceIntervalSeconds, now));
163
+ if (this.#stopped) {
164
+ return;
165
+ }
166
+ if (claimed.length > 0) {
167
+ await this.#query((db, now) => Supervisor.#deletion(db, claimed, now));
168
+ }
169
+ }
170
+ // A statement on the clock's now, run when issued and settled one counted
171
+ // turn later.
172
+ #query(statement) {
173
+ return this.#activity.query(() => {
174
+ assert(this.#phase.kind !== 'unstarted', 'Database not opened.');
175
+ return statement(this.#phase.database, new Date(this.#clock.now()));
176
+ });
177
+ }
178
+ // getQueues (plans.js:1181-1220) has no ORDER BY; PGlite returns the
179
+ // queues in creation order, which decides each 100-queue chunk.
180
+ static #queueNames(db) {
181
+ return db
182
+ .prepare('SELECT name FROM pgboss_queue ORDER BY rowid')
183
+ .all()
184
+ .map((row) => Row.readString(row, 'name'));
185
+ }
186
+ // trySetQueueMonitorTime and trySetQueueTimestamp (plans.js:973-990,
187
+ // 1119-1137): a queue is due once its stamp is `seconds` old, or at once
188
+ // without one; the due queues are stamped now. pg-boss takes the rows in
189
+ // name order only as a lock order (queueRowLock, 1146-1148) and leaves its
190
+ // RETURNING order to the planner; SQLite's single writer needs no lock
191
+ // order, and name order keeps the pass's warnings in one stable order.
192
+ static #claim(db, names, column, stamp, seconds, now) {
193
+ return transaction(db, () => {
194
+ const due = db
195
+ .prepare(`SELECT name, ${stamp} AS stamp FROM pgboss_queue
196
+ WHERE name IN (SELECT value FROM json_each(?))
197
+ ORDER BY name`)
198
+ .all(JSON.stringify(names))
199
+ .filter((row) => {
200
+ const stamped = Row.readNullableString(row, 'stamp');
201
+ return (stamped === null ||
202
+ (now.getTime() - Date.parse(stamped)) / 1000 >= seconds);
203
+ })
204
+ .map((row) => Row.readString(row, 'name'));
205
+ const update = db.prepare(`UPDATE pgboss_queue SET ${column} = ? WHERE name = ?`);
206
+ for (const name of due) {
207
+ update.run(SqlValues.asIso(now), name);
208
+ }
209
+ return due;
210
+ }, { mode: 'immediate' });
211
+ }
212
+ // cacheQueueStats over getQueueStats (plans.js:3411-3471, 3480-3557): each
213
+ // claimed queue's counts by state, the keys its singleton and stately jobs
214
+ // hold active (NULL for none, as array_agg over no rows) and monitor_on,
215
+ // written and returned in the claim's order.
216
+ static #cacheQueueStats(db, names, now) {
217
+ const started = performance.now();
218
+ const isoNow = SqlValues.asIso(now);
219
+ const queues = JSON.stringify(names);
220
+ return transaction(db, () => {
221
+ const counts = new Map(db
222
+ .prepare(`SELECT queue_name,
223
+ SUM(state IN ('created', 'retry') AND start_after > ?) AS deferred,
224
+ SUM(state IN ('created', 'retry')) AS queued,
225
+ SUM(state = 'active') AS active,
226
+ SUM(state = 'failed') AS failed,
227
+ COUNT(*) AS total
228
+ FROM pgboss_job
229
+ WHERE queue_name IN (SELECT value FROM json_each(?))
230
+ GROUP BY queue_name`)
231
+ .all(isoNow, queues)
232
+ .map((row) => [Row.readString(row, 'queue_name'), row]));
233
+ const singletons = new Map();
234
+ for (const row of db
235
+ .prepare(`SELECT queue_name, singleton_key FROM pgboss_job
236
+ WHERE queue_name IN (SELECT value FROM json_each(?))
237
+ AND state = 'active'
238
+ AND policy IN ('${policies.singleton}', '${policies.stately}')
239
+ ORDER BY rowid`)
240
+ .all(queues)) {
241
+ const name = Row.readString(row, 'queue_name');
242
+ singletons.set(name, [
243
+ ...(singletons.get(name) ?? []),
244
+ Row.readNullableString(row, 'singleton_key'),
245
+ ]);
246
+ }
247
+ const update = db.prepare(`UPDATE pgboss_queue SET
248
+ deferred_count = ?,
249
+ queued_count = ?,
250
+ ready_count = ?,
251
+ active_count = ?,
252
+ failed_count = ?,
253
+ total_count = ?,
254
+ singletons_active = ?,
255
+ monitor_on = ?
256
+ WHERE name = ?
257
+ RETURNING name, queued_count, warning_queue_size`);
258
+ return names.flatMap((name) => {
259
+ const row = counts.get(name);
260
+ const count = (column) => row ? Row.readNumber(row, column) : 0;
261
+ const keys = singletons.get(name);
262
+ const written = update.get(count('deferred'), count('queued'), Math.max(count('queued') - count('deferred'), 0), count('active'), count('failed'), count('total'), keys ? JSON.stringify(keys) : null, isoNow, name);
263
+ return written === undefined
264
+ ? []
265
+ : [
266
+ {
267
+ name: Row.readString(written, 'name'),
268
+ queuedCount: Row.readNumber(written, 'queued_count'),
269
+ warningQueueSize: Row.readNumber(written, 'warning_queue_size'),
270
+ pinSeconds: (performance.now() - started) / 1000,
271
+ },
272
+ ];
273
+ });
274
+ }, { mode: 'immediate' });
275
+ }
276
+ // deletion (plans.js:3055-3066): settled jobs deletion_seconds after they
277
+ // settled, unless that is 0, and jobs never started once past keep_until.
278
+ static #deletion(db, names, now) {
279
+ const isoNow = SqlValues.asIso(now);
280
+ db.prepare(`DELETE FROM pgboss_job
281
+ WHERE queue_name IN (SELECT value FROM json_each(?))
282
+ AND (
283
+ (deletion_seconds > 0 AND ${SqlValues.plusSecondsSql('completed_on', 'deletion_seconds')} < ?)
284
+ OR (state IN ('created', 'retry') AND keep_until < ?)
285
+ )`).run(JSON.stringify(names), isoNow, isoNow);
286
+ }
287
+ }
288
+ //# sourceMappingURL=supervisor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { SendOptions } from 'pg-boss';
2
+ export declare class Throttle {
3
+ static slot(singletonSeconds: SendOptions['singletonSeconds'], offset: SendOptions['singletonSeconds'], now: Date): string | null;
4
+ static debounceStartAfter(singletonSeconds: SendOptions['singletonSeconds'], now: Date): number;
5
+ }
6
+ //# sourceMappingURL=throttle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../src/throttle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAO3C,qBAAa,QAAQ;IAOnB,MAAM,CAAC,IAAI,CACT,gBAAgB,EAAE,WAAW,CAAC,kBAAkB,CAAC,EACjD,MAAM,EAAE,WAAW,CAAC,kBAAkB,CAAC,EACvC,GAAG,EAAE,IAAI,GACR,MAAM,GAAG,IAAI;IAgBhB,MAAM,CAAC,kBAAkB,CACvB,gBAAgB,EAAE,WAAW,CAAC,kBAAkB,CAAC,EACjD,GAAG,EAAE,IAAI,GACR,MAAM;CAQV"}
@@ -0,0 +1,35 @@
1
+ import { DatabaseError } from "./database-error.js";
2
+ import { NaiveTimestamp } from "./naive-timestamp.js";
3
+ // pg-boss's send throttle: singletonSeconds, and singletonNextSlot to retry a
4
+ // refused send into the next slot.
5
+ export class Throttle {
6
+ // pg-boss's throttle slot: singletonSeconds wide, shifted by an offset, as a
7
+ // zoneless timestamp (node_modules/pg-boss/dist/plans.js:2279). A null width
8
+ // is no throttle there (`"singletonSeconds" IS NOT NULL`), and a zero width
9
+ // divides by zero in Postgres, which pg-boss surfaces as the driver's error.
10
+ // The offset is 0, or singletonSeconds when a refused send retries into the
11
+ // next slot (manager.js:1253-1256).
12
+ static slot(singletonSeconds, offset, now) {
13
+ if (singletonSeconds === undefined || singletonSeconds === null) {
14
+ return null;
15
+ }
16
+ const width = Number(singletonSeconds);
17
+ if (width === 0) {
18
+ throw new DatabaseError('division by zero', '22012');
19
+ }
20
+ const slotStartSeconds = width * Math.floor((now.getTime() / 1000 + Number(offset)) / width);
21
+ return NaiveTimestamp.fromUtc(new Date(slotStartSeconds * 1000));
22
+ }
23
+ // manager.js:1533-1542: seconds until the next throttle slot starts, never 0,
24
+ // and one more for slots wider than a second. Without a width the slot
25
+ // arithmetic is NaN, which the `|| 1` floors, as in pg-boss.
26
+ static debounceStartAfter(singletonSeconds, now) {
27
+ const width = Number(singletonSeconds);
28
+ const interval = width * 1000;
29
+ const slotStart = Math.floor(now.getTime() / interval) * interval;
30
+ const elapsedSeconds = Math.floor((now.getTime() - slotStart) / 1000);
31
+ const startAfter = width - elapsedSeconds || 1;
32
+ return width > 1 ? startAfter + 1 : startAfter;
33
+ }
34
+ }
35
+ //# sourceMappingURL=throttle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throttle.js","sourceRoot":"","sources":["../src/throttle.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,8EAA8E;AAC9E,mCAAmC;AACnC,MAAM,OAAO,QAAQ;IACnB,6EAA6E;IAC7E,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,oCAAoC;IACpC,MAAM,CAAC,IAAI,CACT,gBAAiD,EACjD,MAAuC,EACvC,GAAS;QAET,IAAI,gBAAgB,KAAK,SAAS,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACvC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,MAAM,IAAI,aAAa,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,gBAAgB,GACpB,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;QACtE,OAAO,cAAc,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,8EAA8E;IAC9E,uEAAuE;IACvE,6DAA6D;IAC7D,MAAM,CAAC,kBAAkB,CACvB,gBAAiD,EACjD,GAAS;QAET,MAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,GAAG,QAAQ,CAAC;QAClE,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,KAAK,GAAG,cAAc,IAAI,CAAC,CAAC;QAC/C,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACjD,CAAC;CACF"}
@@ -0,0 +1,36 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { DatabaseSync } from 'node:sqlite';
3
+ import type { Clock, PgBossEventMap, WorkHandler, WorkOptions } from 'pg-boss';
4
+ import type { Activity } from './activity.ts';
5
+ export type SlottedJob = {
6
+ data: {
7
+ name: string;
8
+ key: string;
9
+ data: unknown;
10
+ options: unknown;
11
+ slot: string;
12
+ };
13
+ singletonKey: string;
14
+ singletonOn: string;
15
+ };
16
+ export type TimekeeperManager = {
17
+ createQueue(name: string): Promise<void>;
18
+ work(name: string, options: WorkOptions, handler: WorkHandler<unknown>): Promise<string>;
19
+ offWork(name: string, options: {
20
+ wait: boolean;
21
+ }): Promise<void>;
22
+ send(request: unknown): Promise<string | null>;
23
+ insert(name: string, jobs: SlottedJob[]): Promise<void>;
24
+ };
25
+ export type TimekeeperConfig = {
26
+ cronMonitorIntervalSeconds: number;
27
+ cronWorkerIntervalSeconds: number;
28
+ };
29
+ export declare class Timekeeper extends EventEmitter<Pick<PgBossEventMap, 'error'>> {
30
+ #private;
31
+ static readonly sendIt = "__pgboss__send-it";
32
+ constructor(clock: Clock, activity: Activity, config: TimekeeperConfig, manager: TimekeeperManager);
33
+ start(database: DatabaseSync): Promise<void>;
34
+ stop(): Promise<void>;
35
+ }
36
+ //# sourceMappingURL=timekeeper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timekeeper.d.ts","sourceRoot":"","sources":["../src/timekeeper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,OAAO,KAAK,EACV,KAAK,EAEL,cAAc,EACd,WAAW,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAKjB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAW9C,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,OAAO,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAIF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,CACF,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,0BAA0B,EAAE,MAAM,CAAC;IACnC,yBAAyB,EAAE,MAAM,CAAC;CACnC,CAAC;AAgCF,qBAAa,UAAW,SAAQ,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;;IAEzE,MAAM,CAAC,QAAQ,CAAC,MAAM,uBAAuB;gBAkB3C,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,iBAAiB;IA+CtB,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B5C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CA4R5B"}