@nest-native/jobs 0.1.0 → 0.2.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 +33 -5
- package/dist/dialects/mysql/index.d.ts +1 -0
- package/dist/dialects/mysql/index.js +1 -0
- package/dist/dialects/mysql/index.js.map +1 -1
- package/dist/dialects/mysql/schedule-store.d.ts +36 -0
- package/dist/dialects/mysql/schedule-store.js +185 -0
- package/dist/dialects/mysql/schedule-store.js.map +1 -0
- package/dist/dialects/mysql/schema.d.ts +274 -0
- package/dist/dialects/mysql/schema.js +31 -1
- package/dist/dialects/mysql/schema.js.map +1 -1
- package/dist/dialects/postgres/index.d.ts +1 -0
- package/dist/dialects/postgres/index.js +1 -0
- package/dist/dialects/postgres/index.js.map +1 -1
- package/dist/dialects/postgres/schedule-store.d.ts +22 -0
- package/dist/dialects/postgres/schedule-store.js +143 -0
- package/dist/dialects/postgres/schedule-store.js.map +1 -0
- package/dist/dialects/postgres/schema.d.ts +273 -0
- package/dist/dialects/postgres/schema.js +30 -1
- package/dist/dialects/postgres/schema.js.map +1 -1
- package/dist/dialects/sqlite/index.d.ts +1 -0
- package/dist/dialects/sqlite/index.js +2 -1
- package/dist/dialects/sqlite/index.js.map +1 -1
- package/dist/dialects/sqlite/schedule-store.d.ts +23 -0
- package/dist/dialects/sqlite/schedule-store.js +153 -0
- package/dist/dialects/sqlite/schedule-store.js.map +1 -0
- package/dist/dialects/sqlite/schema.d.ts +295 -0
- package/dist/dialects/sqlite/schema.js +32 -1
- package/dist/dialects/sqlite/schema.js.map +1 -1
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +15 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +137 -0
- package/dist/job-schedules.service.d.ts +44 -0
- package/dist/job-schedules.service.js +125 -0
- package/dist/job-schedules.service.js.map +1 -0
- package/dist/jobs-claimer.service.d.ts +16 -2
- package/dist/jobs-claimer.service.js +71 -2
- package/dist/jobs-claimer.service.js.map +1 -1
- package/dist/jobs.module.d.ts +3 -1
- package/dist/jobs.module.js +17 -2
- package/dist/jobs.module.js.map +1 -1
- package/dist/schedule-planner.d.ts +30 -0
- package/dist/schedule-planner.js +58 -0
- package/dist/schedule-planner.js.map +1 -0
- package/dist/testing/harness.js +2 -1
- package/dist/testing/harness.js.map +1 -1
- package/dist/tokens.d.ts +5 -0
- package/dist/tokens.js +6 -1
- package/dist/tokens.js.map +1 -1
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -21,7 +21,8 @@ Most NestJS apps grow a first background job long before they need a queueing *s
|
|
|
21
21
|
- **Transactional enqueue** — `enqueue()` inserts the job row *inside your business transaction* (via [`@nestjs-cls/transactional`](https://www.npmjs.com/package/@nestjs-cls/transactional)). The job exists if and only if your writes committed.
|
|
22
22
|
- **Nest-native execution** — declare a class with `@JobHandler('email.welcome')`, register it as a provider, and the claimer dispatches to it with full DI. Handlers are discovered at bootstrap; duplicate names throw at startup.
|
|
23
23
|
- **Retries, delays, priorities, unique jobs** — jittered exponential backoff (or `RetryableError`'s explicit `delayMs`), `PermanentError` to fail fast, `runAt`/`delayMs` scheduling, `priority` ordering, and `uniqueKey` dedup among active jobs.
|
|
24
|
-
- **
|
|
24
|
+
- **DB-stored cron schedules** — recurring enqueue driven by a `job_schedules` row: survives restarts, safe across instances (atomic claim), runtime-editable via `JobSchedulesService`. Missed occurrences are skipped (at most one catch-up).
|
|
25
|
+
- **One runtime dependency** — [`croner`](https://www.npmjs.com/package/croner) does the cron math; everything else (Nest, Drizzle, your driver) is a peer you already installed.
|
|
25
26
|
|
|
26
27
|
## Install
|
|
27
28
|
|
|
@@ -90,6 +91,34 @@ Delivery is **at-least-once**: a worker crash mid-job means the row is reclaimed
|
|
|
90
91
|
|
|
91
92
|
`uniqueKey` means "unique among **active** jobs", identically on all three dialects: a full unique index on `(name, unique_key)`, and terminal transitions (`completed`, `failed`) clear the key. Enqueueing a duplicate `(name, uniqueKey)` while one is pending/processing is a **no-op that returns the existing row**; once that job finishes, the key is free again. Jobs without a `uniqueKey` never collide.
|
|
92
93
|
|
|
94
|
+
## Cron schedules (0.2+)
|
|
95
|
+
|
|
96
|
+
Recurring work driven by rows in your database — survives restarts, safe
|
|
97
|
+
across instances (atomic claim), runtime-editable. Opt in by adding the
|
|
98
|
+
`jobSchedules` table to your Drizzle schema and passing a schedule store:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
JobsModule.forRoot({
|
|
102
|
+
drizzleInstanceToken: DRIZZLE,
|
|
103
|
+
store: new SqliteJobStore(),
|
|
104
|
+
scheduleStore: new SqliteScheduleStore(), // opt-in: omit and nothing changes
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
schedules.upsert({
|
|
110
|
+
name: 'nightly-report', // unique identity (upsert key)
|
|
111
|
+
jobName: 'report.build', // the @JobHandler each occurrence runs
|
|
112
|
+
cron: '0 3 * * *', // croner syntax; timezone: IANA name, default UTC
|
|
113
|
+
uniqueKey: 'nightly-report', // optional: no overlap pile-up while one runs
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Firing is an atomic compare-and-swap plus the occurrence insert in one store
|
|
118
|
+
transaction — exactly one instance wins each occurrence. Missed occurrences
|
|
119
|
+
are skipped (at most one catch-up). An occurrence exhausting its retries
|
|
120
|
+
never touches the schedule. Full details: the Cron Schedules docs page.
|
|
121
|
+
|
|
93
122
|
## Honest comparison
|
|
94
123
|
|
|
95
124
|
| | BullMQ (`@nestjs/bullmq`) | pg-boss | `@nest-native/jobs` |
|
|
@@ -99,15 +128,14 @@ Delivery is **at-least-once**: a worker crash mid-job means the row is reclaimed
|
|
|
99
128
|
| Enqueue in your DB transaction | no (Redis is a second system) | yes (raw SQL in your tx) | yes — first-class, via `@nestjs-cls/transactional` |
|
|
100
129
|
| Delivery | Redis push (blocking ops) | polling + LISTEN/NOTIFY | polling claimer |
|
|
101
130
|
| Throughput | very high | high | right-sized — polling batches, fine for most apps' background work |
|
|
102
|
-
| Repeatable / cron jobs | yes | yes |
|
|
131
|
+
| Repeatable / cron jobs | yes | yes | yes — DB-stored schedules (`JobSchedulesService`) |
|
|
103
132
|
| Dashboards, rate limiting | yes | partial | no |
|
|
104
|
-
| Runtime dependencies | Redis server + client | `pg` |
|
|
133
|
+
| Runtime dependencies | Redis server + client | `pg` | one — `croner` (the rest are peers you already have) |
|
|
105
134
|
|
|
106
135
|
If you need tens of thousands of jobs per second, sandboxed processors, or a dashboard, use BullMQ — it is excellent at that. If you run Postgres without Nest, pg-boss is battle-tested. This library is for the large middle: NestJS + Drizzle apps that want reliable background jobs **without operating another system**.
|
|
107
136
|
|
|
108
|
-
## Non-goals (v0.
|
|
137
|
+
## Non-goals (v0.2)
|
|
109
138
|
|
|
110
|
-
- **Cron / repeatable jobs** — `@nestjs/schedule` already does this well; combine it with `enqueue()` if you want scheduled work to flow through the queue.
|
|
111
139
|
- **Dashboards / UI**, **rate limiting**, **concurrency groups**.
|
|
112
140
|
- **LISTEN/NOTIFY push** — the claimer polls; `pollIntervalMs` is your latency knob.
|
|
113
141
|
- **Redis-class throughput** — this is a polling claimer over your relational DB, by design.
|
|
@@ -18,4 +18,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
// the `jobs` table definition + the MySQL store.
|
|
19
19
|
__exportStar(require("./schema"), exports);
|
|
20
20
|
__exportStar(require("./job-store"), exports);
|
|
21
|
+
__exportStar(require("./schedule-store"), exports);
|
|
21
22
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../dialects/mysql/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAwD;AACxD,iDAAiD;AACjD,2CAAyB;AACzB,8CAA4B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../dialects/mysql/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAwD;AACxD,iDAAiD;AACjD,2CAAyB;AACzB,8CAA4B;AAC5B,mDAAiC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ResolvedScheduleUpsert, ScheduleClaim, ScheduleClaimResult, ScheduleRow, ScheduleStore } from '../../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* MySQL (mysql2) schedule store. Every method is **asynchronous**, mirroring
|
|
4
|
+
* {@link MysqlJobStore}. MySQL's `INSERT` has no `RETURNING`, so writes use
|
|
5
|
+
* client-generated UUID ids and read the canonical row back by id/name.
|
|
6
|
+
*
|
|
7
|
+
* `claimAndEnqueue` runs the compare-and-swap on `next_run_at` and the
|
|
8
|
+
* occurrence insert in ONE transaction. The insert is made conflict-tolerant
|
|
9
|
+
* with the `ON DUPLICATE KEY UPDATE id = id` no-op idiom: an active occurrence
|
|
10
|
+
* holding the schedule's `(name, unique_key)` suppresses the new one (the
|
|
11
|
+
* overlap guard) without raising, and the schedule row still advances.
|
|
12
|
+
* Whether the insert happened is detected by reading our generated id back.
|
|
13
|
+
*/
|
|
14
|
+
export declare class MysqlScheduleStore implements ScheduleStore {
|
|
15
|
+
/**
|
|
16
|
+
* MySQL cannot express the preservation rules atomically: ON DUPLICATE KEY
|
|
17
|
+
* UPDATE evaluates assignments left-to-right with later references seeing
|
|
18
|
+
* already-updated columns, and Drizzle controls the emission order — a CASE
|
|
19
|
+
* reading the stored cron is silently defeated (caught by the gated
|
|
20
|
+
* real-MySQL test). So the mysql upsert is an explicit read-then-write:
|
|
21
|
+
* insert when absent (recovering from a lost first-upsert race via the
|
|
22
|
+
* ER_DUP_ENTRY dedup), otherwise compute the preserved values in JS and
|
|
23
|
+
* UPDATE. The admin-time read-modify-write race this leaves is benign —
|
|
24
|
+
* last writer wins with internally-consistent values.
|
|
25
|
+
*/
|
|
26
|
+
upsert(db: unknown, input: ResolvedScheduleUpsert): Promise<ScheduleRow>;
|
|
27
|
+
/** The insert leg of upsert; undefined when a concurrent upsert won the name. */
|
|
28
|
+
private tryInsert;
|
|
29
|
+
get(db: unknown, name: string): Promise<ScheduleRow | undefined>;
|
|
30
|
+
list(db: unknown): Promise<ScheduleRow[]>;
|
|
31
|
+
remove(db: unknown, name: string): Promise<boolean>;
|
|
32
|
+
setEnabled(db: unknown, name: string, enabled: boolean, nextRunAt: string | null, expectedUpdatedAt?: string): Promise<ScheduleRow | undefined>;
|
|
33
|
+
listDue(db: unknown, nowIso: string, limit: number): Promise<ScheduleRow[]>;
|
|
34
|
+
claimAndEnqueue(db: unknown, claim: ScheduleClaim): Promise<ScheduleClaimResult>;
|
|
35
|
+
disable(db: unknown, id: string, lastError: string): Promise<void>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MysqlScheduleStore = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
6
|
+
const job_store_1 = require("./job-store");
|
|
7
|
+
const schema_1 = require("./schema");
|
|
8
|
+
/**
|
|
9
|
+
* MySQL (mysql2) schedule store. Every method is **asynchronous**, mirroring
|
|
10
|
+
* {@link MysqlJobStore}. MySQL's `INSERT` has no `RETURNING`, so writes use
|
|
11
|
+
* client-generated UUID ids and read the canonical row back by id/name.
|
|
12
|
+
*
|
|
13
|
+
* `claimAndEnqueue` runs the compare-and-swap on `next_run_at` and the
|
|
14
|
+
* occurrence insert in ONE transaction. The insert is made conflict-tolerant
|
|
15
|
+
* with the `ON DUPLICATE KEY UPDATE id = id` no-op idiom: an active occurrence
|
|
16
|
+
* holding the schedule's `(name, unique_key)` suppresses the new one (the
|
|
17
|
+
* overlap guard) without raising, and the schedule row still advances.
|
|
18
|
+
* Whether the insert happened is detected by reading our generated id back.
|
|
19
|
+
*/
|
|
20
|
+
class MysqlScheduleStore {
|
|
21
|
+
/**
|
|
22
|
+
* MySQL cannot express the preservation rules atomically: ON DUPLICATE KEY
|
|
23
|
+
* UPDATE evaluates assignments left-to-right with later references seeing
|
|
24
|
+
* already-updated columns, and Drizzle controls the emission order — a CASE
|
|
25
|
+
* reading the stored cron is silently defeated (caught by the gated
|
|
26
|
+
* real-MySQL test). So the mysql upsert is an explicit read-then-write:
|
|
27
|
+
* insert when absent (recovering from a lost first-upsert race via the
|
|
28
|
+
* ER_DUP_ENTRY dedup), otherwise compute the preserved values in JS and
|
|
29
|
+
* UPDATE. The admin-time read-modify-write race this leaves is benign —
|
|
30
|
+
* last writer wins with internally-consistent values.
|
|
31
|
+
*/
|
|
32
|
+
async upsert(db, input) {
|
|
33
|
+
const nowIso = new Date().toISOString();
|
|
34
|
+
let existing = await this.get(db, input.name);
|
|
35
|
+
if (!existing) {
|
|
36
|
+
const inserted = await this.tryInsert(db, input, nowIso);
|
|
37
|
+
if (inserted) {
|
|
38
|
+
return inserted;
|
|
39
|
+
}
|
|
40
|
+
// Lost a concurrent first-upsert race: the row exists now — update it.
|
|
41
|
+
existing = (await this.get(db, input.name));
|
|
42
|
+
}
|
|
43
|
+
// Boot-safe preservations: an omitted `enabled` keeps the stored flag,
|
|
44
|
+
// and the stored `next_run_at` survives while cron/timezone are unchanged
|
|
45
|
+
// (a pending catch-up is not skipped; the rhythm is not perturbed).
|
|
46
|
+
const preserveNextRunAt = existing.cron === input.cron &&
|
|
47
|
+
existing.timezone === input.timezone &&
|
|
48
|
+
existing.nextRunAt !== null;
|
|
49
|
+
await db
|
|
50
|
+
.update(schema_1.jobSchedules)
|
|
51
|
+
.set({
|
|
52
|
+
jobName: input.jobName,
|
|
53
|
+
payload: input.payload,
|
|
54
|
+
cron: input.cron,
|
|
55
|
+
timezone: input.timezone,
|
|
56
|
+
enabled: input.enabled ?? existing.enabled,
|
|
57
|
+
nextRunAt: preserveNextRunAt ? existing.nextRunAt : input.nextRunAt,
|
|
58
|
+
maxAttempts: input.maxAttempts,
|
|
59
|
+
priority: input.priority,
|
|
60
|
+
uniqueKey: input.uniqueKey,
|
|
61
|
+
lastError: null,
|
|
62
|
+
updatedAt: nowIso,
|
|
63
|
+
})
|
|
64
|
+
.where((0, drizzle_orm_1.eq)(schema_1.jobSchedules.name, input.name));
|
|
65
|
+
return (await this.get(db, input.name));
|
|
66
|
+
}
|
|
67
|
+
/** The insert leg of upsert; undefined when a concurrent upsert won the name. */
|
|
68
|
+
async tryInsert(db, input, nowIso) {
|
|
69
|
+
try {
|
|
70
|
+
await db.insert(schema_1.jobSchedules).values({
|
|
71
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
72
|
+
...input,
|
|
73
|
+
enabled: input.enabled ?? true,
|
|
74
|
+
lastEnqueuedAt: null,
|
|
75
|
+
lastError: null,
|
|
76
|
+
createdAt: nowIso,
|
|
77
|
+
updatedAt: nowIso,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (!(0, job_store_1.isMysqlUniqueViolation)(error)) {
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
return this.get(db, input.name);
|
|
87
|
+
}
|
|
88
|
+
async get(db, name) {
|
|
89
|
+
const rows = await db
|
|
90
|
+
.select()
|
|
91
|
+
.from(schema_1.jobSchedules)
|
|
92
|
+
.where((0, drizzle_orm_1.eq)(schema_1.jobSchedules.name, name));
|
|
93
|
+
return rows[0];
|
|
94
|
+
}
|
|
95
|
+
async list(db) {
|
|
96
|
+
return db
|
|
97
|
+
.select()
|
|
98
|
+
.from(schema_1.jobSchedules)
|
|
99
|
+
.orderBy((0, drizzle_orm_1.asc)(schema_1.jobSchedules.name));
|
|
100
|
+
}
|
|
101
|
+
async remove(db, name) {
|
|
102
|
+
const [result] = await db
|
|
103
|
+
.delete(schema_1.jobSchedules)
|
|
104
|
+
.where((0, drizzle_orm_1.eq)(schema_1.jobSchedules.name, name));
|
|
105
|
+
return result.affectedRows > 0;
|
|
106
|
+
}
|
|
107
|
+
async setEnabled(db, name, enabled, nextRunAt, expectedUpdatedAt) {
|
|
108
|
+
const [result] = await db
|
|
109
|
+
.update(schema_1.jobSchedules)
|
|
110
|
+
.set({ enabled, nextRunAt, updatedAt: new Date().toISOString() })
|
|
111
|
+
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.jobSchedules.name, name),
|
|
112
|
+
// Optimistic guard: only write over the row version the caller read.
|
|
113
|
+
...(expectedUpdatedAt === undefined
|
|
114
|
+
? []
|
|
115
|
+
: [(0, drizzle_orm_1.eq)(schema_1.jobSchedules.updatedAt, expectedUpdatedAt)])));
|
|
116
|
+
// No RETURNING on MySQL: a zero-row update (unknown name OR guard miss)
|
|
117
|
+
// must NOT read back the untouched row as if it were updated.
|
|
118
|
+
if (result.affectedRows === 0) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
return this.get(db, name);
|
|
122
|
+
}
|
|
123
|
+
async listDue(db, nowIso, limit) {
|
|
124
|
+
return db
|
|
125
|
+
.select()
|
|
126
|
+
.from(schema_1.jobSchedules)
|
|
127
|
+
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.jobSchedules.enabled, true), (0, drizzle_orm_1.isNotNull)(schema_1.jobSchedules.nextRunAt), (0, drizzle_orm_1.lte)(schema_1.jobSchedules.nextRunAt, nowIso)))
|
|
128
|
+
.orderBy((0, drizzle_orm_1.asc)(schema_1.jobSchedules.nextRunAt))
|
|
129
|
+
.limit(limit);
|
|
130
|
+
}
|
|
131
|
+
async claimAndEnqueue(db, claim) {
|
|
132
|
+
return db.transaction(async (tx) => {
|
|
133
|
+
const [cas] = await tx
|
|
134
|
+
.update(schema_1.jobSchedules)
|
|
135
|
+
.set({
|
|
136
|
+
nextRunAt: claim.nextRunAt,
|
|
137
|
+
// A schedule with no future occurrence disables itself.
|
|
138
|
+
enabled: claim.nextRunAt !== null,
|
|
139
|
+
lastEnqueuedAt: claim.nowIso,
|
|
140
|
+
lastError: null,
|
|
141
|
+
updatedAt: claim.nowIso,
|
|
142
|
+
})
|
|
143
|
+
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.jobSchedules.id, claim.id), (0, drizzle_orm_1.eq)(schema_1.jobSchedules.nextRunAt, claim.expectedNextRunAt), (0, drizzle_orm_1.eq)(schema_1.jobSchedules.enabled, true)));
|
|
144
|
+
if (cas.affectedRows === 0) {
|
|
145
|
+
return { claimed: false, job: null };
|
|
146
|
+
}
|
|
147
|
+
const jobId = (0, node_crypto_1.randomUUID)();
|
|
148
|
+
await tx
|
|
149
|
+
.insert(schema_1.jobs)
|
|
150
|
+
.values({
|
|
151
|
+
id: jobId,
|
|
152
|
+
name: claim.input.name,
|
|
153
|
+
payload: claim.input.payload,
|
|
154
|
+
status: 'pending',
|
|
155
|
+
maxAttempts: claim.input.maxAttempts ?? 10,
|
|
156
|
+
uniqueKey: claim.input.uniqueKey ?? null,
|
|
157
|
+
priority: claim.input.priority ?? 0,
|
|
158
|
+
availableAt: claim.nowIso,
|
|
159
|
+
createdAt: claim.nowIso,
|
|
160
|
+
})
|
|
161
|
+
// The classic MySQL "insert unless duplicate" no-op: on a
|
|
162
|
+
// (name, unique_key) collision nothing changes and nothing raises.
|
|
163
|
+
.onDuplicateKeyUpdate({ set: { id: (0, drizzle_orm_1.sql) `${schema_1.jobs.id}` } });
|
|
164
|
+
// Detect whether the insert happened by reading our id back: absent
|
|
165
|
+
// means the overlap guard suppressed it (an occurrence with this
|
|
166
|
+
// (name, unique_key) is still active) — the schedule still advanced.
|
|
167
|
+
const insertedRows = await tx
|
|
168
|
+
.select()
|
|
169
|
+
.from(schema_1.jobs)
|
|
170
|
+
.where((0, drizzle_orm_1.eq)(schema_1.jobs.id, jobId));
|
|
171
|
+
return {
|
|
172
|
+
claimed: true,
|
|
173
|
+
job: insertedRows.length > 0 ? insertedRows[0] : null,
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
async disable(db, id, lastError) {
|
|
178
|
+
await db
|
|
179
|
+
.update(schema_1.jobSchedules)
|
|
180
|
+
.set({ enabled: false, lastError, updatedAt: new Date().toISOString() })
|
|
181
|
+
.where((0, drizzle_orm_1.eq)(schema_1.jobSchedules.id, id));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.MysqlScheduleStore = MysqlScheduleStore;
|
|
185
|
+
//# sourceMappingURL=schedule-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-store.js","sourceRoot":"","sources":["../../../dialects/mysql/schedule-store.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AACzC,6CAAgE;AAShE,2CAAqD;AACrD,qCAA8C;AAI9C;;;;;;;;;;;GAWG;AACH,MAAa,kBAAkB;IAC7B;;;;;;;;;;OAUG;IACH,KAAK,CAAC,MAAM,CAAC,EAAW,EAAE,KAA6B;QACrD,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACxC,IAAI,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YACzD,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,QAAQ,CAAC;YAClB,CAAC;YACD,uEAAuE;YACvE,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAgB,CAAC;QAC7D,CAAC;QACD,uEAAuE;QACvE,0EAA0E;QAC1E,oEAAoE;QACpE,MAAM,iBAAiB,GACrB,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;YAC5B,QAAQ,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ;YACpC,QAAQ,CAAC,SAAS,KAAK,IAAI,CAAC;QAC9B,MAAO,EAAS;aACb,MAAM,CAAC,qBAAY,CAAC;aACpB,GAAG,CAAC;YACH,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO;YAC1C,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;YACnE,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,MAAM;SAClB,CAAC;aACD,KAAK,CAAC,IAAA,gBAAE,EAAC,qBAAY,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAgB,CAAC;IACzD,CAAC;IAED,iFAAiF;IACzE,KAAK,CAAC,SAAS,CACrB,EAAW,EACX,KAA6B,EAC7B,MAAc;QAEd,IAAI,CAAC;YACH,MAAO,EAAS,CAAC,MAAM,CAAC,qBAAY,CAAC,CAAC,MAAM,CAAC;gBAC3C,EAAE,EAAE,IAAA,wBAAU,GAAE;gBAChB,GAAG,KAAK;gBACR,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;gBAC9B,cAAc,EAAE,IAAI;gBACpB,SAAS,EAAE,IAAI;gBACf,SAAS,EAAE,MAAM;gBACjB,SAAS,EAAE,MAAM;aAClB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,IAAA,kCAAsB,EAAC,KAAK,CAAC,EAAE,CAAC;gBACnC,MAAM,KAAK,CAAC;YACd,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAW,EAAE,IAAY;QACjC,MAAM,IAAI,GAAG,MAAO,EAAS;aAC1B,MAAM,EAAE;aACR,IAAI,CAAC,qBAAY,CAAC;aAClB,KAAK,CAAC,IAAA,gBAAE,EAAC,qBAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAW;QACpB,OAAQ,EAAS;aACd,MAAM,EAAE;aACR,IAAI,CAAC,qBAAY,CAAC;aAClB,OAAO,CAAC,IAAA,iBAAG,EAAC,qBAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAW,EAAE,IAAY;QACpC,MAAM,CAAC,MAAM,CAAC,GAAG,MAAO,EAAS;aAC9B,MAAM,CAAC,qBAAY,CAAC;aACpB,KAAK,CAAC,IAAA,gBAAE,EAAC,qBAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC,YAAY,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,UAAU,CACd,EAAW,EACX,IAAY,EACZ,OAAgB,EAChB,SAAwB,EACxB,iBAA0B;QAE1B,MAAM,CAAC,MAAM,CAAC,GAAG,MAAO,EAAS;aAC9B,MAAM,CAAC,qBAAY,CAAC;aACpB,GAAG,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;aAChE,KAAK,CACJ,IAAA,iBAAG,EACD,IAAA,gBAAE,EAAC,qBAAY,CAAC,IAAI,EAAE,IAAI,CAAC;QAC3B,qEAAqE;QACrE,GAAG,CAAC,iBAAiB,KAAK,SAAS;YACjC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,IAAA,gBAAE,EAAC,qBAAY,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC,CACrD,CACF,CAAC;QACJ,wEAAwE;QACxE,8DAA8D;QAC9D,IAAI,MAAM,CAAC,YAAY,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAO,CACX,EAAW,EACX,MAAc,EACd,KAAa;QAEb,OAAQ,EAAS;aACd,MAAM,EAAE;aACR,IAAI,CAAC,qBAAY,CAAC;aAClB,KAAK,CACJ,IAAA,iBAAG,EACD,IAAA,gBAAE,EAAC,qBAAY,CAAC,OAAO,EAAE,IAAI,CAAC,EAC9B,IAAA,uBAAS,EAAC,qBAAY,CAAC,SAAS,CAAC,EACjC,IAAA,iBAAG,EAAC,qBAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CACpC,CACF;aACA,OAAO,CAAC,IAAA,iBAAG,EAAC,qBAAY,CAAC,SAAS,CAAC,CAAC;aACpC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,EAAW,EACX,KAAoB;QAEpB,OAAQ,EAAS,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAgC,EAAE;YACvE,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;iBACnB,MAAM,CAAC,qBAAY,CAAC;iBACpB,GAAG,CAAC;gBACH,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,wDAAwD;gBACxD,OAAO,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI;gBACjC,cAAc,EAAE,KAAK,CAAC,MAAM;gBAC5B,SAAS,EAAE,IAAI;gBACf,SAAS,EAAE,KAAK,CAAC,MAAM;aACxB,CAAC;iBACD,KAAK,CACJ,IAAA,iBAAG,EACD,IAAA,gBAAE,EAAC,qBAAY,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,EAC7B,IAAA,gBAAE,EAAC,qBAAY,CAAC,SAAS,EAAE,KAAK,CAAC,iBAAiB,CAAC,EACnD,IAAA,gBAAE,EAAC,qBAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAC/B,CACF,CAAC;YACJ,IAAI,GAAG,CAAC,YAAY,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;YACvC,CAAC;YACD,MAAM,KAAK,GAAG,IAAA,wBAAU,GAAE,CAAC;YAC3B,MAAM,EAAE;iBACL,MAAM,CAAC,aAAI,CAAC;iBACZ,MAAM,CAAC;gBACN,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;gBACtB,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAkC;gBACvD,MAAM,EAAE,SAAS;gBACjB,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE;gBAC1C,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,IAAI;gBACxC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC;gBACnC,WAAW,EAAE,KAAK,CAAC,MAAM;gBACzB,SAAS,EAAE,KAAK,CAAC,MAAM;aACxB,CAAC;gBACF,0DAA0D;gBAC1D,mEAAmE;iBAClE,oBAAoB,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAA,iBAAG,EAAA,GAAG,aAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1D,oEAAoE;YACpE,iEAAiE;YACjE,qEAAqE;YACrE,MAAM,YAAY,GAAG,MAAM,EAAE;iBAC1B,MAAM,EAAE;iBACR,IAAI,CAAC,aAAI,CAAC;iBACV,KAAK,CAAC,IAAA,gBAAE,EAAC,aAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;YAC7B,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,GAAG,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;aACtD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAW,EAAE,EAAU,EAAE,SAAiB;QACtD,MAAO,EAAS;aACb,MAAM,CAAC,qBAAY,CAAC;aACpB,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;aACvE,KAAK,CAAC,IAAA,gBAAE,EAAC,qBAAY,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACpC,CAAC;CACF;AA5MD,gDA4MC"}
|
|
@@ -253,3 +253,277 @@ export declare const jobs: import("drizzle-orm/mysql-core").MySqlTableWithColumn
|
|
|
253
253
|
};
|
|
254
254
|
dialect: "mysql";
|
|
255
255
|
}>;
|
|
256
|
+
/**
|
|
257
|
+
* MySQL `job_schedules` table. Add it to your Drizzle schema (alongside
|
|
258
|
+
* `jobs`) and generate a migration with drizzle-kit — only needed when you
|
|
259
|
+
* opt in to schedules.
|
|
260
|
+
*
|
|
261
|
+
* Same design notes as `jobs`: ISO-8601 `varchar` timestamps (lexicographic
|
|
262
|
+
* comparison drives the due query), key columns capped at 191 chars for
|
|
263
|
+
* index-width headroom. `name` is the unique schedule identity; the
|
|
264
|
+
* `(enabled, next_run_at)` index serves the claimer's due query.
|
|
265
|
+
*/
|
|
266
|
+
export declare const jobSchedules: import("drizzle-orm/mysql-core").MySqlTableWithColumns<{
|
|
267
|
+
name: "job_schedules";
|
|
268
|
+
schema: undefined;
|
|
269
|
+
columns: {
|
|
270
|
+
id: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
271
|
+
name: "id";
|
|
272
|
+
tableName: "job_schedules";
|
|
273
|
+
dataType: "string";
|
|
274
|
+
columnType: "MySqlVarChar";
|
|
275
|
+
data: string;
|
|
276
|
+
driverParam: string | number;
|
|
277
|
+
notNull: true;
|
|
278
|
+
hasDefault: false;
|
|
279
|
+
isPrimaryKey: true;
|
|
280
|
+
isAutoincrement: false;
|
|
281
|
+
hasRuntimeDefault: false;
|
|
282
|
+
enumValues: [string, ...string[]];
|
|
283
|
+
baseColumn: never;
|
|
284
|
+
identity: undefined;
|
|
285
|
+
generated: undefined;
|
|
286
|
+
}, {}, {}>;
|
|
287
|
+
name: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
288
|
+
name: "name";
|
|
289
|
+
tableName: "job_schedules";
|
|
290
|
+
dataType: "string";
|
|
291
|
+
columnType: "MySqlVarChar";
|
|
292
|
+
data: string;
|
|
293
|
+
driverParam: string | number;
|
|
294
|
+
notNull: true;
|
|
295
|
+
hasDefault: false;
|
|
296
|
+
isPrimaryKey: false;
|
|
297
|
+
isAutoincrement: false;
|
|
298
|
+
hasRuntimeDefault: false;
|
|
299
|
+
enumValues: [string, ...string[]];
|
|
300
|
+
baseColumn: never;
|
|
301
|
+
identity: undefined;
|
|
302
|
+
generated: undefined;
|
|
303
|
+
}, {}, {}>;
|
|
304
|
+
jobName: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
305
|
+
name: "job_name";
|
|
306
|
+
tableName: "job_schedules";
|
|
307
|
+
dataType: "string";
|
|
308
|
+
columnType: "MySqlVarChar";
|
|
309
|
+
data: string;
|
|
310
|
+
driverParam: string | number;
|
|
311
|
+
notNull: true;
|
|
312
|
+
hasDefault: false;
|
|
313
|
+
isPrimaryKey: false;
|
|
314
|
+
isAutoincrement: false;
|
|
315
|
+
hasRuntimeDefault: false;
|
|
316
|
+
enumValues: [string, ...string[]];
|
|
317
|
+
baseColumn: never;
|
|
318
|
+
identity: undefined;
|
|
319
|
+
generated: undefined;
|
|
320
|
+
}, {}, {}>;
|
|
321
|
+
payload: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
322
|
+
name: "payload";
|
|
323
|
+
tableName: "job_schedules";
|
|
324
|
+
dataType: "json";
|
|
325
|
+
columnType: "MySqlJson";
|
|
326
|
+
data: Record<string, unknown>;
|
|
327
|
+
driverParam: string;
|
|
328
|
+
notNull: true;
|
|
329
|
+
hasDefault: false;
|
|
330
|
+
isPrimaryKey: false;
|
|
331
|
+
isAutoincrement: false;
|
|
332
|
+
hasRuntimeDefault: false;
|
|
333
|
+
enumValues: undefined;
|
|
334
|
+
baseColumn: never;
|
|
335
|
+
identity: undefined;
|
|
336
|
+
generated: undefined;
|
|
337
|
+
}, {}, {
|
|
338
|
+
$type: Record<string, unknown>;
|
|
339
|
+
}>;
|
|
340
|
+
cron: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
341
|
+
name: "cron";
|
|
342
|
+
tableName: "job_schedules";
|
|
343
|
+
dataType: "string";
|
|
344
|
+
columnType: "MySqlVarChar";
|
|
345
|
+
data: string;
|
|
346
|
+
driverParam: string | number;
|
|
347
|
+
notNull: true;
|
|
348
|
+
hasDefault: false;
|
|
349
|
+
isPrimaryKey: false;
|
|
350
|
+
isAutoincrement: false;
|
|
351
|
+
hasRuntimeDefault: false;
|
|
352
|
+
enumValues: [string, ...string[]];
|
|
353
|
+
baseColumn: never;
|
|
354
|
+
identity: undefined;
|
|
355
|
+
generated: undefined;
|
|
356
|
+
}, {}, {}>;
|
|
357
|
+
timezone: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
358
|
+
name: "timezone";
|
|
359
|
+
tableName: "job_schedules";
|
|
360
|
+
dataType: "string";
|
|
361
|
+
columnType: "MySqlVarChar";
|
|
362
|
+
data: string;
|
|
363
|
+
driverParam: string | number;
|
|
364
|
+
notNull: false;
|
|
365
|
+
hasDefault: false;
|
|
366
|
+
isPrimaryKey: false;
|
|
367
|
+
isAutoincrement: false;
|
|
368
|
+
hasRuntimeDefault: false;
|
|
369
|
+
enumValues: [string, ...string[]];
|
|
370
|
+
baseColumn: never;
|
|
371
|
+
identity: undefined;
|
|
372
|
+
generated: undefined;
|
|
373
|
+
}, {}, {}>;
|
|
374
|
+
enabled: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
375
|
+
name: "enabled";
|
|
376
|
+
tableName: "job_schedules";
|
|
377
|
+
dataType: "boolean";
|
|
378
|
+
columnType: "MySqlBoolean";
|
|
379
|
+
data: boolean;
|
|
380
|
+
driverParam: number | boolean;
|
|
381
|
+
notNull: true;
|
|
382
|
+
hasDefault: true;
|
|
383
|
+
isPrimaryKey: false;
|
|
384
|
+
isAutoincrement: false;
|
|
385
|
+
hasRuntimeDefault: false;
|
|
386
|
+
enumValues: undefined;
|
|
387
|
+
baseColumn: never;
|
|
388
|
+
identity: undefined;
|
|
389
|
+
generated: undefined;
|
|
390
|
+
}, {}, {}>;
|
|
391
|
+
nextRunAt: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
392
|
+
name: "next_run_at";
|
|
393
|
+
tableName: "job_schedules";
|
|
394
|
+
dataType: "string";
|
|
395
|
+
columnType: "MySqlVarChar";
|
|
396
|
+
data: string;
|
|
397
|
+
driverParam: string | number;
|
|
398
|
+
notNull: false;
|
|
399
|
+
hasDefault: false;
|
|
400
|
+
isPrimaryKey: false;
|
|
401
|
+
isAutoincrement: false;
|
|
402
|
+
hasRuntimeDefault: false;
|
|
403
|
+
enumValues: [string, ...string[]];
|
|
404
|
+
baseColumn: never;
|
|
405
|
+
identity: undefined;
|
|
406
|
+
generated: undefined;
|
|
407
|
+
}, {}, {}>;
|
|
408
|
+
maxAttempts: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
409
|
+
name: "max_attempts";
|
|
410
|
+
tableName: "job_schedules";
|
|
411
|
+
dataType: "number";
|
|
412
|
+
columnType: "MySqlInt";
|
|
413
|
+
data: number;
|
|
414
|
+
driverParam: string | number;
|
|
415
|
+
notNull: false;
|
|
416
|
+
hasDefault: false;
|
|
417
|
+
isPrimaryKey: false;
|
|
418
|
+
isAutoincrement: false;
|
|
419
|
+
hasRuntimeDefault: false;
|
|
420
|
+
enumValues: undefined;
|
|
421
|
+
baseColumn: never;
|
|
422
|
+
identity: undefined;
|
|
423
|
+
generated: undefined;
|
|
424
|
+
}, {}, {}>;
|
|
425
|
+
priority: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
426
|
+
name: "priority";
|
|
427
|
+
tableName: "job_schedules";
|
|
428
|
+
dataType: "number";
|
|
429
|
+
columnType: "MySqlInt";
|
|
430
|
+
data: number;
|
|
431
|
+
driverParam: string | number;
|
|
432
|
+
notNull: false;
|
|
433
|
+
hasDefault: false;
|
|
434
|
+
isPrimaryKey: false;
|
|
435
|
+
isAutoincrement: false;
|
|
436
|
+
hasRuntimeDefault: false;
|
|
437
|
+
enumValues: undefined;
|
|
438
|
+
baseColumn: never;
|
|
439
|
+
identity: undefined;
|
|
440
|
+
generated: undefined;
|
|
441
|
+
}, {}, {}>;
|
|
442
|
+
uniqueKey: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
443
|
+
name: "unique_key";
|
|
444
|
+
tableName: "job_schedules";
|
|
445
|
+
dataType: "string";
|
|
446
|
+
columnType: "MySqlVarChar";
|
|
447
|
+
data: string;
|
|
448
|
+
driverParam: string | number;
|
|
449
|
+
notNull: false;
|
|
450
|
+
hasDefault: false;
|
|
451
|
+
isPrimaryKey: false;
|
|
452
|
+
isAutoincrement: false;
|
|
453
|
+
hasRuntimeDefault: false;
|
|
454
|
+
enumValues: [string, ...string[]];
|
|
455
|
+
baseColumn: never;
|
|
456
|
+
identity: undefined;
|
|
457
|
+
generated: undefined;
|
|
458
|
+
}, {}, {}>;
|
|
459
|
+
lastEnqueuedAt: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
460
|
+
name: "last_enqueued_at";
|
|
461
|
+
tableName: "job_schedules";
|
|
462
|
+
dataType: "string";
|
|
463
|
+
columnType: "MySqlVarChar";
|
|
464
|
+
data: string;
|
|
465
|
+
driverParam: string | number;
|
|
466
|
+
notNull: false;
|
|
467
|
+
hasDefault: false;
|
|
468
|
+
isPrimaryKey: false;
|
|
469
|
+
isAutoincrement: false;
|
|
470
|
+
hasRuntimeDefault: false;
|
|
471
|
+
enumValues: [string, ...string[]];
|
|
472
|
+
baseColumn: never;
|
|
473
|
+
identity: undefined;
|
|
474
|
+
generated: undefined;
|
|
475
|
+
}, {}, {}>;
|
|
476
|
+
lastError: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
477
|
+
name: "last_error";
|
|
478
|
+
tableName: "job_schedules";
|
|
479
|
+
dataType: "string";
|
|
480
|
+
columnType: "MySqlText";
|
|
481
|
+
data: string;
|
|
482
|
+
driverParam: string;
|
|
483
|
+
notNull: false;
|
|
484
|
+
hasDefault: false;
|
|
485
|
+
isPrimaryKey: false;
|
|
486
|
+
isAutoincrement: false;
|
|
487
|
+
hasRuntimeDefault: false;
|
|
488
|
+
enumValues: [string, ...string[]];
|
|
489
|
+
baseColumn: never;
|
|
490
|
+
identity: undefined;
|
|
491
|
+
generated: undefined;
|
|
492
|
+
}, {}, {}>;
|
|
493
|
+
createdAt: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
494
|
+
name: "created_at";
|
|
495
|
+
tableName: "job_schedules";
|
|
496
|
+
dataType: "string";
|
|
497
|
+
columnType: "MySqlVarChar";
|
|
498
|
+
data: string;
|
|
499
|
+
driverParam: string | number;
|
|
500
|
+
notNull: true;
|
|
501
|
+
hasDefault: false;
|
|
502
|
+
isPrimaryKey: false;
|
|
503
|
+
isAutoincrement: false;
|
|
504
|
+
hasRuntimeDefault: false;
|
|
505
|
+
enumValues: [string, ...string[]];
|
|
506
|
+
baseColumn: never;
|
|
507
|
+
identity: undefined;
|
|
508
|
+
generated: undefined;
|
|
509
|
+
}, {}, {}>;
|
|
510
|
+
updatedAt: import("drizzle-orm/mysql-core").MySqlColumn<{
|
|
511
|
+
name: "updated_at";
|
|
512
|
+
tableName: "job_schedules";
|
|
513
|
+
dataType: "string";
|
|
514
|
+
columnType: "MySqlVarChar";
|
|
515
|
+
data: string;
|
|
516
|
+
driverParam: string | number;
|
|
517
|
+
notNull: true;
|
|
518
|
+
hasDefault: false;
|
|
519
|
+
isPrimaryKey: false;
|
|
520
|
+
isAutoincrement: false;
|
|
521
|
+
hasRuntimeDefault: false;
|
|
522
|
+
enumValues: [string, ...string[]];
|
|
523
|
+
baseColumn: never;
|
|
524
|
+
identity: undefined;
|
|
525
|
+
generated: undefined;
|
|
526
|
+
}, {}, {}>;
|
|
527
|
+
};
|
|
528
|
+
dialect: "mysql";
|
|
529
|
+
}>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.jobs = void 0;
|
|
3
|
+
exports.jobSchedules = exports.jobs = void 0;
|
|
4
4
|
const mysql_core_1 = require("drizzle-orm/mysql-core");
|
|
5
5
|
// MySQL-specific schema choices (documented so they are deliberate, not
|
|
6
6
|
// accidental divergence from the Postgres/SQLite definitions):
|
|
@@ -44,4 +44,34 @@ exports.jobs = (0, mysql_core_1.mysqlTable)('jobs', {
|
|
|
44
44
|
(0, mysql_core_1.uniqueIndex)('jobs_name_unique_key_unique').on(table.name, table.uniqueKey),
|
|
45
45
|
(0, mysql_core_1.index)('jobs_status_available_idx').on(table.status, table.availableAt),
|
|
46
46
|
]);
|
|
47
|
+
/**
|
|
48
|
+
* MySQL `job_schedules` table. Add it to your Drizzle schema (alongside
|
|
49
|
+
* `jobs`) and generate a migration with drizzle-kit — only needed when you
|
|
50
|
+
* opt in to schedules.
|
|
51
|
+
*
|
|
52
|
+
* Same design notes as `jobs`: ISO-8601 `varchar` timestamps (lexicographic
|
|
53
|
+
* comparison drives the due query), key columns capped at 191 chars for
|
|
54
|
+
* index-width headroom. `name` is the unique schedule identity; the
|
|
55
|
+
* `(enabled, next_run_at)` index serves the claimer's due query.
|
|
56
|
+
*/
|
|
57
|
+
exports.jobSchedules = (0, mysql_core_1.mysqlTable)('job_schedules', {
|
|
58
|
+
id: (0, mysql_core_1.varchar)('id', { length: 191 }).primaryKey(),
|
|
59
|
+
name: (0, mysql_core_1.varchar)('name', { length: 191 }).notNull(),
|
|
60
|
+
jobName: (0, mysql_core_1.varchar)('job_name', { length: 255 }).notNull(),
|
|
61
|
+
payload: (0, mysql_core_1.json)('payload').$type().notNull(),
|
|
62
|
+
cron: (0, mysql_core_1.varchar)('cron', { length: 255 }).notNull(),
|
|
63
|
+
timezone: (0, mysql_core_1.varchar)('timezone', { length: 64 }),
|
|
64
|
+
enabled: (0, mysql_core_1.boolean)('enabled').notNull().default(true),
|
|
65
|
+
nextRunAt: (0, mysql_core_1.varchar)('next_run_at', { length: 32 }),
|
|
66
|
+
maxAttempts: (0, mysql_core_1.int)('max_attempts'),
|
|
67
|
+
priority: (0, mysql_core_1.int)('priority'),
|
|
68
|
+
uniqueKey: (0, mysql_core_1.varchar)('unique_key', { length: 191 }),
|
|
69
|
+
lastEnqueuedAt: (0, mysql_core_1.varchar)('last_enqueued_at', { length: 32 }),
|
|
70
|
+
lastError: (0, mysql_core_1.text)('last_error'),
|
|
71
|
+
createdAt: (0, mysql_core_1.varchar)('created_at', { length: 32 }).notNull(),
|
|
72
|
+
updatedAt: (0, mysql_core_1.varchar)('updated_at', { length: 32 }).notNull(),
|
|
73
|
+
}, (table) => [
|
|
74
|
+
(0, mysql_core_1.uniqueIndex)('job_schedules_name_unique').on(table.name),
|
|
75
|
+
(0, mysql_core_1.index)('job_schedules_enabled_next_run_idx').on(table.enabled, table.nextRunAt),
|
|
76
|
+
]);
|
|
47
77
|
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../dialects/mysql/schema.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../dialects/mysql/schema.ts"],"names":[],"mappings":";;;AAAA,uDASgC;AAGhC,wEAAwE;AACxE,+DAA+D;AAC/D,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,yEAAyE;AACzE,2EAA2E;AAC3E,2EAA2E;AAC3E,qEAAqE;AACrE,yCAAyC;AACzC,wEAAwE;AACxE,0EAA0E;AAC1E,6EAA6E;AAC7E,6EAA6E;AAC7E,0EAA0E;AAC1E,4EAA4E;AAC5E,+CAA+C;AAE/C;;;;;GAKG;AACU,QAAA,IAAI,GAAG,IAAA,uBAAU,EAC5B,MAAM,EACN;IACE,EAAE,EAAE,IAAA,oBAAO,EAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,UAAU,EAAE;IAC/C,IAAI,EAAE,IAAA,oBAAO,EAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE;IAChD,OAAO,EAAE,IAAA,iBAAI,EAAC,SAAS,CAAC,CAAC,KAAK,EAA2B,CAAC,OAAO,EAAE;IACnE,MAAM,EAAE,IAAA,oBAAO,EAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAa,CAAC,OAAO,EAAE;IACtE,QAAQ,EAAE,IAAA,gBAAG,EAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9C,WAAW,EAAE,IAAA,gBAAG,EAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACtD,SAAS,EAAE,IAAA,oBAAO,EAAC,YAAY,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACjD,QAAQ,EAAE,IAAA,gBAAG,EAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9C,WAAW,EAAE,IAAA,oBAAO,EAAC,cAAc,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE;IAC9D,SAAS,EAAE,IAAA,oBAAO,EAAC,YAAY,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAChD,SAAS,EAAE,IAAA,oBAAO,EAAC,YAAY,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACjD,WAAW,EAAE,IAAA,oBAAO,EAAC,cAAc,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACpD,SAAS,EAAE,IAAA,iBAAI,EAAC,YAAY,CAAC;IAC7B,SAAS,EAAE,IAAA,oBAAO,EAAC,YAAY,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE;CAC3D,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,IAAA,wBAAW,EAAC,6BAA6B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1E,IAAA,kBAAK,EAAC,2BAA2B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC;CACvE,CACF,CAAC;AAEF;;;;;;;;;GASG;AACU,QAAA,YAAY,GAAG,IAAA,uBAAU,EACpC,eAAe,EACf;IACE,EAAE,EAAE,IAAA,oBAAO,EAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,UAAU,EAAE;IAC/C,IAAI,EAAE,IAAA,oBAAO,EAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE;IAChD,OAAO,EAAE,IAAA,oBAAO,EAAC,UAAU,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE;IACvD,OAAO,EAAE,IAAA,iBAAI,EAAC,SAAS,CAAC,CAAC,KAAK,EAA2B,CAAC,OAAO,EAAE;IACnE,IAAI,EAAE,IAAA,oBAAO,EAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE;IAChD,QAAQ,EAAE,IAAA,oBAAO,EAAC,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC7C,OAAO,EAAE,IAAA,oBAAO,EAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACnD,SAAS,EAAE,IAAA,oBAAO,EAAC,aAAa,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACjD,WAAW,EAAE,IAAA,gBAAG,EAAC,cAAc,CAAC;IAChC,QAAQ,EAAE,IAAA,gBAAG,EAAC,UAAU,CAAC;IACzB,SAAS,EAAE,IAAA,oBAAO,EAAC,YAAY,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACjD,cAAc,EAAE,IAAA,oBAAO,EAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC3D,SAAS,EAAE,IAAA,iBAAI,EAAC,YAAY,CAAC;IAC7B,SAAS,EAAE,IAAA,oBAAO,EAAC,YAAY,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE;IAC1D,SAAS,EAAE,IAAA,oBAAO,EAAC,YAAY,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE;CAC3D,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,IAAA,wBAAW,EAAC,2BAA2B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;IACvD,IAAA,kBAAK,EAAC,oCAAoC,CAAC,CAAC,EAAE,CAC5C,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,SAAS,CAChB;CACF,CACF,CAAC"}
|
|
@@ -18,4 +18,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
// the `jobs` table definition + the Postgres store.
|
|
19
19
|
__exportStar(require("./schema"), exports);
|
|
20
20
|
__exportStar(require("./job-store"), exports);
|
|
21
|
+
__exportStar(require("./schedule-store"), exports);
|
|
21
22
|
//# sourceMappingURL=index.js.map
|