@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.
- package/LICENSE +21 -0
- package/README.md +151 -2
- package/dist/activity.d.ts +10 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/activity.js +93 -0
- package/dist/activity.js.map +1 -0
- package/dist/attorney.d.ts +35 -0
- package/dist/attorney.d.ts.map +1 -0
- package/dist/attorney.js +367 -0
- package/dist/attorney.js.map +1 -0
- package/dist/claim-timer.d.ts +8 -0
- package/dist/claim-timer.d.ts.map +1 -0
- package/dist/claim-timer.js +80 -0
- package/dist/claim-timer.js.map +1 -0
- package/dist/completion-data.d.ts +6 -0
- package/dist/completion-data.d.ts.map +1 -0
- package/dist/completion-data.js +36 -0
- package/dist/completion-data.js.map +1 -0
- package/dist/database-error.d.ts +6 -0
- package/dist/database-error.d.ts.map +1 -0
- package/dist/database-error.js +12 -0
- package/dist/database-error.js.map +1 -0
- package/dist/database.d.ts +7 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +28 -0
- package/dist/database.js.map +1 -0
- package/dist/in-flight.d.ts +7 -0
- package/dist/in-flight.d.ts.map +1 -0
- package/dist/in-flight.js +24 -0
- package/dist/in-flight.js.map +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1069 -0
- package/dist/index.js.map +1 -0
- package/dist/job-fetcher.d.ts +16 -0
- package/dist/job-fetcher.d.ts.map +1 -0
- package/dist/job-fetcher.js +227 -0
- package/dist/job-fetcher.js.map +1 -0
- package/dist/job-queue.d.ts +27 -0
- package/dist/job-queue.d.ts.map +1 -0
- package/dist/job-queue.js +2 -0
- package/dist/job-queue.js.map +1 -0
- package/dist/job-rows.d.ts +49 -0
- package/dist/job-rows.d.ts.map +1 -0
- package/dist/job-rows.js +155 -0
- package/dist/job-rows.js.map +1 -0
- package/dist/job-settler.d.ts +24 -0
- package/dist/job-settler.d.ts.map +1 -0
- package/dist/job-settler.js +240 -0
- package/dist/job-settler.js.map +1 -0
- package/dist/jsonb.d.ts +7 -0
- package/dist/jsonb.d.ts.map +1 -0
- package/dist/jsonb.js +85 -0
- package/dist/jsonb.js.map +1 -0
- package/dist/local-groups.d.ts +16 -0
- package/dist/local-groups.d.ts.map +1 -0
- package/dist/local-groups.js +113 -0
- package/dist/local-groups.js.map +1 -0
- package/dist/naive-timestamp.d.ts +6 -0
- package/dist/naive-timestamp.d.ts.map +1 -0
- package/dist/naive-timestamp.js +21 -0
- package/dist/naive-timestamp.js.map +1 -0
- package/dist/queue-cache.d.ts +9 -0
- package/dist/queue-cache.d.ts.map +1 -0
- package/dist/queue-cache.js +27 -0
- package/dist/queue-cache.js.map +1 -0
- package/dist/queue-rows.d.ts +25 -0
- package/dist/queue-rows.d.ts.map +1 -0
- package/dist/queue-rows.js +44 -0
- package/dist/queue-rows.js.map +1 -0
- package/dist/recurrence.d.ts +11 -0
- package/dist/recurrence.d.ts.map +1 -0
- package/dist/recurrence.js +226 -0
- package/dist/recurrence.js.map +1 -0
- package/dist/rows.d.ts +10 -0
- package/dist/rows.d.ts.map +1 -0
- package/dist/rows.js +46 -0
- package/dist/rows.js.map +1 -0
- package/dist/schema.d.ts +3 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +139 -0
- package/dist/schema.js.map +1 -0
- package/dist/sql-values.d.ts +9 -0
- package/dist/sql-values.d.ts.map +1 -0
- package/dist/sql-values.js +26 -0
- package/dist/sql-values.js.map +1 -0
- package/dist/start-after.d.ts +10 -0
- package/dist/start-after.d.ts.map +1 -0
- package/dist/start-after.js +125 -0
- package/dist/start-after.js.map +1 -0
- package/dist/supervisor.d.ts +16 -0
- package/dist/supervisor.d.ts.map +1 -0
- package/dist/supervisor.js +288 -0
- package/dist/supervisor.js.map +1 -0
- package/dist/throttle.d.ts +6 -0
- package/dist/throttle.d.ts.map +1 -0
- package/dist/throttle.js +35 -0
- package/dist/throttle.js.map +1 -0
- package/dist/timekeeper.d.ts +36 -0
- package/dist/timekeeper.d.ts.map +1 -0
- package/dist/timekeeper.js +305 -0
- package/dist/timekeeper.js.map +1 -0
- package/dist/timers.d.ts +9 -0
- package/dist/timers.d.ts.map +1 -0
- package/dist/timers.js +50 -0
- package/dist/timers.js.map +1 -0
- package/dist/uuid.d.ts +7 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +36 -0
- package/dist/uuid.js.map +1 -0
- package/dist/worker.d.ts +35 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +147 -0
- package/dist/worker.js.map +1 -0
- package/package.json +53 -4
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { setImmediate } from 'node:timers/promises';
|
|
3
|
+
import { CronExpressionParser } from 'cron-parser';
|
|
4
|
+
import { scheduleKinds, scheduleMissedPolicies } from 'pg-boss';
|
|
5
|
+
import { transaction } from '@zukhruf/sqlite-transaction';
|
|
6
|
+
import { ClaimTimer } from "./claim-timer.js";
|
|
7
|
+
import { InFlight } from "./in-flight.js";
|
|
8
|
+
import { NaiveTimestamp } from "./naive-timestamp.js";
|
|
9
|
+
import { Recurrence } from "./recurrence.js";
|
|
10
|
+
import { Row } from "./rows.js";
|
|
11
|
+
import { SqlValues } from "./sql-values.js";
|
|
12
|
+
// pg-boss's Timekeeper (node_modules/pg-boss/dist/timekeeper.js) without the
|
|
13
|
+
// clock-skew loop (SQLite's clock is the database clock), invalid_schedule
|
|
14
|
+
// warnings, kind relabels and last_job_id: only schedule() writes a row, so
|
|
15
|
+
// no row is unreadable or mislabelled, and no method of the queue reads one
|
|
16
|
+
// back. A pass every cronMonitorIntervalSeconds claims the instance-wide
|
|
17
|
+
// cron stamp, files each schedule's due occurrences in __pgboss__send-it, one
|
|
18
|
+
// job per minute slot, and the send-it worker forwards each to its queue.
|
|
19
|
+
export class Timekeeper extends EventEmitter {
|
|
20
|
+
// timekeeper.js:12-14
|
|
21
|
+
static sendIt = '__pgboss__send-it';
|
|
22
|
+
// timekeeper.js:46: how long an occurrence stays due, and the width of the
|
|
23
|
+
// slot its job is filed in.
|
|
24
|
+
static #occurrenceWindowSeconds = 60;
|
|
25
|
+
// timekeeper.js:48
|
|
26
|
+
static #missedPolicies = Object.values(scheduleMissedPolicies);
|
|
27
|
+
#clock;
|
|
28
|
+
#activity;
|
|
29
|
+
#config;
|
|
30
|
+
#manager;
|
|
31
|
+
#phase = { kind: 'stopped' };
|
|
32
|
+
// pg-boss's _timekeeping: the pass in flight.
|
|
33
|
+
#pass = null;
|
|
34
|
+
constructor(clock, activity, config, manager) {
|
|
35
|
+
super();
|
|
36
|
+
this.#clock = clock;
|
|
37
|
+
this.#activity = activity;
|
|
38
|
+
this.#config = config;
|
|
39
|
+
this.#manager = manager;
|
|
40
|
+
}
|
|
41
|
+
// timekeeper.js:66-68: the name's underscores escaped, so the first
|
|
42
|
+
// unescaped underscore pair is the separator.
|
|
43
|
+
static #occurrenceKey(name, key) {
|
|
44
|
+
return `${name.replaceAll('_', '\\_')}__${key}`;
|
|
45
|
+
}
|
|
46
|
+
// timekeeper.js:76-79
|
|
47
|
+
static #throttleSlot(instant) {
|
|
48
|
+
const width = Timekeeper.#occurrenceWindowSeconds * 1000;
|
|
49
|
+
return new Date(Math.floor(instant.getTime() / width) * width)
|
|
50
|
+
.toISOString()
|
|
51
|
+
.replace('T', ' ')
|
|
52
|
+
.slice(0, 19);
|
|
53
|
+
}
|
|
54
|
+
// timekeeper.js:105-112: SQLite hands timestamps back as the text it
|
|
55
|
+
// stored.
|
|
56
|
+
static #toTime(value) {
|
|
57
|
+
if (value === null) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const time = new Date(value).getTime();
|
|
61
|
+
return Number.isNaN(time) ? null : time;
|
|
62
|
+
}
|
|
63
|
+
// timekeeper.js:145-150
|
|
64
|
+
static #missedPolicy(options) {
|
|
65
|
+
const missed = typeof options === 'object' && options !== null && 'missed' in options
|
|
66
|
+
? options.missed
|
|
67
|
+
: undefined;
|
|
68
|
+
return missed !== undefined && Timekeeper.#missedPolicies.includes(missed)
|
|
69
|
+
? missed
|
|
70
|
+
: scheduleMissedPolicies.skip;
|
|
71
|
+
}
|
|
72
|
+
// timekeeper.js:241-262. The first pass runs on a real setImmediate, as
|
|
73
|
+
// pg-boss's does, then every cronMonitorIntervalSeconds on the clock.
|
|
74
|
+
async start(database) {
|
|
75
|
+
if (this.#phase.kind === 'keeping') {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
await this.#manager.createQueue(Timekeeper.sendIt);
|
|
79
|
+
await this.#manager.work(Timekeeper.sendIt, {
|
|
80
|
+
pollingIntervalSeconds: this.#config.cronWorkerIntervalSeconds,
|
|
81
|
+
batchSize: 50,
|
|
82
|
+
}, (jobs) => this.#onSendIt(jobs));
|
|
83
|
+
void setImmediate().then(() => this.#onCron());
|
|
84
|
+
this.#phase = {
|
|
85
|
+
kind: 'keeping',
|
|
86
|
+
database,
|
|
87
|
+
timer: new ClaimTimer(this.#clock, this.#config.cronMonitorIntervalSeconds, () => this.#onCron()),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// timekeeper.js:263-280, which polls its pass flag every 10 ms of real
|
|
91
|
+
// time.
|
|
92
|
+
async stop() {
|
|
93
|
+
const phase = this.#phase;
|
|
94
|
+
if (phase.kind !== 'keeping') {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
this.#phase = { kind: 'stopped' };
|
|
98
|
+
await this.#manager.offWork(Timekeeper.sendIt, { wait: true });
|
|
99
|
+
phase.timer.stop();
|
|
100
|
+
await this.#pass?.settled();
|
|
101
|
+
}
|
|
102
|
+
// timekeeper.js:335-384
|
|
103
|
+
async #onCron() {
|
|
104
|
+
if (this.#phase.kind !== 'keeping' || this.#pass) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const pass = this.#cronPass(this.#phase);
|
|
108
|
+
this.#pass = new InFlight(pass);
|
|
109
|
+
try {
|
|
110
|
+
await pass;
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
this.#pass = null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async #cronPass(phase) {
|
|
117
|
+
try {
|
|
118
|
+
const { priorCronOn, elapsed, claimed } = await this.#activity.query(() => Timekeeper.#trySetCronTime(phase.database, this.#config.cronMonitorIntervalSeconds, new Date(this.#clock.now())));
|
|
119
|
+
if (claimed) {
|
|
120
|
+
phase.timer.anchor();
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
phase.timer.anchor(this.#claimRetryDelay(elapsed));
|
|
124
|
+
}
|
|
125
|
+
if (this.#phase.kind === 'keeping' && claimed) {
|
|
126
|
+
await this.#cron(phase.database, priorCronOn);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
this.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// timekeeper.js:406-411: until the claim it lost to comes due, plus a
|
|
134
|
+
// quarter of the interval capped at a second.
|
|
135
|
+
#claimRetryDelay(elapsed) {
|
|
136
|
+
const interval = this.#config.cronMonitorIntervalSeconds * 1000;
|
|
137
|
+
const age = Number(elapsed);
|
|
138
|
+
const remaining = Number.isFinite(age) && age > 0
|
|
139
|
+
? Math.max(0, interval - age * 1000)
|
|
140
|
+
: interval;
|
|
141
|
+
return remaining + Math.min(1000, interval / 4);
|
|
142
|
+
}
|
|
143
|
+
// trySetCronTime and trySetTimestamp (plans.js:1078-1086, 1111-1118): the
|
|
144
|
+
// stamp it replaced and its age, and whether this pass moved it. A stamp
|
|
145
|
+
// never written counts as a week old.
|
|
146
|
+
static #trySetCronTime(db, seconds, now) {
|
|
147
|
+
return transaction(db, () => {
|
|
148
|
+
const row = Row.parse(db.prepare('SELECT cron_on FROM pgboss_version').get(), 'version');
|
|
149
|
+
const priorCronOn = Row.readNullableString(row, 'cron_on');
|
|
150
|
+
const prior = Timekeeper.#toTime(priorCronOn);
|
|
151
|
+
const elapsed = prior === null ? null : (now.getTime() - prior) / 1000;
|
|
152
|
+
const claimed = (now.getTime() - (prior ?? now.getTime() - 604_800_000)) / 1000 >=
|
|
153
|
+
seconds;
|
|
154
|
+
if (claimed) {
|
|
155
|
+
db.prepare('UPDATE pgboss_version SET cron_on = ?').run(SqlValues.asIso(now));
|
|
156
|
+
}
|
|
157
|
+
return { priorCronOn, elapsed, claimed };
|
|
158
|
+
}, { mode: 'immediate' });
|
|
159
|
+
}
|
|
160
|
+
// timekeeper.js:418-527, one instant for the whole pass.
|
|
161
|
+
async #cron(db, priorCronOn) {
|
|
162
|
+
const schedules = await this.#activity.query(() => Timekeeper.#getSchedules(db));
|
|
163
|
+
const scheduled = [];
|
|
164
|
+
const databaseTime = this.#clock.now();
|
|
165
|
+
const windowStart = databaseTime - Timekeeper.#occurrenceWindowSeconds * 1000;
|
|
166
|
+
const lastPass = Timekeeper.#toTime(priorCronOn);
|
|
167
|
+
for (const schedule of schedules) {
|
|
168
|
+
const { name, key, data, options, kind, cron, timezone } = schedule;
|
|
169
|
+
let due;
|
|
170
|
+
try {
|
|
171
|
+
due = Timekeeper.#readOccurrences(cron, kind, timezone, databaseTime);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// timekeeper.js:450-458: one row never decides the others'.
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
let missed = null;
|
|
178
|
+
try {
|
|
179
|
+
missed = Timekeeper.#missedOccurrence(schedule, lastPass, windowStart);
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
// timekeeper.js:464-474: the gap closes anyway, since the claim has
|
|
183
|
+
// moved.
|
|
184
|
+
}
|
|
185
|
+
// timekeeper.js:503-515: a set of slots, so a missed occurrence and a
|
|
186
|
+
// due one in the same minute send one job.
|
|
187
|
+
const slots = new Set();
|
|
188
|
+
if (missed !== null) {
|
|
189
|
+
slots.add(Timekeeper.#throttleSlot(missed));
|
|
190
|
+
}
|
|
191
|
+
for (const occurrence of due) {
|
|
192
|
+
slots.add(Timekeeper.#throttleSlot(occurrence));
|
|
193
|
+
}
|
|
194
|
+
for (const slot of slots) {
|
|
195
|
+
scheduled.push({
|
|
196
|
+
data: { name, key, data, options, slot },
|
|
197
|
+
singletonKey: Timekeeper.#occurrenceKey(name, key),
|
|
198
|
+
// The insert casts the slot to a zoneless timestamp
|
|
199
|
+
// (plans.js:2258).
|
|
200
|
+
singletonOn: NaiveTimestamp.fromUtc(new Date(`${slot}Z`)),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (scheduled.length > 0 && this.#phase.kind === 'keeping') {
|
|
205
|
+
await this.#manager.insert(Timekeeper.sendIt, scheduled);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// getSchedules (plans.js:1276-1290), in name and key order.
|
|
209
|
+
static #getSchedules(db) {
|
|
210
|
+
return db
|
|
211
|
+
.prepare(`SELECT queue_name, key, kind, cron, COALESCE(timezone, 'UTC') AS timezone,
|
|
212
|
+
data, options, created_on
|
|
213
|
+
FROM pgboss_schedule
|
|
214
|
+
ORDER BY queue_name, key`)
|
|
215
|
+
.all()
|
|
216
|
+
.map((value) => {
|
|
217
|
+
const row = Row.parse(value, 'schedule');
|
|
218
|
+
const data = Row.readNullableString(row, 'data');
|
|
219
|
+
const options = Row.readNullableString(row, 'options');
|
|
220
|
+
return {
|
|
221
|
+
name: Row.readString(row, 'queue_name'),
|
|
222
|
+
key: Row.readString(row, 'key'),
|
|
223
|
+
kind: Row.readString(row, 'kind'),
|
|
224
|
+
cron: Row.readString(row, 'cron'),
|
|
225
|
+
timezone: Row.readString(row, 'timezone'),
|
|
226
|
+
data: data === null ? null : JSON.parse(data),
|
|
227
|
+
options: options === null ? null : JSON.parse(options),
|
|
228
|
+
createdOn: Row.readString(row, 'created_on'),
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
// timekeeper.js:591-601: under `once`, the latest occurrence in
|
|
233
|
+
// (max(lastPass, createdOn), windowStart], the gap no pass covered.
|
|
234
|
+
static #missedOccurrence(schedule, lastPass, windowStart) {
|
|
235
|
+
const { cron, kind, timezone, options, createdOn } = schedule;
|
|
236
|
+
if (Timekeeper.#missedPolicy(options) === scheduleMissedPolicies.skip ||
|
|
237
|
+
lastPass === null) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
const from = Math.max(lastPass, Timekeeper.#toTime(createdOn) ?? lastPass);
|
|
241
|
+
if (from >= windowStart) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
return Timekeeper.#latestOccurrenceBefore(cron, kind, timezone, new Date(from), new Date(windowStart));
|
|
245
|
+
}
|
|
246
|
+
// timekeeper.js:610-621. cron-parser's prev() answers strictly before its
|
|
247
|
+
// reference, so the reference is a millisecond past `until`.
|
|
248
|
+
static #latestOccurrenceBefore(expression, kind, tz, after, until) {
|
|
249
|
+
if (kind === scheduleKinds.rrule) {
|
|
250
|
+
return Recurrence.latestOccurrenceBefore(expression, after, until, tz);
|
|
251
|
+
}
|
|
252
|
+
const occurrence = CronExpressionParser.parse(expression, {
|
|
253
|
+
tz,
|
|
254
|
+
strict: false,
|
|
255
|
+
currentDate: new Date(until.getTime() + 1),
|
|
256
|
+
})
|
|
257
|
+
.prev()
|
|
258
|
+
.toDate();
|
|
259
|
+
return occurrence.getTime() > after.getTime() ? occurrence : null;
|
|
260
|
+
}
|
|
261
|
+
// timekeeper.js:639-653: every occurrence in the last minute, a cron
|
|
262
|
+
// expression's latest only.
|
|
263
|
+
static #readOccurrences(expression, kind, tz, databaseTime) {
|
|
264
|
+
const window = new Date(databaseTime - Timekeeper.#occurrenceWindowSeconds * 1000);
|
|
265
|
+
if (kind === scheduleKinds.rrule) {
|
|
266
|
+
return Recurrence.occurrencesInWindow(expression, window, new Date(databaseTime), tz);
|
|
267
|
+
}
|
|
268
|
+
const previous = CronExpressionParser.parse(expression, {
|
|
269
|
+
tz,
|
|
270
|
+
strict: false,
|
|
271
|
+
currentDate: new Date(databaseTime + 1),
|
|
272
|
+
})
|
|
273
|
+
.prev()
|
|
274
|
+
.toDate();
|
|
275
|
+
return previous.getTime() > window.getTime() ? [previous] : [];
|
|
276
|
+
}
|
|
277
|
+
// timekeeper.js:658-665: an error event nobody listens for must not fail
|
|
278
|
+
// the send-it job, which would replay every occurrence in its batch.
|
|
279
|
+
#reportSendItError(error) {
|
|
280
|
+
try {
|
|
281
|
+
this.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
// nothing left to report it to
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// timekeeper.js:666-687: each occurrence's request goes to send() without
|
|
288
|
+
// its key and slot; a send that rejects is reported, and the send-it job
|
|
289
|
+
// completes either way.
|
|
290
|
+
async #onSendIt(jobs) {
|
|
291
|
+
const results = await Promise.allSettled(jobs.map(async ({ data }) => {
|
|
292
|
+
if (typeof data !== 'object' || data === null) {
|
|
293
|
+
throw new TypeError('send-it job data must be an object');
|
|
294
|
+
}
|
|
295
|
+
const request = Object.fromEntries(Object.entries(data).filter(([field]) => field !== 'key' && field !== 'slot'));
|
|
296
|
+
return await this.#manager.send(request);
|
|
297
|
+
}));
|
|
298
|
+
for (const result of results) {
|
|
299
|
+
if (result.status === 'rejected') {
|
|
300
|
+
this.#reportSendItError(result.reason);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=timekeeper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timekeeper.js","sourceRoot":"","sources":["../src/timekeeper.ts"],"names":[],"mappings":"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"}
|
package/dist/timers.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Clock } from 'pg-boss';
|
|
2
|
+
export type ClockDelay = Promise<void> & {
|
|
3
|
+
abort(): void;
|
|
4
|
+
};
|
|
5
|
+
export declare class Timers {
|
|
6
|
+
static delay(clock: Clock, ms: number, error?: string, abortController?: AbortController): ClockDelay;
|
|
7
|
+
static resolveWithinSeconds<T>(clock: Clock, promise: Promise<T>, seconds: number, message: string, abortController: AbortController): Promise<T | void>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=timers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timers.d.ts","sourceRoot":"","sources":["../src/timers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGrC,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG;IAAE,KAAK,IAAI,IAAI,CAAA;CAAE,CAAC;AAI3D,qBAAa,MAAM;IAEjB,MAAM,CAAC,KAAK,CACV,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,MAAM,EACV,KAAK,CAAC,EAAE,MAAM,EACd,eAAe,CAAC,EAAE,eAAe,GAChC,UAAU;WAiCA,oBAAoB,CAAC,CAAC,EACjC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;CASrB"}
|
package/dist/timers.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// pg-boss's waits, scheduled on the configured clock so a test clock fires
|
|
2
|
+
// them (node_modules/pg-boss/dist/tools.js:32-77).
|
|
3
|
+
export class Timers {
|
|
4
|
+
// clockDelay: rejects with `error` when the wait runs out, if given.
|
|
5
|
+
static delay(clock, ms, error, abortController) {
|
|
6
|
+
const controller = abortController ?? new AbortController();
|
|
7
|
+
const promise = new Promise((resolve, reject) => {
|
|
8
|
+
const handle = clock.setTimeout(() => {
|
|
9
|
+
controller.signal.removeEventListener('abort', onAbort);
|
|
10
|
+
if (error) {
|
|
11
|
+
reject(new Error(error));
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
resolve();
|
|
15
|
+
}
|
|
16
|
+
}, ms);
|
|
17
|
+
const onAbort = () => {
|
|
18
|
+
clock.clearTimeout(handle);
|
|
19
|
+
resolve();
|
|
20
|
+
};
|
|
21
|
+
if (controller.signal.aborted) {
|
|
22
|
+
onAbort();
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
controller.signal.addEventListener('abort', onAbort, { once: true });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return Object.assign(promise, {
|
|
29
|
+
abort: () => {
|
|
30
|
+
if (!controller.signal.aborted) {
|
|
31
|
+
controller.abort();
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// Races `promise` against `seconds` (at least one), rejecting with
|
|
37
|
+
// `message` when they run out. Settling aborts the controller either way,
|
|
38
|
+
// which is how the deadline cancels itself.
|
|
39
|
+
static async resolveWithinSeconds(clock, promise, seconds, message, abortController) {
|
|
40
|
+
const timeout = Math.max(1, seconds) * 1000;
|
|
41
|
+
const deadline = Timers.delay(clock, timeout, message, abortController);
|
|
42
|
+
try {
|
|
43
|
+
return await Promise.race([promise, deadline]);
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
deadline.abort();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=timers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timers.js","sourceRoot":"","sources":["../src/timers.ts"],"names":[],"mappings":"AAKA,2EAA2E;AAC3E,mDAAmD;AACnD,MAAM,OAAO,MAAM;IACjB,qEAAqE;IACrE,MAAM,CAAC,KAAK,CACV,KAAY,EACZ,EAAU,EACV,KAAc,EACd,eAAiC;QAEjC,MAAM,UAAU,GAAG,eAAe,IAAI,IAAI,eAAe,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACpD,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE;gBACnC,UAAU,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACxD,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC3B,CAAC;qBAAM,CAAC;oBACN,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC,EAAE,EAAE,CAAC,CAAC;YACP,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;gBAC3B,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YACF,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC9B,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACvE,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE;YAC5B,KAAK,EAAE,GAAG,EAAE;gBACV,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC/B,UAAU,CAAC,KAAK,EAAE,CAAC;gBACrB,CAAC;YACH,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED,mEAAmE;IACnE,0EAA0E;IAC1E,4CAA4C;IAC5C,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAC/B,KAAY,EACZ,OAAmB,EACnB,OAAe,EACf,OAAe,EACf,eAAgC;QAEhC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;QAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;QACxE,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;QACjD,CAAC;gBAAS,CAAC;YACT,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;CACF"}
|
package/dist/uuid.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"AAMA,qBAAa,IAAI;;IAIf,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAuBtC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAQ1C,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;CAGhD"}
|
package/dist/uuid.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { DatabaseError } from "./database-error.js";
|
|
2
|
+
// Postgres's uuid input, which pg-boss binds every job id through: 32 hex
|
|
3
|
+
// digits in either case, a hyphen allowed after any group of four but the
|
|
4
|
+
// last, optionally in braces, printed lower case as 8-4-4-4-12; any other
|
|
5
|
+
// text is 22P02 (https://www.postgresql.org/docs/current/datatype-uuid.html).
|
|
6
|
+
export class Uuid {
|
|
7
|
+
static #input = /^(?:\{([0-9a-f]{4}(?:-?[0-9a-f]{4}){7})\}|([0-9a-f]{4}(?:-?[0-9a-f]{4}){7}))$/i;
|
|
8
|
+
static canonical(text) {
|
|
9
|
+
const match = Uuid.#input.exec(text);
|
|
10
|
+
const digits = (match?.[1] ?? match?.[2])
|
|
11
|
+
?.replaceAll('-', '')
|
|
12
|
+
.toLowerCase();
|
|
13
|
+
if (digits === undefined) {
|
|
14
|
+
throw new DatabaseError(`invalid input syntax for type uuid: "${text}"`, '22P02');
|
|
15
|
+
}
|
|
16
|
+
return [
|
|
17
|
+
digits.slice(0, 8),
|
|
18
|
+
digits.slice(8, 12),
|
|
19
|
+
digits.slice(12, 16),
|
|
20
|
+
digits.slice(16, 20),
|
|
21
|
+
digits.slice(20),
|
|
22
|
+
].join('-');
|
|
23
|
+
}
|
|
24
|
+
// send()'s id, which pg-boss's insert reads out of its JSON payload
|
|
25
|
+
// (node_modules/pg-boss/dist/plans.js:2303): a string as it is, anything
|
|
26
|
+
// else as its JSON text.
|
|
27
|
+
static fromPayload(value) {
|
|
28
|
+
return Uuid.canonical(typeof value === 'string' ? value : JSON.stringify(value));
|
|
29
|
+
}
|
|
30
|
+
// findJobs()'s id, bound as a parameter (plans.js:3694): null is SQL NULL,
|
|
31
|
+
// which matches no job.
|
|
32
|
+
static parameter(value) {
|
|
33
|
+
return value === null ? null : Uuid.canonical(String(value));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=uuid.js.map
|
package/dist/uuid.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.js","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,0EAA0E;AAC1E,0EAA0E;AAC1E,0EAA0E;AAC1E,8EAA8E;AAC9E,MAAM,OAAO,IAAI;IACf,MAAM,CAAU,MAAM,GACpB,gFAAgF,CAAC;IAEnF,MAAM,CAAC,SAAS,CAAC,IAAY;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;YACvC,EAAE,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC;aACpB,WAAW,EAAE,CAAC;QACjB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,aAAa,CACrB,wCAAwC,IAAI,GAAG,EAC/C,OAAO,CACR,CAAC;QACJ,CAAC;QACD,OAAO;YACL,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YAClB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YACnB,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;SACjB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACd,CAAC;IAED,oEAAoE;IACpE,yEAAyE;IACzE,yBAAyB;IACzB,MAAM,CAAC,WAAW,CAAC,KAAc;QAC/B,OAAO,IAAI,CAAC,SAAS,CACnB,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAC1D,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,wBAAwB;IACxB,MAAM,CAAC,SAAS,CAAC,KAAc;QAC7B,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,CAAC"}
|
package/dist/worker.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Clock, WipData, WorkOptions } from 'pg-boss';
|
|
2
|
+
export type WorkerOptions = WorkOptions & {
|
|
3
|
+
pollingInterval: number;
|
|
4
|
+
notifyPollingInterval: number;
|
|
5
|
+
};
|
|
6
|
+
export interface WorkerConfig<TJob> {
|
|
7
|
+
id: string;
|
|
8
|
+
workId: string;
|
|
9
|
+
name: string;
|
|
10
|
+
options: WorkerOptions;
|
|
11
|
+
clock: Clock;
|
|
12
|
+
resolveInterval: (lastFetchCount: number) => number;
|
|
13
|
+
fetch: () => Promise<TJob[]>;
|
|
14
|
+
onFetch: (jobs: TJob[]) => Promise<void>;
|
|
15
|
+
onError: (error: Error) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare class Worker<TJob> {
|
|
18
|
+
#private;
|
|
19
|
+
readonly id: string;
|
|
20
|
+
readonly workId: string;
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly options: WorkerOptions;
|
|
23
|
+
readonly createdOn: number;
|
|
24
|
+
jobs: TJob[];
|
|
25
|
+
abortController: AbortController | null;
|
|
26
|
+
constructor(config: WorkerConfig<TJob>);
|
|
27
|
+
get stopping(): boolean;
|
|
28
|
+
get stopped(): boolean;
|
|
29
|
+
start(): void;
|
|
30
|
+
notify(): void;
|
|
31
|
+
abort(): void;
|
|
32
|
+
stop(): Promise<void>;
|
|
33
|
+
toWipData(): WipData;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAe,MAAM,SAAS,CAAC;AAQxE,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG;IACxC,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,MAAM,WAAW,YAAY,CAAC,IAAI;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,eAAe,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,CAAC;IACpD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACjC;AAKD,qBAAa,MAAM,CAAC,IAAI;;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,IAAI,EAAE,IAAI,EAAE,CAAM;IAElB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAQ;gBAqBnC,MAAM,EAAE,YAAY,CAAC,IAAI,CAAC;IAatC,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAKD,KAAK,IAAI,IAAI;IAsDb,MAAM,IAAI,IAAI;IAMd,KAAK,IAAI,IAAI;IASP,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,SAAS,IAAI,OAAO;CAiBrB"}
|
package/dist/worker.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Latch } from '@zukhruf/async';
|
|
2
|
+
import { Timers } from "./timers.js";
|
|
3
|
+
// One polling loop of a work() call, which starts one per localConcurrency
|
|
4
|
+
// (node_modules/pg-boss/dist/worker.js:53-114): fetch at once, hand the jobs
|
|
5
|
+
// over, then wait out the interval on the clock unless notified meanwhile.
|
|
6
|
+
export class Worker {
|
|
7
|
+
id;
|
|
8
|
+
// The id work() returned, shared by every loop it started.
|
|
9
|
+
workId;
|
|
10
|
+
name;
|
|
11
|
+
options;
|
|
12
|
+
createdOn;
|
|
13
|
+
// The batch in flight, which a shutdown fails (manager.js:884-909).
|
|
14
|
+
jobs = [];
|
|
15
|
+
// The batch's controller while it runs, which a shutdown aborts.
|
|
16
|
+
abortController = null;
|
|
17
|
+
#clock;
|
|
18
|
+
#resolveInterval;
|
|
19
|
+
#fetch;
|
|
20
|
+
#onFetch;
|
|
21
|
+
#onError;
|
|
22
|
+
#state = 'created';
|
|
23
|
+
// pg-boss's #beenNotified, cleared as each round starts: notify() counts,
|
|
24
|
+
// and a round was notified when the count moved since it started.
|
|
25
|
+
#notifications = 0;
|
|
26
|
+
// Aborts the round's wait; a fresh one arms each wait.
|
|
27
|
+
#wake = new AbortController();
|
|
28
|
+
// How the loop ended, which stop() waits for.
|
|
29
|
+
#ran = new Latch();
|
|
30
|
+
#lastFetchedOn = null;
|
|
31
|
+
#lastJobStartedOn = null;
|
|
32
|
+
#lastJobEndedOn = null;
|
|
33
|
+
#lastJobDuration = null;
|
|
34
|
+
#lastError = null;
|
|
35
|
+
#lastErrorOn = null;
|
|
36
|
+
constructor(config) {
|
|
37
|
+
this.id = config.id;
|
|
38
|
+
this.workId = config.workId;
|
|
39
|
+
this.name = config.name;
|
|
40
|
+
this.options = config.options;
|
|
41
|
+
this.#clock = config.clock;
|
|
42
|
+
this.createdOn = config.clock.now();
|
|
43
|
+
this.#resolveInterval = config.resolveInterval;
|
|
44
|
+
this.#fetch = config.fetch;
|
|
45
|
+
this.#onFetch = config.onFetch;
|
|
46
|
+
this.#onError = config.onError;
|
|
47
|
+
}
|
|
48
|
+
get stopping() {
|
|
49
|
+
return this.#state === 'stopping';
|
|
50
|
+
}
|
|
51
|
+
get stopped() {
|
|
52
|
+
return this.#state === 'stopped';
|
|
53
|
+
}
|
|
54
|
+
// pg-boss keeps the loop's promise for stop() to await (worker.js:51, 113):
|
|
55
|
+
// a loop that rejects, for example on an error emit with no listener,
|
|
56
|
+
// rejects the stop that waits for it, and is unhandled when no stop waits.
|
|
57
|
+
start() {
|
|
58
|
+
void this.#run().then(() => this.#ran.open({ ok: true }), (error) => {
|
|
59
|
+
this.#ran.open({ ok: false, error });
|
|
60
|
+
if (!this.stopping) {
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async #run() {
|
|
66
|
+
// A stop() before start() leaves the loop at once.
|
|
67
|
+
if (this.#state === 'created') {
|
|
68
|
+
this.#state = 'active';
|
|
69
|
+
}
|
|
70
|
+
while (!this.stopping) {
|
|
71
|
+
const started = this.#clock.now();
|
|
72
|
+
// Stays 0 on an error, so a failed fetch backs off to the normal poll.
|
|
73
|
+
let fetchedCount = 0;
|
|
74
|
+
const notifications = this.#notifications;
|
|
75
|
+
try {
|
|
76
|
+
const jobs = await this.#fetch();
|
|
77
|
+
this.#lastFetchedOn = this.#clock.now();
|
|
78
|
+
fetchedCount = jobs.length;
|
|
79
|
+
this.jobs = jobs;
|
|
80
|
+
this.#lastJobStartedOn = this.#lastFetchedOn;
|
|
81
|
+
await this.#onFetch(jobs);
|
|
82
|
+
this.#lastJobEndedOn = this.#clock.now();
|
|
83
|
+
this.jobs = [];
|
|
84
|
+
}
|
|
85
|
+
catch (caught) {
|
|
86
|
+
this.#lastErrorOn = this.#clock.now();
|
|
87
|
+
const error = caught instanceof Error ? caught : new Error(String(caught));
|
|
88
|
+
this.#lastError = error;
|
|
89
|
+
error.message = `${error.message} (Queue: ${this.name}, Worker: ${this.id})`;
|
|
90
|
+
this.#onError(error);
|
|
91
|
+
}
|
|
92
|
+
const duration = this.#clock.now() - started;
|
|
93
|
+
this.#lastJobDuration = duration;
|
|
94
|
+
const remaining = this.#resolveInterval(fetchedCount) - duration;
|
|
95
|
+
if (!this.stopping &&
|
|
96
|
+
this.#notifications === notifications &&
|
|
97
|
+
remaining > 100) {
|
|
98
|
+
this.#wake = new AbortController();
|
|
99
|
+
await Timers.delay(this.#clock, remaining, undefined, this.#wake);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.#state = 'stopped';
|
|
103
|
+
}
|
|
104
|
+
notify() {
|
|
105
|
+
this.#notifications += 1;
|
|
106
|
+
this.#wake.abort();
|
|
107
|
+
}
|
|
108
|
+
// worker.js:115-122
|
|
109
|
+
abort() {
|
|
110
|
+
if (!this.abortController) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!this.abortController.signal.aborted) {
|
|
114
|
+
this.abortController.abort();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async stop() {
|
|
118
|
+
if (this.stopped) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
this.#state = 'stopping';
|
|
122
|
+
this.#wake.abort();
|
|
123
|
+
const ran = await this.#ran.wait();
|
|
124
|
+
if (!ran.ok) {
|
|
125
|
+
throw ran.error;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// worker.js:123-139
|
|
129
|
+
toWipData() {
|
|
130
|
+
return {
|
|
131
|
+
id: this.id,
|
|
132
|
+
workId: this.workId,
|
|
133
|
+
name: this.name,
|
|
134
|
+
options: this.options,
|
|
135
|
+
state: this.#state,
|
|
136
|
+
count: this.jobs.length,
|
|
137
|
+
createdOn: this.createdOn,
|
|
138
|
+
lastFetchedOn: this.#lastFetchedOn,
|
|
139
|
+
lastJobStartedOn: this.#lastJobStartedOn,
|
|
140
|
+
lastJobEndedOn: this.#lastJobEndedOn,
|
|
141
|
+
lastError: this.#lastError,
|
|
142
|
+
lastErrorOn: this.#lastErrorOn,
|
|
143
|
+
lastJobDuration: this.#lastJobDuration,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
|