pg-boss 12.1.1 → 12.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.mts +4 -226
- package/dist/index.mjs +17 -2139
- package/dist/node_modules/serialize-error/error-constructors.mjs +18 -0
- package/dist/node_modules/serialize-error/index.mjs +109 -0
- package/dist/package.mjs +5 -0
- package/dist/src/attorney.mjs +166 -0
- package/dist/src/boss.mjs +129 -0
- package/dist/src/contractor.mjs +71 -0
- package/dist/src/db.mjs +40 -0
- package/dist/src/manager.mjs +485 -0
- package/dist/src/migrationStore.mjs +122 -0
- package/dist/src/plans.d.mts +19 -0
- package/dist/src/plans.mjs +868 -0
- package/dist/src/timekeeper.mjs +160 -0
- package/dist/src/tools.mjs +37 -0
- package/dist/src/types.d.mts +207 -0
- package/dist/src/worker.mjs +102 -0
- package/package.json +4 -4
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { getSchedules, getSchedulesByQueue, getTime, schedule, trySetCronTime, unschedule } from "./plans.mjs";
|
|
2
|
+
import { assertKey, checkSendArgs } from "./attorney.mjs";
|
|
3
|
+
import EventEmitter from "node:events";
|
|
4
|
+
import { CronExpressionParser } from "cron-parser";
|
|
5
|
+
|
|
6
|
+
//#region src/timekeeper.ts
|
|
7
|
+
const QUEUES = { SEND_IT: "__pgboss__send-it" };
|
|
8
|
+
const EVENTS = {
|
|
9
|
+
error: "error",
|
|
10
|
+
schedule: "schedule",
|
|
11
|
+
warning: "warning"
|
|
12
|
+
};
|
|
13
|
+
const WARNINGS = { CLOCK_SKEW: { message: "Warning: Clock skew between this instance and the database server. This will not break scheduling, but is emitted any time the skew exceeds 60 seconds." } };
|
|
14
|
+
var Timekeeper = class extends EventEmitter {
|
|
15
|
+
db;
|
|
16
|
+
config;
|
|
17
|
+
manager;
|
|
18
|
+
stopped = true;
|
|
19
|
+
cronMonitorInterval;
|
|
20
|
+
skewMonitorInterval;
|
|
21
|
+
timekeeping;
|
|
22
|
+
clockSkew = 0;
|
|
23
|
+
events = EVENTS;
|
|
24
|
+
constructor(db, manager, config) {
|
|
25
|
+
super();
|
|
26
|
+
this.db = db;
|
|
27
|
+
this.config = config;
|
|
28
|
+
this.manager = manager;
|
|
29
|
+
}
|
|
30
|
+
async start() {
|
|
31
|
+
this.stopped = false;
|
|
32
|
+
await this.cacheClockSkew();
|
|
33
|
+
await this.manager.createQueue(QUEUES.SEND_IT);
|
|
34
|
+
const options = {
|
|
35
|
+
pollingIntervalSeconds: this.config.cronWorkerIntervalSeconds,
|
|
36
|
+
batchSize: 50
|
|
37
|
+
};
|
|
38
|
+
await this.manager.work(QUEUES.SEND_IT, options, (jobs) => this.onSendIt(jobs));
|
|
39
|
+
setImmediate(() => this.onCron());
|
|
40
|
+
this.cronMonitorInterval = setInterval(async () => await this.onCron(), this.config.cronMonitorIntervalSeconds * 1e3);
|
|
41
|
+
this.skewMonitorInterval = setInterval(async () => await this.cacheClockSkew(), this.config.clockMonitorIntervalSeconds * 1e3);
|
|
42
|
+
}
|
|
43
|
+
async stop() {
|
|
44
|
+
if (this.stopped) return;
|
|
45
|
+
this.stopped = true;
|
|
46
|
+
await this.manager.offWork(QUEUES.SEND_IT, { wait: true });
|
|
47
|
+
if (this.skewMonitorInterval) {
|
|
48
|
+
clearInterval(this.skewMonitorInterval);
|
|
49
|
+
this.skewMonitorInterval = null;
|
|
50
|
+
}
|
|
51
|
+
if (this.cronMonitorInterval) {
|
|
52
|
+
clearInterval(this.cronMonitorInterval);
|
|
53
|
+
this.cronMonitorInterval = null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async cacheClockSkew() {
|
|
57
|
+
let skew = 0;
|
|
58
|
+
try {
|
|
59
|
+
if (this.config.__test__force_clock_monitoring_error) throw new Error(this.config.__test__force_clock_monitoring_error);
|
|
60
|
+
const { rows } = await this.db.executeSql(getTime());
|
|
61
|
+
const local = Date.now();
|
|
62
|
+
skew = parseFloat(rows[0].time) - local;
|
|
63
|
+
const skewSeconds = Math.abs(skew) / 1e3;
|
|
64
|
+
if (skewSeconds >= 60 || this.config.__test__force_clock_skew_warning) this.emit(this.events.warning, {
|
|
65
|
+
message: WARNINGS.CLOCK_SKEW.message,
|
|
66
|
+
data: {
|
|
67
|
+
seconds: skewSeconds,
|
|
68
|
+
direction: skew > 0 ? "slower" : "faster"
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
} catch (err) {
|
|
72
|
+
this.emit(this.events.error, err);
|
|
73
|
+
} finally {
|
|
74
|
+
this.clockSkew = skew;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async onCron() {
|
|
78
|
+
try {
|
|
79
|
+
if (this.stopped || this.timekeeping) return;
|
|
80
|
+
if (this.config.__test__force_cron_monitoring_error) throw new Error(this.config.__test__force_cron_monitoring_error);
|
|
81
|
+
this.timekeeping = true;
|
|
82
|
+
const sql = trySetCronTime(this.config.schema, this.config.cronMonitorIntervalSeconds);
|
|
83
|
+
if (!this.stopped) {
|
|
84
|
+
const { rows } = await this.db.executeSql(sql);
|
|
85
|
+
if (!this.stopped && rows.length === 1) await this.cron();
|
|
86
|
+
}
|
|
87
|
+
} catch (err) {
|
|
88
|
+
this.emit(this.events.error, err);
|
|
89
|
+
} finally {
|
|
90
|
+
this.timekeeping = false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async cron() {
|
|
94
|
+
const scheduled = (await this.getSchedules()).filter((i) => this.shouldSendIt(i.cron, i.timezone)).map(({ name, key, data, options }) => ({
|
|
95
|
+
data: {
|
|
96
|
+
name,
|
|
97
|
+
data,
|
|
98
|
+
options
|
|
99
|
+
},
|
|
100
|
+
singletonKey: `${name}__${key}`,
|
|
101
|
+
singletonSeconds: 60
|
|
102
|
+
}));
|
|
103
|
+
if (scheduled.length > 0 && !this.stopped) await this.manager.insert(QUEUES.SEND_IT, scheduled);
|
|
104
|
+
}
|
|
105
|
+
shouldSendIt(cron, tz) {
|
|
106
|
+
const prevTime = CronExpressionParser.parse(cron, {
|
|
107
|
+
tz,
|
|
108
|
+
strict: false
|
|
109
|
+
}).prev();
|
|
110
|
+
return (Date.now() + this.clockSkew - prevTime.getTime()) / 1e3 < 60;
|
|
111
|
+
}
|
|
112
|
+
async onSendIt(jobs) {
|
|
113
|
+
await Promise.allSettled(jobs.map(({ data }) => this.manager.send(data)));
|
|
114
|
+
}
|
|
115
|
+
async getSchedules(name, key = "") {
|
|
116
|
+
let sql = getSchedules(this.config.schema);
|
|
117
|
+
let params = [];
|
|
118
|
+
if (name) {
|
|
119
|
+
sql = getSchedulesByQueue(this.config.schema);
|
|
120
|
+
params = [name, key];
|
|
121
|
+
}
|
|
122
|
+
const { rows } = await this.db.executeSql(sql, params);
|
|
123
|
+
return rows;
|
|
124
|
+
}
|
|
125
|
+
async schedule(name, cron, data, options = {}) {
|
|
126
|
+
const { tz = "UTC", key = "", ...rest } = options;
|
|
127
|
+
CronExpressionParser.parse(cron, {
|
|
128
|
+
tz,
|
|
129
|
+
strict: false
|
|
130
|
+
});
|
|
131
|
+
checkSendArgs([
|
|
132
|
+
name,
|
|
133
|
+
data,
|
|
134
|
+
{ ...rest }
|
|
135
|
+
]);
|
|
136
|
+
assertKey(key);
|
|
137
|
+
try {
|
|
138
|
+
const sql = schedule(this.config.schema);
|
|
139
|
+
await this.db.executeSql(sql, [
|
|
140
|
+
name,
|
|
141
|
+
key,
|
|
142
|
+
cron,
|
|
143
|
+
tz,
|
|
144
|
+
data,
|
|
145
|
+
options
|
|
146
|
+
]);
|
|
147
|
+
} catch (err) {
|
|
148
|
+
if (err.message.includes("foreign key")) err.message = `Queue ${name} not found`;
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async unschedule(name, key = "") {
|
|
153
|
+
const sql = unschedule(this.config.schema);
|
|
154
|
+
await this.db.executeSql(sql, [name, key]);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
var timekeeper_default = Timekeeper;
|
|
158
|
+
|
|
159
|
+
//#endregion
|
|
160
|
+
export { QUEUES, timekeeper_default as default };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { setTimeout } from "node:timers/promises";
|
|
2
|
+
|
|
3
|
+
//#region src/tools.ts
|
|
4
|
+
/**
|
|
5
|
+
* When sql contains multiple queries, result is an array of objects with rows property
|
|
6
|
+
* This function unwraps the result into a single object with rows property
|
|
7
|
+
*/
|
|
8
|
+
function unwrapSQLResult(result) {
|
|
9
|
+
if (Array.isArray(result)) return { rows: result.flatMap((i) => i.rows) };
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
function delay(ms, error) {
|
|
13
|
+
const ac = new AbortController();
|
|
14
|
+
const promise = new Promise((resolve, reject) => {
|
|
15
|
+
setTimeout(ms, null, { signal: ac.signal }).then(() => {
|
|
16
|
+
if (error) reject(new Error(error));
|
|
17
|
+
else resolve();
|
|
18
|
+
}).catch(resolve);
|
|
19
|
+
});
|
|
20
|
+
promise.abort = () => {
|
|
21
|
+
if (!ac.signal.aborted) ac.abort();
|
|
22
|
+
};
|
|
23
|
+
return promise;
|
|
24
|
+
}
|
|
25
|
+
async function resolveWithinSeconds(promise, seconds, message) {
|
|
26
|
+
const reject = delay(Math.max(1, seconds) * 1e3, message);
|
|
27
|
+
let result;
|
|
28
|
+
try {
|
|
29
|
+
result = await Promise.race([promise, reject]);
|
|
30
|
+
} finally {
|
|
31
|
+
reject.abort();
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { delay, resolveWithinSeconds, unwrapSQLResult };
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
type JobStates = {
|
|
3
|
+
created: 'created';
|
|
4
|
+
retry: 'retry';
|
|
5
|
+
active: 'active';
|
|
6
|
+
completed: 'completed';
|
|
7
|
+
cancelled: 'cancelled';
|
|
8
|
+
failed: 'failed';
|
|
9
|
+
};
|
|
10
|
+
type Events = {
|
|
11
|
+
error: 'error';
|
|
12
|
+
warning: 'warning';
|
|
13
|
+
wip: 'wip';
|
|
14
|
+
stopped: 'stopped';
|
|
15
|
+
};
|
|
16
|
+
interface IDatabase {
|
|
17
|
+
executeSql(text: string, values?: unknown[]): Promise<{
|
|
18
|
+
rows: any[];
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
interface DatabaseOptions {
|
|
22
|
+
application_name?: string;
|
|
23
|
+
database?: string;
|
|
24
|
+
user?: string;
|
|
25
|
+
password?: string | (() => string) | (() => Promise<string>);
|
|
26
|
+
host?: string;
|
|
27
|
+
port?: number;
|
|
28
|
+
schema?: string;
|
|
29
|
+
ssl?: any;
|
|
30
|
+
connectionString?: string;
|
|
31
|
+
max?: number;
|
|
32
|
+
db?: IDatabase;
|
|
33
|
+
connectionTimeoutMillis?: number;
|
|
34
|
+
}
|
|
35
|
+
interface SchedulingOptions {
|
|
36
|
+
schedule?: boolean;
|
|
37
|
+
clockMonitorIntervalSeconds?: number;
|
|
38
|
+
cronWorkerIntervalSeconds?: number;
|
|
39
|
+
cronMonitorIntervalSeconds?: number;
|
|
40
|
+
}
|
|
41
|
+
interface MaintenanceOptions {
|
|
42
|
+
supervise?: boolean;
|
|
43
|
+
migrate?: boolean;
|
|
44
|
+
createSchema?: boolean;
|
|
45
|
+
warningSlowQuerySeconds?: number;
|
|
46
|
+
warningQueueSize?: number;
|
|
47
|
+
superviseIntervalSeconds?: number;
|
|
48
|
+
maintenanceIntervalSeconds?: number;
|
|
49
|
+
queueCacheIntervalSeconds?: number;
|
|
50
|
+
monitorIntervalSeconds?: number;
|
|
51
|
+
}
|
|
52
|
+
interface ConstructorOptions extends DatabaseOptions, SchedulingOptions, MaintenanceOptions {}
|
|
53
|
+
interface QueueOptions {
|
|
54
|
+
expireInSeconds?: number;
|
|
55
|
+
retentionSeconds?: number;
|
|
56
|
+
deleteAfterSeconds?: number;
|
|
57
|
+
retryLimit?: number;
|
|
58
|
+
retryDelay?: number;
|
|
59
|
+
retryBackoff?: boolean;
|
|
60
|
+
retryDelayMax?: number;
|
|
61
|
+
}
|
|
62
|
+
interface JobOptions {
|
|
63
|
+
id?: string;
|
|
64
|
+
priority?: number;
|
|
65
|
+
startAfter?: number | string | Date;
|
|
66
|
+
singletonKey?: string;
|
|
67
|
+
singletonSeconds?: number;
|
|
68
|
+
singletonNextSlot?: boolean;
|
|
69
|
+
keepUntil?: number | string | Date;
|
|
70
|
+
}
|
|
71
|
+
interface ConnectionOptions {
|
|
72
|
+
db?: IDatabase;
|
|
73
|
+
}
|
|
74
|
+
type InsertOptions = ConnectionOptions;
|
|
75
|
+
type SendOptions = JobOptions & QueueOptions & ConnectionOptions;
|
|
76
|
+
type QueuePolicy = 'standard' | 'short' | 'singleton' | 'stately' | 'exclusive';
|
|
77
|
+
interface Queue extends QueueOptions {
|
|
78
|
+
name: string;
|
|
79
|
+
policy?: QueuePolicy;
|
|
80
|
+
partition?: boolean;
|
|
81
|
+
deadLetter?: string;
|
|
82
|
+
warningQueueSize?: number;
|
|
83
|
+
}
|
|
84
|
+
interface QueueResult extends Queue {
|
|
85
|
+
deferredCount: number;
|
|
86
|
+
queuedCount: number;
|
|
87
|
+
activeCount: number;
|
|
88
|
+
totalCount: number;
|
|
89
|
+
table: string;
|
|
90
|
+
createdOn: Date;
|
|
91
|
+
updatedOn: Date;
|
|
92
|
+
singletonsActive: string[] | null;
|
|
93
|
+
}
|
|
94
|
+
type ScheduleOptions = SendOptions & {
|
|
95
|
+
tz?: string;
|
|
96
|
+
key?: string;
|
|
97
|
+
};
|
|
98
|
+
interface JobPollingOptions {
|
|
99
|
+
pollingIntervalSeconds?: number;
|
|
100
|
+
}
|
|
101
|
+
interface JobFetchOptions {
|
|
102
|
+
includeMetadata?: boolean;
|
|
103
|
+
priority?: boolean;
|
|
104
|
+
batchSize?: number;
|
|
105
|
+
ignoreStartAfter?: boolean;
|
|
106
|
+
}
|
|
107
|
+
type WorkOptions = JobFetchOptions & JobPollingOptions;
|
|
108
|
+
type FetchOptions = JobFetchOptions & ConnectionOptions;
|
|
109
|
+
interface WorkHandler<ReqData> {
|
|
110
|
+
(job: Job<ReqData>[]): Promise<any>;
|
|
111
|
+
}
|
|
112
|
+
interface WorkWithMetadataHandler<ReqData> {
|
|
113
|
+
(job: JobWithMetadata<ReqData>[]): Promise<any>;
|
|
114
|
+
}
|
|
115
|
+
interface Request {
|
|
116
|
+
name: string;
|
|
117
|
+
data?: object;
|
|
118
|
+
options?: SendOptions;
|
|
119
|
+
}
|
|
120
|
+
interface Schedule {
|
|
121
|
+
name: string;
|
|
122
|
+
key: string;
|
|
123
|
+
cron: string;
|
|
124
|
+
timezone: string;
|
|
125
|
+
data?: object;
|
|
126
|
+
options?: SendOptions;
|
|
127
|
+
}
|
|
128
|
+
interface Job<T = object> {
|
|
129
|
+
id: string;
|
|
130
|
+
name: string;
|
|
131
|
+
data: T;
|
|
132
|
+
expireInSeconds: number;
|
|
133
|
+
}
|
|
134
|
+
interface JobWithMetadata<T = object> extends Job<T> {
|
|
135
|
+
priority: number;
|
|
136
|
+
state: 'created' | 'retry' | 'active' | 'completed' | 'cancelled' | 'failed';
|
|
137
|
+
retryLimit: number;
|
|
138
|
+
retryCount: number;
|
|
139
|
+
retryDelay: number;
|
|
140
|
+
retryBackoff: boolean;
|
|
141
|
+
retryDelayMax?: number;
|
|
142
|
+
startAfter: Date;
|
|
143
|
+
startedOn: Date;
|
|
144
|
+
singletonKey: string | null;
|
|
145
|
+
singletonOn: Date | null;
|
|
146
|
+
expireInSeconds: number;
|
|
147
|
+
deleteAfterSeconds: number;
|
|
148
|
+
createdOn: Date;
|
|
149
|
+
completedOn: Date | null;
|
|
150
|
+
keepUntil: Date;
|
|
151
|
+
policy: QueuePolicy;
|
|
152
|
+
deadLetter: string;
|
|
153
|
+
output: object;
|
|
154
|
+
}
|
|
155
|
+
interface JobInsert<T = object> {
|
|
156
|
+
id?: string;
|
|
157
|
+
data?: T;
|
|
158
|
+
priority?: number;
|
|
159
|
+
retryLimit?: number;
|
|
160
|
+
retryDelay?: number;
|
|
161
|
+
retryBackoff?: boolean;
|
|
162
|
+
retryDelayMax?: number;
|
|
163
|
+
startAfter?: number | string | Date;
|
|
164
|
+
singletonKey?: string;
|
|
165
|
+
singletonSeconds?: number;
|
|
166
|
+
expireInSeconds?: number;
|
|
167
|
+
deleteAfterSeconds?: number;
|
|
168
|
+
retentionSeconds?: number;
|
|
169
|
+
}
|
|
170
|
+
type WorkerState = 'created' | 'active' | 'stopping' | 'stopped';
|
|
171
|
+
interface WipData {
|
|
172
|
+
id: string;
|
|
173
|
+
name: string;
|
|
174
|
+
options: WorkOptions;
|
|
175
|
+
state: WorkerState;
|
|
176
|
+
count: number;
|
|
177
|
+
createdOn: number;
|
|
178
|
+
lastFetchedOn: number | null;
|
|
179
|
+
lastJobStartedOn: number | null;
|
|
180
|
+
lastJobEndedOn: number | null;
|
|
181
|
+
lastJobDuration: number | null;
|
|
182
|
+
lastError: object | null;
|
|
183
|
+
lastErrorOn: number | null;
|
|
184
|
+
}
|
|
185
|
+
interface StopOptions {
|
|
186
|
+
close?: boolean;
|
|
187
|
+
graceful?: boolean;
|
|
188
|
+
timeout?: number;
|
|
189
|
+
}
|
|
190
|
+
interface OffWorkOptions {
|
|
191
|
+
id?: string;
|
|
192
|
+
wait?: boolean;
|
|
193
|
+
}
|
|
194
|
+
type UpdateQueueOptions = Omit<Queue, 'name' | 'partition' | 'policy'>;
|
|
195
|
+
interface Warning {
|
|
196
|
+
message: string;
|
|
197
|
+
data: object;
|
|
198
|
+
}
|
|
199
|
+
interface CommandResponse {}
|
|
200
|
+
type PgBossEventMap = {
|
|
201
|
+
error: [error: Error];
|
|
202
|
+
warning: [warning: Warning];
|
|
203
|
+
wip: [data: WipData[]];
|
|
204
|
+
stopped: [];
|
|
205
|
+
};
|
|
206
|
+
//#endregion
|
|
207
|
+
export { CommandResponse, ConnectionOptions, ConstructorOptions, Events, FetchOptions, IDatabase, InsertOptions, Job, JobFetchOptions, JobInsert, JobPollingOptions, JobStates, JobWithMetadata, MaintenanceOptions, OffWorkOptions, PgBossEventMap, Queue, QueuePolicy, QueueResult, Request, Schedule, ScheduleOptions, SchedulingOptions, SendOptions, StopOptions, UpdateQueueOptions, WipData, WorkHandler, WorkOptions, WorkWithMetadataHandler };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { delay } from "./tools.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/worker.ts
|
|
4
|
+
const WORKER_STATES = {
|
|
5
|
+
created: "created",
|
|
6
|
+
active: "active",
|
|
7
|
+
stopping: "stopping",
|
|
8
|
+
stopped: "stopped"
|
|
9
|
+
};
|
|
10
|
+
var Worker = class {
|
|
11
|
+
id;
|
|
12
|
+
name;
|
|
13
|
+
options;
|
|
14
|
+
fetch;
|
|
15
|
+
onFetch;
|
|
16
|
+
onError;
|
|
17
|
+
interval;
|
|
18
|
+
jobs = [];
|
|
19
|
+
createdOn = Date.now();
|
|
20
|
+
state = WORKER_STATES.created;
|
|
21
|
+
lastFetchedOn = null;
|
|
22
|
+
lastJobStartedOn = null;
|
|
23
|
+
lastJobEndedOn = null;
|
|
24
|
+
lastJobDuration = null;
|
|
25
|
+
lastError = null;
|
|
26
|
+
lastErrorOn = null;
|
|
27
|
+
stopping = false;
|
|
28
|
+
stopped = false;
|
|
29
|
+
loopDelayPromise = null;
|
|
30
|
+
beenNotified = false;
|
|
31
|
+
constructor({ id, name, options, interval, fetch, onFetch, onError }) {
|
|
32
|
+
this.id = id;
|
|
33
|
+
this.name = name;
|
|
34
|
+
this.options = options;
|
|
35
|
+
this.fetch = fetch;
|
|
36
|
+
this.onFetch = onFetch;
|
|
37
|
+
this.onError = onError;
|
|
38
|
+
this.interval = interval;
|
|
39
|
+
}
|
|
40
|
+
notify() {
|
|
41
|
+
this.beenNotified = true;
|
|
42
|
+
if (this.loopDelayPromise) this.loopDelayPromise.abort();
|
|
43
|
+
}
|
|
44
|
+
async start() {
|
|
45
|
+
this.state = WORKER_STATES.active;
|
|
46
|
+
while (!this.stopping) {
|
|
47
|
+
const started = Date.now();
|
|
48
|
+
try {
|
|
49
|
+
this.beenNotified = false;
|
|
50
|
+
const jobs = await this.fetch();
|
|
51
|
+
this.lastFetchedOn = Date.now();
|
|
52
|
+
if (jobs) {
|
|
53
|
+
this.jobs = jobs;
|
|
54
|
+
this.lastJobStartedOn = this.lastFetchedOn;
|
|
55
|
+
await this.onFetch(jobs);
|
|
56
|
+
this.lastJobEndedOn = Date.now();
|
|
57
|
+
this.jobs = [];
|
|
58
|
+
}
|
|
59
|
+
} catch (err) {
|
|
60
|
+
this.lastErrorOn = Date.now();
|
|
61
|
+
this.lastError = err;
|
|
62
|
+
err.message = `${err.message} (Queue: ${this.name}, Worker: ${this.id})`;
|
|
63
|
+
this.onError(err);
|
|
64
|
+
}
|
|
65
|
+
const duration = Date.now() - started;
|
|
66
|
+
this.lastJobDuration = duration;
|
|
67
|
+
if (!this.stopping && !this.beenNotified && this.interval - duration > 100) {
|
|
68
|
+
this.loopDelayPromise = delay(this.interval - duration);
|
|
69
|
+
await this.loopDelayPromise;
|
|
70
|
+
this.loopDelayPromise = null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
this.stopping = false;
|
|
74
|
+
this.stopped = true;
|
|
75
|
+
this.state = WORKER_STATES.stopped;
|
|
76
|
+
}
|
|
77
|
+
stop() {
|
|
78
|
+
this.stopping = true;
|
|
79
|
+
this.state = WORKER_STATES.stopping;
|
|
80
|
+
if (this.loopDelayPromise) this.loopDelayPromise.abort();
|
|
81
|
+
}
|
|
82
|
+
toWipData() {
|
|
83
|
+
return {
|
|
84
|
+
id: this.id,
|
|
85
|
+
name: this.name,
|
|
86
|
+
options: this.options,
|
|
87
|
+
state: this.state,
|
|
88
|
+
count: this.jobs.length,
|
|
89
|
+
createdOn: this.createdOn,
|
|
90
|
+
lastFetchedOn: this.lastFetchedOn,
|
|
91
|
+
lastJobStartedOn: this.lastJobStartedOn,
|
|
92
|
+
lastJobEndedOn: this.lastJobEndedOn,
|
|
93
|
+
lastError: this.lastError,
|
|
94
|
+
lastErrorOn: this.lastErrorOn,
|
|
95
|
+
lastJobDuration: this.lastJobDuration
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
var worker_default = Worker;
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
export { worker_default as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pg-boss",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.3.0",
|
|
4
4
|
"description": "Queueing jobs in Postgres from Node.js like a boss",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
|
23
|
-
"@tsconfig/node22": "^22.0.
|
|
23
|
+
"@tsconfig/node22": "^22.0.5",
|
|
24
24
|
"@types/mocha": "^10.0.10",
|
|
25
|
-
"@types/node": "^22.19.
|
|
25
|
+
"@types/node": "^22.19.1",
|
|
26
26
|
"@types/pg": "^8.15.6",
|
|
27
27
|
"eslint": "^9.39.1",
|
|
28
28
|
"luxon": "^3.7.2",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"neostandard": "^0.12.2",
|
|
31
31
|
"nyc": "^17.1.0",
|
|
32
32
|
"source-map-support": "^0.5.21",
|
|
33
|
-
"tsdown": "^0.16.
|
|
33
|
+
"tsdown": "^0.16.6",
|
|
34
34
|
"tsx": "^4.20.6",
|
|
35
35
|
"typescript": "^5.9.3"
|
|
36
36
|
},
|
package/dist/index.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/plans.ts","../src/index.ts"],"sourcesContent":[],"mappings":"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"}
|