@nest-native/jobs 0.1.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 +115 -0
- package/dist/dialects/mysql/index.d.ts +2 -0
- package/dist/dialects/mysql/index.js +21 -0
- package/dist/dialects/mysql/index.js.map +1 -0
- package/dist/dialects/mysql/job-store.d.ts +35 -0
- package/dist/dialects/mysql/job-store.js +150 -0
- package/dist/dialects/mysql/job-store.js.map +1 -0
- package/dist/dialects/mysql/schema.d.ts +255 -0
- package/dist/dialects/mysql/schema.js +47 -0
- package/dist/dialects/mysql/schema.js.map +1 -0
- package/dist/dialects/postgres/index.d.ts +2 -0
- package/dist/dialects/postgres/index.js +21 -0
- package/dist/dialects/postgres/index.js.map +1 -0
- package/dist/dialects/postgres/job-store.d.ts +32 -0
- package/dist/dialects/postgres/job-store.js +145 -0
- package/dist/dialects/postgres/job-store.js.map +1 -0
- package/dist/dialects/postgres/schema.d.ts +262 -0
- package/dist/dialects/postgres/schema.js +37 -0
- package/dist/dialects/postgres/schema.js.map +1 -0
- package/dist/dialects/sqlite/index.d.ts +2 -0
- package/dist/dialects/sqlite/index.js +21 -0
- package/dist/dialects/sqlite/index.js.map +1 -0
- package/dist/dialects/sqlite/job-store.d.ts +32 -0
- package/dist/dialects/sqlite/job-store.js +155 -0
- package/dist/dialects/sqlite/job-store.js.map +1 -0
- package/dist/dialects/sqlite/schema.d.ts +279 -0
- package/dist/dialects/sqlite/schema.js +37 -0
- package/dist/dialects/sqlite/schema.js.map +1 -0
- package/dist/enqueue-input.d.ts +12 -0
- package/dist/enqueue-input.js +26 -0
- package/dist/enqueue-input.js.map +1 -0
- package/dist/errors.d.ts +18 -0
- package/dist/errors.js +33 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +125 -0
- package/dist/interfaces.js +10 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/job-handler.decorator.d.ts +31 -0
- package/dist/job-handler.decorator.js +18 -0
- package/dist/job-handler.decorator.js.map +1 -0
- package/dist/jobs-claimer.service.d.ts +37 -0
- package/dist/jobs-claimer.service.js +121 -0
- package/dist/jobs-claimer.service.js.map +1 -0
- package/dist/jobs-handler.explorer.d.ts +24 -0
- package/dist/jobs-handler.explorer.js +67 -0
- package/dist/jobs-handler.explorer.js.map +1 -0
- package/dist/jobs-worker.d.ts +21 -0
- package/dist/jobs-worker.js +40 -0
- package/dist/jobs-worker.js.map +1 -0
- package/dist/jobs.module.d.ts +19 -0
- package/dist/jobs.module.js +49 -0
- package/dist/jobs.module.js.map +1 -0
- package/dist/jobs.service.d.ts +25 -0
- package/dist/jobs.service.js +55 -0
- package/dist/jobs.service.js.map +1 -0
- package/dist/testing/harness.d.ts +61 -0
- package/dist/testing/harness.js +86 -0
- package/dist/testing/harness.js.map +1 -0
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +19 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tokens.d.ts +10 -0
- package/dist/tokens.js +15 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +107 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqliteJobStore = void 0;
|
|
4
|
+
exports.isSqliteUniqueViolation = isSqliteUniqueViolation;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
7
|
+
const enqueue_input_1 = require("../../enqueue-input");
|
|
8
|
+
const schema_1 = require("./schema");
|
|
9
|
+
/**
|
|
10
|
+
* better-sqlite3 surfaces a unique-constraint violation as a `SqliteError` with
|
|
11
|
+
* `code === 'SQLITE_CONSTRAINT_UNIQUE'`. Match on the code (stable across driver
|
|
12
|
+
* versions), not the message. Drizzle may wrap driver errors in a
|
|
13
|
+
* `DrizzleQueryError`, so the code may instead sit on `error.cause` — check both.
|
|
14
|
+
*/
|
|
15
|
+
function isSqliteUniqueViolation(error) {
|
|
16
|
+
const code = 'SQLITE_CONSTRAINT_UNIQUE';
|
|
17
|
+
return hasCode(error, code) || hasCode(error?.cause, code);
|
|
18
|
+
}
|
|
19
|
+
function hasCode(error, code) {
|
|
20
|
+
return (typeof error === 'object' &&
|
|
21
|
+
error !== null &&
|
|
22
|
+
'code' in error &&
|
|
23
|
+
error.code === code);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* SQLite (better-sqlite3) job store. Every method runs **synchronously** —
|
|
27
|
+
* `enqueue` returns the row directly so it composes inside a synchronous
|
|
28
|
+
* `@Transactional` body, and the rest wrap their synchronous result in a
|
|
29
|
+
* resolved Promise for the engine to await from outside the transaction.
|
|
30
|
+
*
|
|
31
|
+
* A `(name, unique_key)` unique violation on `enqueue` is the active-dedup
|
|
32
|
+
* no-op: the store returns the EXISTING active row instead of inserting.
|
|
33
|
+
*/
|
|
34
|
+
class SqliteJobStore {
|
|
35
|
+
enqueue(db, input) {
|
|
36
|
+
const availableAt = (0, enqueue_input_1.resolveAvailableAt)(input).toISOString();
|
|
37
|
+
try {
|
|
38
|
+
return db
|
|
39
|
+
.insert(schema_1.jobs)
|
|
40
|
+
.values({
|
|
41
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
42
|
+
name: input.name,
|
|
43
|
+
// The one place the structural input payload widens to the stored shape.
|
|
44
|
+
payload: input.payload,
|
|
45
|
+
status: 'pending',
|
|
46
|
+
maxAttempts: input.maxAttempts ?? 10,
|
|
47
|
+
uniqueKey: input.uniqueKey ?? null,
|
|
48
|
+
priority: input.priority ?? 0,
|
|
49
|
+
availableAt,
|
|
50
|
+
createdAt: new Date().toISOString(),
|
|
51
|
+
})
|
|
52
|
+
.returning()
|
|
53
|
+
.get();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
const existing = this.findActiveDuplicate(db, input, error);
|
|
57
|
+
if (!existing)
|
|
58
|
+
throw error;
|
|
59
|
+
return existing;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* On a unique violation with a `uniqueKey`, the ACTIVE row that owns the
|
|
64
|
+
* `(name, uniqueKey)` pair — terminal rows cannot own it (their key is
|
|
65
|
+
* cleared to NULL). Any other error, or a vanished row (the owner completed
|
|
66
|
+
* between the insert and this read), returns undefined so the caller
|
|
67
|
+
* rethrows the original error.
|
|
68
|
+
*/
|
|
69
|
+
findActiveDuplicate(db, input, error) {
|
|
70
|
+
if (!isSqliteUniqueViolation(error) || input.uniqueKey == null) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
return db
|
|
74
|
+
.select()
|
|
75
|
+
.from(schema_1.jobs)
|
|
76
|
+
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.jobs.name, input.name), (0, drizzle_orm_1.eq)(schema_1.jobs.uniqueKey, input.uniqueKey)))
|
|
77
|
+
.get();
|
|
78
|
+
}
|
|
79
|
+
claimBatch(db, cfg) {
|
|
80
|
+
const now = new Date();
|
|
81
|
+
const nowIso = now.toISOString();
|
|
82
|
+
const stuckCutoff = new Date(now.getTime() - cfg.stuckTimeoutMs).toISOString();
|
|
83
|
+
const rows = db.transaction((tx) => {
|
|
84
|
+
const candidates = tx
|
|
85
|
+
.select({ id: schema_1.jobs.id })
|
|
86
|
+
.from(schema_1.jobs)
|
|
87
|
+
.where((0, drizzle_orm_1.or)((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.jobs.status, 'pending'), (0, drizzle_orm_1.lte)(schema_1.jobs.availableAt, nowIso)), (0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.jobs.status, 'processing'), (0, drizzle_orm_1.lte)(schema_1.jobs.claimedAt, stuckCutoff))))
|
|
88
|
+
.orderBy((0, drizzle_orm_1.desc)(schema_1.jobs.priority), (0, drizzle_orm_1.asc)(schema_1.jobs.availableAt))
|
|
89
|
+
.limit(cfg.batchSize)
|
|
90
|
+
.all();
|
|
91
|
+
if (candidates.length === 0)
|
|
92
|
+
return [];
|
|
93
|
+
const ids = candidates.map((c) => c.id);
|
|
94
|
+
tx.update(schema_1.jobs)
|
|
95
|
+
.set({ status: 'processing', claimedAt: nowIso, claimedBy: cfg.workerInstanceId })
|
|
96
|
+
.where((0, drizzle_orm_1.inArray)(schema_1.jobs.id, ids))
|
|
97
|
+
.run();
|
|
98
|
+
return tx
|
|
99
|
+
.select()
|
|
100
|
+
.from(schema_1.jobs)
|
|
101
|
+
.where((0, drizzle_orm_1.inArray)(schema_1.jobs.id, ids))
|
|
102
|
+
.orderBy((0, drizzle_orm_1.desc)(schema_1.jobs.priority), (0, drizzle_orm_1.asc)(schema_1.jobs.availableAt))
|
|
103
|
+
.all();
|
|
104
|
+
});
|
|
105
|
+
return Promise.resolve(rows);
|
|
106
|
+
}
|
|
107
|
+
markCompleted(db, id) {
|
|
108
|
+
db
|
|
109
|
+
.update(schema_1.jobs)
|
|
110
|
+
.set({
|
|
111
|
+
status: 'completed',
|
|
112
|
+
processedAt: new Date().toISOString(),
|
|
113
|
+
lastError: null,
|
|
114
|
+
// Terminal → release the active-dedup key.
|
|
115
|
+
uniqueKey: null,
|
|
116
|
+
})
|
|
117
|
+
.where((0, drizzle_orm_1.eq)(schema_1.jobs.id, id))
|
|
118
|
+
.run();
|
|
119
|
+
return Promise.resolve();
|
|
120
|
+
}
|
|
121
|
+
retry(db, id, delayMs, lastError) {
|
|
122
|
+
const nextAvailable = new Date(Date.now() + delayMs).toISOString();
|
|
123
|
+
db
|
|
124
|
+
.update(schema_1.jobs)
|
|
125
|
+
.set({
|
|
126
|
+
status: 'pending',
|
|
127
|
+
attempts: (0, drizzle_orm_1.sql) `${schema_1.jobs.attempts} + 1`,
|
|
128
|
+
availableAt: nextAvailable,
|
|
129
|
+
claimedAt: null,
|
|
130
|
+
claimedBy: null,
|
|
131
|
+
lastError: lastError ?? null,
|
|
132
|
+
// Still active → the uniqueKey stays claimed.
|
|
133
|
+
})
|
|
134
|
+
.where((0, drizzle_orm_1.eq)(schema_1.jobs.id, id))
|
|
135
|
+
.run();
|
|
136
|
+
return Promise.resolve();
|
|
137
|
+
}
|
|
138
|
+
markFailed(db, id, reason) {
|
|
139
|
+
db
|
|
140
|
+
.update(schema_1.jobs)
|
|
141
|
+
.set({
|
|
142
|
+
status: 'failed',
|
|
143
|
+
attempts: (0, drizzle_orm_1.sql) `${schema_1.jobs.attempts} + 1`,
|
|
144
|
+
lastError: reason,
|
|
145
|
+
processedAt: new Date().toISOString(),
|
|
146
|
+
// Terminal → release the active-dedup key.
|
|
147
|
+
uniqueKey: null,
|
|
148
|
+
})
|
|
149
|
+
.where((0, drizzle_orm_1.eq)(schema_1.jobs.id, id))
|
|
150
|
+
.run();
|
|
151
|
+
return Promise.resolve();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.SqliteJobStore = SqliteJobStore;
|
|
155
|
+
//# sourceMappingURL=job-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-store.js","sourceRoot":"","sources":["../../../dialects/sqlite/job-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite `jobs` table. Add it to your Drizzle schema and generate a migration
|
|
3
|
+
* with drizzle-kit.
|
|
4
|
+
*
|
|
5
|
+
* The **full** unique index on `(name, unique_key)` is the active-dedup
|
|
6
|
+
* primitive: SQL treats `NULL` as distinct in unique indexes, so jobs without
|
|
7
|
+
* a `uniqueKey` never collide, and — because terminal transitions clear
|
|
8
|
+
* `unique_key` to `NULL` — uniqueness only constrains ACTIVE jobs. The same
|
|
9
|
+
* full-index shape works on every dialect (no partial indexes needed). The
|
|
10
|
+
* `(status, available_at)` index serves the claimer's batch query.
|
|
11
|
+
*/
|
|
12
|
+
export declare const jobs: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
13
|
+
name: "jobs";
|
|
14
|
+
schema: undefined;
|
|
15
|
+
columns: {
|
|
16
|
+
id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
17
|
+
name: "id";
|
|
18
|
+
tableName: "jobs";
|
|
19
|
+
dataType: "string";
|
|
20
|
+
columnType: "SQLiteText";
|
|
21
|
+
data: string;
|
|
22
|
+
driverParam: string;
|
|
23
|
+
notNull: true;
|
|
24
|
+
hasDefault: false;
|
|
25
|
+
isPrimaryKey: true;
|
|
26
|
+
isAutoincrement: false;
|
|
27
|
+
hasRuntimeDefault: false;
|
|
28
|
+
enumValues: [string, ...string[]];
|
|
29
|
+
baseColumn: never;
|
|
30
|
+
identity: undefined;
|
|
31
|
+
generated: undefined;
|
|
32
|
+
}, {}, {
|
|
33
|
+
length: number | undefined;
|
|
34
|
+
}>;
|
|
35
|
+
name: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
36
|
+
name: "name";
|
|
37
|
+
tableName: "jobs";
|
|
38
|
+
dataType: "string";
|
|
39
|
+
columnType: "SQLiteText";
|
|
40
|
+
data: string;
|
|
41
|
+
driverParam: string;
|
|
42
|
+
notNull: true;
|
|
43
|
+
hasDefault: false;
|
|
44
|
+
isPrimaryKey: false;
|
|
45
|
+
isAutoincrement: false;
|
|
46
|
+
hasRuntimeDefault: false;
|
|
47
|
+
enumValues: [string, ...string[]];
|
|
48
|
+
baseColumn: never;
|
|
49
|
+
identity: undefined;
|
|
50
|
+
generated: undefined;
|
|
51
|
+
}, {}, {
|
|
52
|
+
length: number | undefined;
|
|
53
|
+
}>;
|
|
54
|
+
payload: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
55
|
+
name: "payload";
|
|
56
|
+
tableName: "jobs";
|
|
57
|
+
dataType: "json";
|
|
58
|
+
columnType: "SQLiteTextJson";
|
|
59
|
+
data: Record<string, unknown>;
|
|
60
|
+
driverParam: string;
|
|
61
|
+
notNull: true;
|
|
62
|
+
hasDefault: false;
|
|
63
|
+
isPrimaryKey: false;
|
|
64
|
+
isAutoincrement: false;
|
|
65
|
+
hasRuntimeDefault: false;
|
|
66
|
+
enumValues: undefined;
|
|
67
|
+
baseColumn: never;
|
|
68
|
+
identity: undefined;
|
|
69
|
+
generated: undefined;
|
|
70
|
+
}, {}, {
|
|
71
|
+
$type: Record<string, unknown>;
|
|
72
|
+
}>;
|
|
73
|
+
status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
74
|
+
name: "status";
|
|
75
|
+
tableName: "jobs";
|
|
76
|
+
dataType: "string";
|
|
77
|
+
columnType: "SQLiteText";
|
|
78
|
+
data: "pending" | "processing" | "completed" | "failed";
|
|
79
|
+
driverParam: string;
|
|
80
|
+
notNull: true;
|
|
81
|
+
hasDefault: false;
|
|
82
|
+
isPrimaryKey: false;
|
|
83
|
+
isAutoincrement: false;
|
|
84
|
+
hasRuntimeDefault: false;
|
|
85
|
+
enumValues: [string, ...string[]];
|
|
86
|
+
baseColumn: never;
|
|
87
|
+
identity: undefined;
|
|
88
|
+
generated: undefined;
|
|
89
|
+
}, {}, {
|
|
90
|
+
length: number | undefined;
|
|
91
|
+
$type: "pending" | "processing" | "completed" | "failed";
|
|
92
|
+
}>;
|
|
93
|
+
attempts: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
94
|
+
name: "attempts";
|
|
95
|
+
tableName: "jobs";
|
|
96
|
+
dataType: "number";
|
|
97
|
+
columnType: "SQLiteInteger";
|
|
98
|
+
data: number;
|
|
99
|
+
driverParam: number;
|
|
100
|
+
notNull: true;
|
|
101
|
+
hasDefault: true;
|
|
102
|
+
isPrimaryKey: false;
|
|
103
|
+
isAutoincrement: false;
|
|
104
|
+
hasRuntimeDefault: false;
|
|
105
|
+
enumValues: undefined;
|
|
106
|
+
baseColumn: never;
|
|
107
|
+
identity: undefined;
|
|
108
|
+
generated: undefined;
|
|
109
|
+
}, {}, {}>;
|
|
110
|
+
maxAttempts: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
111
|
+
name: "max_attempts";
|
|
112
|
+
tableName: "jobs";
|
|
113
|
+
dataType: "number";
|
|
114
|
+
columnType: "SQLiteInteger";
|
|
115
|
+
data: number;
|
|
116
|
+
driverParam: number;
|
|
117
|
+
notNull: true;
|
|
118
|
+
hasDefault: true;
|
|
119
|
+
isPrimaryKey: false;
|
|
120
|
+
isAutoincrement: false;
|
|
121
|
+
hasRuntimeDefault: false;
|
|
122
|
+
enumValues: undefined;
|
|
123
|
+
baseColumn: never;
|
|
124
|
+
identity: undefined;
|
|
125
|
+
generated: undefined;
|
|
126
|
+
}, {}, {}>;
|
|
127
|
+
uniqueKey: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
128
|
+
name: "unique_key";
|
|
129
|
+
tableName: "jobs";
|
|
130
|
+
dataType: "string";
|
|
131
|
+
columnType: "SQLiteText";
|
|
132
|
+
data: string;
|
|
133
|
+
driverParam: string;
|
|
134
|
+
notNull: false;
|
|
135
|
+
hasDefault: false;
|
|
136
|
+
isPrimaryKey: false;
|
|
137
|
+
isAutoincrement: false;
|
|
138
|
+
hasRuntimeDefault: false;
|
|
139
|
+
enumValues: [string, ...string[]];
|
|
140
|
+
baseColumn: never;
|
|
141
|
+
identity: undefined;
|
|
142
|
+
generated: undefined;
|
|
143
|
+
}, {}, {
|
|
144
|
+
length: number | undefined;
|
|
145
|
+
}>;
|
|
146
|
+
priority: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
147
|
+
name: "priority";
|
|
148
|
+
tableName: "jobs";
|
|
149
|
+
dataType: "number";
|
|
150
|
+
columnType: "SQLiteInteger";
|
|
151
|
+
data: number;
|
|
152
|
+
driverParam: number;
|
|
153
|
+
notNull: true;
|
|
154
|
+
hasDefault: true;
|
|
155
|
+
isPrimaryKey: false;
|
|
156
|
+
isAutoincrement: false;
|
|
157
|
+
hasRuntimeDefault: false;
|
|
158
|
+
enumValues: undefined;
|
|
159
|
+
baseColumn: never;
|
|
160
|
+
identity: undefined;
|
|
161
|
+
generated: undefined;
|
|
162
|
+
}, {}, {}>;
|
|
163
|
+
availableAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
164
|
+
name: "available_at";
|
|
165
|
+
tableName: "jobs";
|
|
166
|
+
dataType: "string";
|
|
167
|
+
columnType: "SQLiteText";
|
|
168
|
+
data: string;
|
|
169
|
+
driverParam: string;
|
|
170
|
+
notNull: true;
|
|
171
|
+
hasDefault: false;
|
|
172
|
+
isPrimaryKey: false;
|
|
173
|
+
isAutoincrement: false;
|
|
174
|
+
hasRuntimeDefault: false;
|
|
175
|
+
enumValues: [string, ...string[]];
|
|
176
|
+
baseColumn: never;
|
|
177
|
+
identity: undefined;
|
|
178
|
+
generated: undefined;
|
|
179
|
+
}, {}, {
|
|
180
|
+
length: number | undefined;
|
|
181
|
+
}>;
|
|
182
|
+
claimedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
183
|
+
name: "claimed_at";
|
|
184
|
+
tableName: "jobs";
|
|
185
|
+
dataType: "string";
|
|
186
|
+
columnType: "SQLiteText";
|
|
187
|
+
data: string;
|
|
188
|
+
driverParam: string;
|
|
189
|
+
notNull: false;
|
|
190
|
+
hasDefault: false;
|
|
191
|
+
isPrimaryKey: false;
|
|
192
|
+
isAutoincrement: false;
|
|
193
|
+
hasRuntimeDefault: false;
|
|
194
|
+
enumValues: [string, ...string[]];
|
|
195
|
+
baseColumn: never;
|
|
196
|
+
identity: undefined;
|
|
197
|
+
generated: undefined;
|
|
198
|
+
}, {}, {
|
|
199
|
+
length: number | undefined;
|
|
200
|
+
}>;
|
|
201
|
+
claimedBy: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
202
|
+
name: "claimed_by";
|
|
203
|
+
tableName: "jobs";
|
|
204
|
+
dataType: "string";
|
|
205
|
+
columnType: "SQLiteText";
|
|
206
|
+
data: string;
|
|
207
|
+
driverParam: string;
|
|
208
|
+
notNull: false;
|
|
209
|
+
hasDefault: false;
|
|
210
|
+
isPrimaryKey: false;
|
|
211
|
+
isAutoincrement: false;
|
|
212
|
+
hasRuntimeDefault: false;
|
|
213
|
+
enumValues: [string, ...string[]];
|
|
214
|
+
baseColumn: never;
|
|
215
|
+
identity: undefined;
|
|
216
|
+
generated: undefined;
|
|
217
|
+
}, {}, {
|
|
218
|
+
length: number | undefined;
|
|
219
|
+
}>;
|
|
220
|
+
processedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
221
|
+
name: "processed_at";
|
|
222
|
+
tableName: "jobs";
|
|
223
|
+
dataType: "string";
|
|
224
|
+
columnType: "SQLiteText";
|
|
225
|
+
data: string;
|
|
226
|
+
driverParam: string;
|
|
227
|
+
notNull: false;
|
|
228
|
+
hasDefault: false;
|
|
229
|
+
isPrimaryKey: false;
|
|
230
|
+
isAutoincrement: false;
|
|
231
|
+
hasRuntimeDefault: false;
|
|
232
|
+
enumValues: [string, ...string[]];
|
|
233
|
+
baseColumn: never;
|
|
234
|
+
identity: undefined;
|
|
235
|
+
generated: undefined;
|
|
236
|
+
}, {}, {
|
|
237
|
+
length: number | undefined;
|
|
238
|
+
}>;
|
|
239
|
+
lastError: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
240
|
+
name: "last_error";
|
|
241
|
+
tableName: "jobs";
|
|
242
|
+
dataType: "string";
|
|
243
|
+
columnType: "SQLiteText";
|
|
244
|
+
data: string;
|
|
245
|
+
driverParam: string;
|
|
246
|
+
notNull: false;
|
|
247
|
+
hasDefault: false;
|
|
248
|
+
isPrimaryKey: false;
|
|
249
|
+
isAutoincrement: false;
|
|
250
|
+
hasRuntimeDefault: false;
|
|
251
|
+
enumValues: [string, ...string[]];
|
|
252
|
+
baseColumn: never;
|
|
253
|
+
identity: undefined;
|
|
254
|
+
generated: undefined;
|
|
255
|
+
}, {}, {
|
|
256
|
+
length: number | undefined;
|
|
257
|
+
}>;
|
|
258
|
+
createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
259
|
+
name: "created_at";
|
|
260
|
+
tableName: "jobs";
|
|
261
|
+
dataType: "string";
|
|
262
|
+
columnType: "SQLiteText";
|
|
263
|
+
data: string;
|
|
264
|
+
driverParam: string;
|
|
265
|
+
notNull: true;
|
|
266
|
+
hasDefault: false;
|
|
267
|
+
isPrimaryKey: false;
|
|
268
|
+
isAutoincrement: false;
|
|
269
|
+
hasRuntimeDefault: false;
|
|
270
|
+
enumValues: [string, ...string[]];
|
|
271
|
+
baseColumn: never;
|
|
272
|
+
identity: undefined;
|
|
273
|
+
generated: undefined;
|
|
274
|
+
}, {}, {
|
|
275
|
+
length: number | undefined;
|
|
276
|
+
}>;
|
|
277
|
+
};
|
|
278
|
+
dialect: "sqlite";
|
|
279
|
+
}>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.jobs = void 0;
|
|
4
|
+
const sqlite_core_1 = require("drizzle-orm/sqlite-core");
|
|
5
|
+
/**
|
|
6
|
+
* SQLite `jobs` table. Add it to your Drizzle schema and generate a migration
|
|
7
|
+
* with drizzle-kit.
|
|
8
|
+
*
|
|
9
|
+
* The **full** unique index on `(name, unique_key)` is the active-dedup
|
|
10
|
+
* primitive: SQL treats `NULL` as distinct in unique indexes, so jobs without
|
|
11
|
+
* a `uniqueKey` never collide, and — because terminal transitions clear
|
|
12
|
+
* `unique_key` to `NULL` — uniqueness only constrains ACTIVE jobs. The same
|
|
13
|
+
* full-index shape works on every dialect (no partial indexes needed). The
|
|
14
|
+
* `(status, available_at)` index serves the claimer's batch query.
|
|
15
|
+
*/
|
|
16
|
+
exports.jobs = (0, sqlite_core_1.sqliteTable)('jobs', {
|
|
17
|
+
id: (0, sqlite_core_1.text)('id').primaryKey(),
|
|
18
|
+
name: (0, sqlite_core_1.text)('name').notNull(),
|
|
19
|
+
payload: (0, sqlite_core_1.text)('payload', { mode: 'json' })
|
|
20
|
+
.$type()
|
|
21
|
+
.notNull(),
|
|
22
|
+
status: (0, sqlite_core_1.text)('status').$type().notNull(),
|
|
23
|
+
attempts: (0, sqlite_core_1.integer)('attempts').notNull().default(0),
|
|
24
|
+
maxAttempts: (0, sqlite_core_1.integer)('max_attempts').notNull().default(10),
|
|
25
|
+
uniqueKey: (0, sqlite_core_1.text)('unique_key'),
|
|
26
|
+
priority: (0, sqlite_core_1.integer)('priority').notNull().default(0),
|
|
27
|
+
availableAt: (0, sqlite_core_1.text)('available_at').notNull(),
|
|
28
|
+
claimedAt: (0, sqlite_core_1.text)('claimed_at'),
|
|
29
|
+
claimedBy: (0, sqlite_core_1.text)('claimed_by'),
|
|
30
|
+
processedAt: (0, sqlite_core_1.text)('processed_at'),
|
|
31
|
+
lastError: (0, sqlite_core_1.text)('last_error'),
|
|
32
|
+
createdAt: (0, sqlite_core_1.text)('created_at').notNull(),
|
|
33
|
+
}, (table) => [
|
|
34
|
+
(0, sqlite_core_1.uniqueIndex)('jobs_name_unique_key_unique').on(table.name, table.uniqueKey),
|
|
35
|
+
(0, sqlite_core_1.index)('jobs_status_available_idx').on(table.status, table.availableAt),
|
|
36
|
+
]);
|
|
37
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../dialects/sqlite/schema.ts"],"names":[],"mappings":";;;AAAA,yDAMiC;AAGjC;;;;;;;;;;GAUG;AACU,QAAA,IAAI,GAAG,IAAA,yBAAW,EAC7B,MAAM,EACN;IACE,EAAE,EAAE,IAAA,kBAAI,EAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,IAAI,EAAE,IAAA,kBAAI,EAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,OAAO,EAAE,IAAA,kBAAI,EAAC,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SACvC,KAAK,EAA2B;SAChC,OAAO,EAAE;IACZ,MAAM,EAAE,IAAA,kBAAI,EAAC,QAAQ,CAAC,CAAC,KAAK,EAAa,CAAC,OAAO,EAAE;IACnD,QAAQ,EAAE,IAAA,qBAAO,EAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,WAAW,EAAE,IAAA,qBAAO,EAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1D,SAAS,EAAE,IAAA,kBAAI,EAAC,YAAY,CAAC;IAC7B,QAAQ,EAAE,IAAA,qBAAO,EAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,WAAW,EAAE,IAAA,kBAAI,EAAC,cAAc,CAAC,CAAC,OAAO,EAAE;IAC3C,SAAS,EAAE,IAAA,kBAAI,EAAC,YAAY,CAAC;IAC7B,SAAS,EAAE,IAAA,kBAAI,EAAC,YAAY,CAAC;IAC7B,WAAW,EAAE,IAAA,kBAAI,EAAC,cAAc,CAAC;IACjC,SAAS,EAAE,IAAA,kBAAI,EAAC,YAAY,CAAC;IAC7B,SAAS,EAAE,IAAA,kBAAI,EAAC,YAAY,CAAC,CAAC,OAAO,EAAE;CACxC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,IAAA,yBAAW,EAAC,6BAA6B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1E,IAAA,mBAAK,EAAC,2BAA2B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC;CACvE,CACF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves when an enqueued job becomes due.
|
|
3
|
+
*
|
|
4
|
+
* - `runAt` and `delayMs` are **mutually exclusive** — both set throws, so a
|
|
5
|
+
* silent precedence rule can never mask a caller bug.
|
|
6
|
+
* - `runAt` wins as the absolute time; `delayMs` counts from now; neither
|
|
7
|
+
* means "due immediately".
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveAvailableAt(input: {
|
|
10
|
+
runAt?: Date;
|
|
11
|
+
delayMs?: number;
|
|
12
|
+
}): Date;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Shared enqueue-input resolution, used by every dialect store so the
|
|
3
|
+
// runAt/delayMs contract is identical no matter which store executes it.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.resolveAvailableAt = resolveAvailableAt;
|
|
6
|
+
/**
|
|
7
|
+
* Resolves when an enqueued job becomes due.
|
|
8
|
+
*
|
|
9
|
+
* - `runAt` and `delayMs` are **mutually exclusive** — both set throws, so a
|
|
10
|
+
* silent precedence rule can never mask a caller bug.
|
|
11
|
+
* - `runAt` wins as the absolute time; `delayMs` counts from now; neither
|
|
12
|
+
* means "due immediately".
|
|
13
|
+
*/
|
|
14
|
+
function resolveAvailableAt(input) {
|
|
15
|
+
if (input.runAt !== undefined && input.delayMs !== undefined) {
|
|
16
|
+
throw new Error('EnqueueJobInput: runAt and delayMs are mutually exclusive — set at most one.');
|
|
17
|
+
}
|
|
18
|
+
if (input.runAt !== undefined) {
|
|
19
|
+
return input.runAt;
|
|
20
|
+
}
|
|
21
|
+
if (input.delayMs !== undefined) {
|
|
22
|
+
return new Date(Date.now() + input.delayMs);
|
|
23
|
+
}
|
|
24
|
+
return new Date();
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=enqueue-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enqueue-input.js","sourceRoot":"","sources":["../enqueue-input.ts"],"names":[],"mappings":";AAAA,sEAAsE;AACtE,yEAAyE;;AAUzE,gDAaC;AArBD;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAAC,KAAyC;IAC1E,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,IAAI,EAAE,CAAC;AACpB,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signals a transient failure: the job could not complete now but a later
|
|
3
|
+
* attempt may succeed. `delayMs`, when set, overrides the claimer's jittered
|
|
4
|
+
* exponential backoff for the next attempt (e.g. a handler-supplied
|
|
5
|
+
* retry-after).
|
|
6
|
+
*/
|
|
7
|
+
export declare class RetryableError extends Error {
|
|
8
|
+
readonly delayMs?: number | undefined;
|
|
9
|
+
constructor(message: string, delayMs?: number | undefined);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Signals a non-recoverable failure: retrying can never succeed (e.g. no
|
|
13
|
+
* handler registered for the job name, or a malformed payload). The claimer
|
|
14
|
+
* marks the job failed immediately rather than burning retry attempts.
|
|
15
|
+
*/
|
|
16
|
+
export declare class PermanentError extends Error {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// The retry vocabulary handlers use to steer the claimer. It is deliberately
|
|
3
|
+
// dependency-free (no Nest, no Drizzle) so handlers, stores, and tests can all
|
|
4
|
+
// throw these without importing anything heavier than this module.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PermanentError = exports.RetryableError = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Signals a transient failure: the job could not complete now but a later
|
|
9
|
+
* attempt may succeed. `delayMs`, when set, overrides the claimer's jittered
|
|
10
|
+
* exponential backoff for the next attempt (e.g. a handler-supplied
|
|
11
|
+
* retry-after).
|
|
12
|
+
*/
|
|
13
|
+
class RetryableError extends Error {
|
|
14
|
+
constructor(message, delayMs) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.delayMs = delayMs;
|
|
17
|
+
this.name = 'RetryableError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.RetryableError = RetryableError;
|
|
21
|
+
/**
|
|
22
|
+
* Signals a non-recoverable failure: retrying can never succeed (e.g. no
|
|
23
|
+
* handler registered for the job name, or a malformed payload). The claimer
|
|
24
|
+
* marks the job failed immediately rather than burning retry attempts.
|
|
25
|
+
*/
|
|
26
|
+
class PermanentError extends Error {
|
|
27
|
+
constructor(message) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.name = 'PermanentError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.PermanentError = PermanentError;
|
|
33
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../errors.ts"],"names":[],"mappings":";AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,mEAAmE;;;AAEnE;;;;;GAKG;AACH,MAAa,cAAe,SAAQ,KAAK;IACvC,YACE,OAAe,EACN,OAAgB;QAEzB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,YAAO,GAAP,OAAO,CAAS;QAGzB,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AARD,wCAQC;AAED;;;;GAIG;AACH,MAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AALD,wCAKC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './errors';
|
|
2
|
+
export * from './interfaces';
|
|
3
|
+
export * from './tokens';
|
|
4
|
+
export * from './enqueue-input';
|
|
5
|
+
export * from './job-handler.decorator';
|
|
6
|
+
export * from './jobs-handler.explorer';
|
|
7
|
+
export * from './jobs.service';
|
|
8
|
+
export * from './jobs-claimer.service';
|
|
9
|
+
export * from './jobs-worker';
|
|
10
|
+
export * from './jobs.module';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// Public entrypoint for @nest-native/jobs (core engine).
|
|
18
|
+
// Dialect-specific stores + table definitions ship from their own modules
|
|
19
|
+
// (./sqlite, ./postgres, ./mysql); this barrel is the dialect-agnostic engine.
|
|
20
|
+
__exportStar(require("./errors"), exports);
|
|
21
|
+
__exportStar(require("./interfaces"), exports);
|
|
22
|
+
__exportStar(require("./tokens"), exports);
|
|
23
|
+
__exportStar(require("./enqueue-input"), exports);
|
|
24
|
+
__exportStar(require("./job-handler.decorator"), exports);
|
|
25
|
+
__exportStar(require("./jobs-handler.explorer"), exports);
|
|
26
|
+
__exportStar(require("./jobs.service"), exports);
|
|
27
|
+
__exportStar(require("./jobs-claimer.service"), exports);
|
|
28
|
+
__exportStar(require("./jobs-worker"), exports);
|
|
29
|
+
__exportStar(require("./jobs.module"), exports);
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAyD;AACzD,0EAA0E;AAC1E,+EAA+E;AAC/E,2CAAyB;AACzB,+CAA6B;AAC7B,2CAAyB;AACzB,kDAAgC;AAChC,0DAAwC;AACxC,0DAAwC;AACxC,iDAA+B;AAC/B,yDAAuC;AACvC,gDAA8B;AAC9B,gDAA8B"}
|