pg-boss 12.2.0 → 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/dist/index.d.mts +3 -225
- package/dist/index.mjs +9 -2144
- 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 +3 -3
- 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,7 +20,7 @@
|
|
|
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
25
|
"@types/node": "^22.19.1",
|
|
26
26
|
"@types/pg": "^8.15.6",
|
|
@@ -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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"}
|