mysql-boss 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.
Files changed (148) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +688 -0
  3. package/dist/cjs/archive.d.ts +8 -0
  4. package/dist/cjs/archive.d.ts.map +1 -0
  5. package/dist/cjs/archive.js +82 -0
  6. package/dist/cjs/archive.js.map +1 -0
  7. package/dist/cjs/boss.d.ts +45 -0
  8. package/dist/cjs/boss.d.ts.map +1 -0
  9. package/dist/cjs/boss.js +205 -0
  10. package/dist/cjs/boss.js.map +1 -0
  11. package/dist/cjs/claim.d.ts +5 -0
  12. package/dist/cjs/claim.d.ts.map +1 -0
  13. package/dist/cjs/claim.js +47 -0
  14. package/dist/cjs/claim.js.map +1 -0
  15. package/dist/cjs/connection.d.ts +4 -0
  16. package/dist/cjs/connection.d.ts.map +1 -0
  17. package/dist/cjs/connection.js +26 -0
  18. package/dist/cjs/connection.js.map +1 -0
  19. package/dist/cjs/cron/next.d.ts +3 -0
  20. package/dist/cjs/cron/next.d.ts.map +1 -0
  21. package/dist/cjs/cron/next.js +179 -0
  22. package/dist/cjs/cron/next.js.map +1 -0
  23. package/dist/cjs/cron/parse.d.ts +11 -0
  24. package/dist/cjs/cron/parse.d.ts.map +1 -0
  25. package/dist/cjs/cron/parse.js +99 -0
  26. package/dist/cjs/cron/parse.js.map +1 -0
  27. package/dist/cjs/dlq.d.ts +11 -0
  28. package/dist/cjs/dlq.d.ts.map +1 -0
  29. package/dist/cjs/dlq.js +92 -0
  30. package/dist/cjs/dlq.js.map +1 -0
  31. package/dist/cjs/errors.d.ts +10 -0
  32. package/dist/cjs/errors.d.ts.map +1 -0
  33. package/dist/cjs/errors.js +25 -0
  34. package/dist/cjs/errors.js.map +1 -0
  35. package/dist/cjs/fail.d.ts +8 -0
  36. package/dist/cjs/fail.d.ts.map +1 -0
  37. package/dist/cjs/fail.js +19 -0
  38. package/dist/cjs/fail.js.map +1 -0
  39. package/dist/cjs/heartbeat.d.ts +4 -0
  40. package/dist/cjs/heartbeat.d.ts.map +1 -0
  41. package/dist/cjs/heartbeat.js +18 -0
  42. package/dist/cjs/heartbeat.js.map +1 -0
  43. package/dist/cjs/index.d.ts +70 -0
  44. package/dist/cjs/index.d.ts.map +1 -0
  45. package/dist/cjs/index.js +10 -0
  46. package/dist/cjs/index.js.map +1 -0
  47. package/dist/cjs/migrate.d.ts +4 -0
  48. package/dist/cjs/migrate.d.ts.map +1 -0
  49. package/dist/cjs/migrate.js +14 -0
  50. package/dist/cjs/migrate.js.map +1 -0
  51. package/dist/cjs/package.json +1 -0
  52. package/dist/cjs/retry-util.d.ts +2 -0
  53. package/dist/cjs/retry-util.d.ts.map +1 -0
  54. package/dist/cjs/retry-util.js +31 -0
  55. package/dist/cjs/retry-util.js.map +1 -0
  56. package/dist/cjs/sql.d.ts +82 -0
  57. package/dist/cjs/sql.d.ts.map +1 -0
  58. package/dist/cjs/sql.js +396 -0
  59. package/dist/cjs/sql.js.map +1 -0
  60. package/dist/cjs/sweep.d.ts +4 -0
  61. package/dist/cjs/sweep.d.ts.map +1 -0
  62. package/dist/cjs/sweep.js +46 -0
  63. package/dist/cjs/sweep.js.map +1 -0
  64. package/dist/cjs/tick.d.ts +11 -0
  65. package/dist/cjs/tick.d.ts.map +1 -0
  66. package/dist/cjs/tick.js +82 -0
  67. package/dist/cjs/tick.js.map +1 -0
  68. package/dist/cjs/util.d.ts +2 -0
  69. package/dist/cjs/util.d.ts.map +1 -0
  70. package/dist/cjs/util.js +7 -0
  71. package/dist/cjs/util.js.map +1 -0
  72. package/dist/cjs/worker.d.ts +42 -0
  73. package/dist/cjs/worker.d.ts.map +1 -0
  74. package/dist/cjs/worker.js +232 -0
  75. package/dist/cjs/worker.js.map +1 -0
  76. package/dist/esm/archive.d.ts +8 -0
  77. package/dist/esm/archive.d.ts.map +1 -0
  78. package/dist/esm/archive.js +76 -0
  79. package/dist/esm/archive.js.map +1 -0
  80. package/dist/esm/boss.d.ts +45 -0
  81. package/dist/esm/boss.d.ts.map +1 -0
  82. package/dist/esm/boss.js +201 -0
  83. package/dist/esm/boss.js.map +1 -0
  84. package/dist/esm/claim.d.ts +5 -0
  85. package/dist/esm/claim.d.ts.map +1 -0
  86. package/dist/esm/claim.js +44 -0
  87. package/dist/esm/claim.js.map +1 -0
  88. package/dist/esm/connection.d.ts +4 -0
  89. package/dist/esm/connection.d.ts.map +1 -0
  90. package/dist/esm/connection.js +22 -0
  91. package/dist/esm/connection.js.map +1 -0
  92. package/dist/esm/cron/next.d.ts +3 -0
  93. package/dist/esm/cron/next.d.ts.map +1 -0
  94. package/dist/esm/cron/next.js +176 -0
  95. package/dist/esm/cron/next.js.map +1 -0
  96. package/dist/esm/cron/parse.d.ts +11 -0
  97. package/dist/esm/cron/parse.d.ts.map +1 -0
  98. package/dist/esm/cron/parse.js +96 -0
  99. package/dist/esm/cron/parse.js.map +1 -0
  100. package/dist/esm/dlq.d.ts +11 -0
  101. package/dist/esm/dlq.d.ts.map +1 -0
  102. package/dist/esm/dlq.js +87 -0
  103. package/dist/esm/dlq.js.map +1 -0
  104. package/dist/esm/errors.d.ts +10 -0
  105. package/dist/esm/errors.d.ts.map +1 -0
  106. package/dist/esm/errors.js +19 -0
  107. package/dist/esm/errors.js.map +1 -0
  108. package/dist/esm/fail.d.ts +8 -0
  109. package/dist/esm/fail.d.ts.map +1 -0
  110. package/dist/esm/fail.js +16 -0
  111. package/dist/esm/fail.js.map +1 -0
  112. package/dist/esm/heartbeat.d.ts +4 -0
  113. package/dist/esm/heartbeat.d.ts.map +1 -0
  114. package/dist/esm/heartbeat.js +15 -0
  115. package/dist/esm/heartbeat.js.map +1 -0
  116. package/dist/esm/index.d.ts +70 -0
  117. package/dist/esm/index.d.ts.map +1 -0
  118. package/dist/esm/index.js +3 -0
  119. package/dist/esm/index.js.map +1 -0
  120. package/dist/esm/migrate.d.ts +4 -0
  121. package/dist/esm/migrate.d.ts.map +1 -0
  122. package/dist/esm/migrate.js +11 -0
  123. package/dist/esm/migrate.js.map +1 -0
  124. package/dist/esm/retry-util.d.ts +2 -0
  125. package/dist/esm/retry-util.d.ts.map +1 -0
  126. package/dist/esm/retry-util.js +28 -0
  127. package/dist/esm/retry-util.js.map +1 -0
  128. package/dist/esm/sql.d.ts +82 -0
  129. package/dist/esm/sql.d.ts.map +1 -0
  130. package/dist/esm/sql.js +392 -0
  131. package/dist/esm/sql.js.map +1 -0
  132. package/dist/esm/sweep.d.ts +4 -0
  133. package/dist/esm/sweep.d.ts.map +1 -0
  134. package/dist/esm/sweep.js +43 -0
  135. package/dist/esm/sweep.js.map +1 -0
  136. package/dist/esm/tick.d.ts +11 -0
  137. package/dist/esm/tick.d.ts.map +1 -0
  138. package/dist/esm/tick.js +77 -0
  139. package/dist/esm/tick.js.map +1 -0
  140. package/dist/esm/util.d.ts +2 -0
  141. package/dist/esm/util.d.ts.map +1 -0
  142. package/dist/esm/util.js +4 -0
  143. package/dist/esm/util.js.map +1 -0
  144. package/dist/esm/worker.d.ts +42 -0
  145. package/dist/esm/worker.d.ts.map +1 -0
  146. package/dist/esm/worker.js +228 -0
  147. package/dist/esm/worker.js.map +1 -0
  148. package/package.json +64 -0
@@ -0,0 +1,392 @@
1
+ // §1.1 — DDL
2
+ export const CREATE_JOBS = `
3
+ CREATE TABLE IF NOT EXISTS jobs (
4
+ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
5
+ queue VARCHAR(128) NOT NULL,
6
+ state ENUM('available','active') NOT NULL DEFAULT 'available',
7
+ priority SMALLINT NOT NULL DEFAULT 0,
8
+ payload JSON NULL,
9
+ singleton_key VARCHAR(191) NULL,
10
+ retry_count INT UNSIGNED NOT NULL DEFAULT 0,
11
+ retry_limit INT UNSIGNED NOT NULL DEFAULT 2,
12
+ retry_delay_secs INT UNSIGNED NOT NULL DEFAULT 30,
13
+ retry_backoff TINYINT(1) NOT NULL DEFAULT 0,
14
+ run_at DATETIME(6) NOT NULL,
15
+ created_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),
16
+ started_at DATETIME(6) NULL,
17
+ locked_by BINARY(16) NULL,
18
+ lease_expires_at DATETIME(6) NULL,
19
+ last_error JSON NULL,
20
+ PRIMARY KEY (id),
21
+ UNIQUE KEY uq_jobs_singleton (queue, singleton_key),
22
+ KEY ix_jobs_dequeue (queue, state, priority DESC, run_at, id),
23
+ KEY ix_jobs_lease (state, lease_expires_at)
24
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
25
+ `;
26
+ export const CREATE_JOBS_ARCHIVE = `
27
+ CREATE TABLE IF NOT EXISTS jobs_archive (
28
+ id BIGINT UNSIGNED NOT NULL,
29
+ queue VARCHAR(128) NOT NULL,
30
+ priority SMALLINT NOT NULL,
31
+ payload JSON NULL,
32
+ singleton_key VARCHAR(191) NULL,
33
+ retry_count INT UNSIGNED NOT NULL,
34
+ created_at DATETIME(6) NOT NULL,
35
+ started_at DATETIME(6) NOT NULL,
36
+ completed_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),
37
+ duration_ms INT UNSIGNED NOT NULL,
38
+ PRIMARY KEY (id),
39
+ KEY ix_archive_queue_time (queue, completed_at),
40
+ KEY ix_archive_time (completed_at)
41
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
42
+ `;
43
+ export const CREATE_JOBS_DEAD = `
44
+ CREATE TABLE IF NOT EXISTS jobs_dead (
45
+ id BIGINT UNSIGNED NOT NULL,
46
+ queue VARCHAR(128) NOT NULL,
47
+ priority SMALLINT NOT NULL,
48
+ payload JSON NULL,
49
+ singleton_key VARCHAR(191) NULL,
50
+ retry_count INT UNSIGNED NOT NULL,
51
+ retry_limit INT UNSIGNED NOT NULL,
52
+ retry_delay_secs INT UNSIGNED NOT NULL,
53
+ retry_backoff TINYINT(1) NOT NULL,
54
+ created_at DATETIME(6) NOT NULL,
55
+ failed_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),
56
+ last_error JSON NULL,
57
+ PRIMARY KEY (id),
58
+ KEY ix_dead_queue_time (queue, failed_at)
59
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
60
+ `;
61
+ export const CREATE_SCHEDULES = `
62
+ CREATE TABLE IF NOT EXISTS schedules (
63
+ name VARCHAR(128) NOT NULL,
64
+ queue VARCHAR(128) NOT NULL,
65
+ cron VARCHAR(64) NOT NULL,
66
+ timezone VARCHAR(64) NOT NULL DEFAULT 'UTC',
67
+ payload JSON NULL,
68
+ job_options JSON NULL,
69
+ next_run_at DATETIME(6) NOT NULL,
70
+ last_enqueued_at DATETIME(6) NULL,
71
+ updated_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6))
72
+ ON UPDATE CURRENT_TIMESTAMP(6),
73
+ PRIMARY KEY (name),
74
+ KEY ix_schedules_due (next_run_at)
75
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
76
+ `;
77
+ // §1.2 — Enqueue
78
+ export const ENQUEUE = `
79
+ INSERT INTO jobs
80
+ (queue, priority, payload, singleton_key,
81
+ retry_limit, retry_delay_secs, retry_backoff, run_at)
82
+ VALUES
83
+ (?, ?, ?, ?, ?, ?, ?, COALESCE(?, UTC_TIMESTAMP(6)));
84
+ `;
85
+ export const ENQUEUE_SINGLETON = `
86
+ INSERT IGNORE INTO jobs
87
+ (queue, priority, payload, singleton_key,
88
+ retry_limit, retry_delay_secs, retry_backoff, run_at)
89
+ VALUES
90
+ (?, ?, ?, ?, ?, ?, ?, COALESCE(?, UTC_TIMESTAMP(6)));
91
+ `;
92
+ export const LAST_INSERT_ID = `
93
+ SELECT CAST(LAST_INSERT_ID() AS CHAR) AS id;
94
+ `;
95
+ // §1.2 — Dequeue / claim
96
+ export const CLAIM_SELECT = `
97
+ SELECT CAST(id AS CHAR) AS id, queue, payload, retry_count, retry_limit,
98
+ retry_delay_secs, retry_backoff
99
+ FROM jobs
100
+ WHERE queue = ?
101
+ AND state = 'available'
102
+ AND run_at <= UTC_TIMESTAMP(6)
103
+ ORDER BY priority DESC, run_at, id
104
+ LIMIT ?
105
+ FOR UPDATE SKIP LOCKED;
106
+ `;
107
+ export const CLAIM_UPDATE = `
108
+ UPDATE jobs
109
+ SET state = 'active',
110
+ started_at = UTC_TIMESTAMP(6),
111
+ locked_by = UUID_TO_BIN(?),
112
+ lease_expires_at = UTC_TIMESTAMP(6) + INTERVAL ? SECOND
113
+ WHERE id IN (?);
114
+ `;
115
+ // §1.2 — Complete (archive move)
116
+ export const COMPLETE_ARCHIVE = `
117
+ INSERT INTO jobs_archive
118
+ (id, queue, priority, payload, singleton_key, retry_count,
119
+ created_at, started_at, duration_ms)
120
+ SELECT id, queue, priority, payload, singleton_key, retry_count,
121
+ created_at, started_at,
122
+ TIMESTAMPDIFF(MICROSECOND, started_at, UTC_TIMESTAMP(6)) DIV 1000
123
+ FROM jobs
124
+ WHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';
125
+ `;
126
+ export const COMPLETE_DELETE = `
127
+ DELETE FROM jobs
128
+ WHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';
129
+ `;
130
+ // §2.2 — Fail with retries remaining
131
+ export const FAIL_RETRY = `
132
+ UPDATE jobs
133
+ SET state = 'available',
134
+ run_at = UTC_TIMESTAMP(6) + INTERVAL
135
+ LEAST(
136
+ 86400,
137
+ IF(retry_backoff = 1,
138
+ retry_delay_secs * POW(2, retry_count),
139
+ retry_delay_secs)
140
+ + FLOOR(RAND() * retry_delay_secs)
141
+ ) SECOND,
142
+ retry_count = retry_count + 1,
143
+ locked_by = NULL,
144
+ lease_expires_at = NULL,
145
+ started_at = NULL,
146
+ last_error = ?
147
+ WHERE id = ?
148
+ AND locked_by = UUID_TO_BIN(?)
149
+ AND state = 'active'
150
+ AND retry_count < retry_limit;
151
+ `;
152
+ // §3.2 — Dead-letter move
153
+ export const DLQ_INSERT = `
154
+ INSERT INTO jobs_dead
155
+ (id, queue, priority, payload, singleton_key,
156
+ retry_count, retry_limit, retry_delay_secs, retry_backoff,
157
+ created_at, last_error)
158
+ SELECT id, queue, priority, payload, singleton_key,
159
+ retry_count + 1, retry_limit, retry_delay_secs, retry_backoff,
160
+ created_at, ?
161
+ FROM jobs
162
+ WHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';
163
+ `;
164
+ export const DLQ_DELETE = `
165
+ DELETE FROM jobs
166
+ WHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';
167
+ `;
168
+ // §3.2 — DLQ query
169
+ export const LIST_DEAD = `
170
+ SELECT CAST(id AS CHAR) AS id, queue, priority, payload, retry_count,
171
+ UNIX_TIMESTAMP(created_at) AS created_at_unix,
172
+ UNIX_TIMESTAMP(failed_at) AS failed_at_unix,
173
+ last_error
174
+ FROM jobs_dead
175
+ WHERE queue = ? AND failed_at BETWEEN ? AND ?
176
+ ORDER BY failed_at DESC
177
+ LIMIT ? OFFSET ?;
178
+ `;
179
+ // §3.2 — Replay
180
+ export const REPLAY_INSERT = `
181
+ INSERT INTO jobs
182
+ (queue, priority, payload, singleton_key,
183
+ retry_limit, retry_delay_secs, retry_backoff, run_at)
184
+ SELECT queue, priority, payload, singleton_key,
185
+ retry_limit, retry_delay_secs, retry_backoff, UTC_TIMESTAMP(6)
186
+ FROM jobs_dead
187
+ WHERE id IN (?)
188
+ FOR UPDATE;
189
+ `;
190
+ export const REPLAY_DELETE = `
191
+ DELETE FROM jobs_dead WHERE id IN (?);
192
+ `;
193
+ // §4.2 — Cron tick
194
+ export const DB_NOW = "SELECT UNIX_TIMESTAMP(UTC_TIMESTAMP(6)) AS db_now_unix;";
195
+ export const TICK_SELECT = `
196
+ SELECT name, queue, cron, timezone, payload, job_options,
197
+ next_run_at,
198
+ UNIX_TIMESTAMP(next_run_at) AS next_run_at_unix
199
+ FROM schedules
200
+ WHERE next_run_at <= UTC_TIMESTAMP(6)
201
+ ORDER BY next_run_at
202
+ LIMIT 20
203
+ FOR UPDATE SKIP LOCKED;
204
+ `;
205
+ export const TICK_ENQUEUE = `
206
+ INSERT IGNORE INTO jobs
207
+ (queue, priority, payload, singleton_key,
208
+ retry_limit, retry_delay_secs, retry_backoff, run_at)
209
+ VALUES
210
+ (?, ?, ?, CONCAT('cron:', ?, ':', DATE_FORMAT(?, '%Y%m%d%H%i%s')),
211
+ ?, ?, ?, UTC_TIMESTAMP(6));
212
+ `;
213
+ export const TICK_ADVANCE = `
214
+ UPDATE schedules
215
+ SET next_run_at = ?, last_enqueued_at = UTC_TIMESTAMP(6)
216
+ WHERE name = ?;
217
+ `;
218
+ // §4 — Schedule CRUD
219
+ export const SCHEDULE_UPSERT = `
220
+ INSERT INTO schedules (name, queue, cron, timezone, payload, job_options, next_run_at)
221
+ VALUES (?, ?, ?, ?, ?, ?, ?)
222
+ ON DUPLICATE KEY UPDATE
223
+ queue = VALUES(queue),
224
+ cron = VALUES(cron),
225
+ timezone = VALUES(timezone),
226
+ payload = VALUES(payload),
227
+ job_options = VALUES(job_options),
228
+ next_run_at = VALUES(next_run_at);
229
+ `;
230
+ export const SCHEDULE_DELETE = `
231
+ DELETE FROM schedules WHERE name = ?;
232
+ `;
233
+ // §6.1 — Heartbeat
234
+ export const HEARTBEAT = `
235
+ UPDATE jobs
236
+ SET lease_expires_at = UTC_TIMESTAMP(6) + INTERVAL ? SECOND
237
+ WHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';
238
+ `;
239
+ export const HEARTBEAT_OWNED = `
240
+ SELECT CAST(id AS CHAR) AS id
241
+ FROM jobs
242
+ WHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';
243
+ `;
244
+ // §6.2 — Drain release
245
+ export const DRAIN_RELEASE = `
246
+ UPDATE jobs
247
+ SET state = 'available', run_at = UTC_TIMESTAMP(6),
248
+ locked_by = NULL, lease_expires_at = NULL, started_at = NULL
249
+ WHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';
250
+ `;
251
+ // §6.3 — Stale sweep
252
+ export const SWEEP_SELECT = `
253
+ SELECT CAST(id AS CHAR) AS id, retry_count, retry_limit
254
+ FROM jobs
255
+ WHERE state = 'active' AND lease_expires_at < UTC_TIMESTAMP(6)
256
+ ORDER BY lease_expires_at
257
+ LIMIT 100
258
+ FOR UPDATE SKIP LOCKED;
259
+ `;
260
+ export const SWEEP_RETRY = `
261
+ UPDATE jobs
262
+ SET state = 'available',
263
+ run_at = UTC_TIMESTAMP(6) + INTERVAL
264
+ LEAST(
265
+ 86400,
266
+ IF(retry_backoff = 1,
267
+ retry_delay_secs * POW(2, retry_count),
268
+ retry_delay_secs)
269
+ + FLOOR(RAND() * retry_delay_secs)
270
+ ) SECOND,
271
+ retry_count = retry_count + 1,
272
+ locked_by = NULL, lease_expires_at = NULL, started_at = NULL,
273
+ last_error = JSON_OBJECT('message', 'lease expired', 'at', UTC_TIMESTAMP(6))
274
+ WHERE id IN (?) AND retry_count < retry_limit;
275
+ `;
276
+ export const SWEEP_DLQ_INSERT = `
277
+ INSERT INTO jobs_dead
278
+ (id, queue, priority, payload, singleton_key,
279
+ retry_count, retry_limit, retry_delay_secs, retry_backoff,
280
+ created_at, last_error)
281
+ SELECT id, queue, priority, payload, singleton_key,
282
+ retry_count + 1, retry_limit, retry_delay_secs, retry_backoff,
283
+ created_at, JSON_OBJECT('message', 'lease expired', 'at', UTC_TIMESTAMP(6))
284
+ FROM jobs
285
+ WHERE id IN (?);
286
+ `;
287
+ export const SWEEP_DLQ_DELETE = `
288
+ DELETE FROM jobs WHERE id IN (?);
289
+ `;
290
+ // §6.3 — Archive retention
291
+ export const ARCHIVE_PRUNE = `
292
+ DELETE FROM jobs_archive
293
+ WHERE completed_at < UTC_TIMESTAMP(6) - INTERVAL ? DAY
294
+ ORDER BY completed_at
295
+ LIMIT 5000;
296
+ `;
297
+ // Archive query
298
+ export const GET_ARCHIVED_JOB = `
299
+ SELECT CAST(id AS CHAR) AS id, queue, priority, payload, singleton_key, retry_count,
300
+ UNIX_TIMESTAMP(created_at) AS created_at_unix,
301
+ UNIX_TIMESTAMP(started_at) AS started_at_unix,
302
+ UNIX_TIMESTAMP(completed_at) AS completed_at_unix,
303
+ duration_ms
304
+ FROM jobs_archive
305
+ WHERE id = ?;
306
+ `;
307
+ export const LIST_ARCHIVE = `
308
+ SELECT CAST(id AS CHAR) AS id, queue, priority, payload, singleton_key, retry_count,
309
+ UNIX_TIMESTAMP(created_at) AS created_at_unix,
310
+ UNIX_TIMESTAMP(started_at) AS started_at_unix,
311
+ UNIX_TIMESTAMP(completed_at) AS completed_at_unix,
312
+ duration_ms
313
+ FROM jobs_archive
314
+ WHERE queue = ? AND completed_at < ?
315
+ ORDER BY completed_at DESC
316
+ LIMIT ?;
317
+ `;
318
+ // Connection setup
319
+ export const INIT_SESSION = `
320
+ SET SESSION transaction_isolation = 'READ-COMMITTED',
321
+ SESSION time_zone = '+00:00';
322
+ `;
323
+ export const DEFAULT_TABLE_PREFIX = "mysql_boss";
324
+ export const UNPREFIXED_SQL = {
325
+ CREATE_JOBS,
326
+ CREATE_JOBS_ARCHIVE,
327
+ CREATE_JOBS_DEAD,
328
+ CREATE_SCHEDULES,
329
+ ENQUEUE,
330
+ ENQUEUE_SINGLETON,
331
+ LAST_INSERT_ID,
332
+ CLAIM_SELECT,
333
+ CLAIM_UPDATE,
334
+ COMPLETE_ARCHIVE,
335
+ COMPLETE_DELETE,
336
+ FAIL_RETRY,
337
+ DLQ_INSERT,
338
+ DLQ_DELETE,
339
+ LIST_DEAD,
340
+ REPLAY_INSERT,
341
+ REPLAY_DELETE,
342
+ DB_NOW,
343
+ TICK_SELECT,
344
+ TICK_ENQUEUE,
345
+ TICK_ADVANCE,
346
+ SCHEDULE_UPSERT,
347
+ SCHEDULE_DELETE,
348
+ HEARTBEAT,
349
+ HEARTBEAT_OWNED,
350
+ DRAIN_RELEASE,
351
+ SWEEP_SELECT,
352
+ SWEEP_RETRY,
353
+ SWEEP_DLQ_INSERT,
354
+ SWEEP_DLQ_DELETE,
355
+ ARCHIVE_PRUNE,
356
+ GET_ARCHIVED_JOB,
357
+ LIST_ARCHIVE,
358
+ };
359
+ const TABLE_SUFFIXES = [
360
+ "jobs_archive",
361
+ "jobs_dead",
362
+ "schedules",
363
+ "jobs",
364
+ ];
365
+ /**
366
+ * Builds the SQL used by one MysqlBoss instance.
367
+ *
368
+ * Prefixes are deliberately limited to portable identifier characters. This
369
+ * lets us quote every generated table name safely instead of interpolating an
370
+ * arbitrary SQL identifier.
371
+ */
372
+ export function createSql(tablePrefix = DEFAULT_TABLE_PREFIX) {
373
+ if (!/^[A-Za-z0-9_]*$/.test(tablePrefix)) {
374
+ throw new Error("tablePrefix may contain only ASCII letters, numbers, and underscores");
375
+ }
376
+ if (tablePrefix.length > 50) {
377
+ throw new Error("tablePrefix must be 50 characters or fewer");
378
+ }
379
+ const tableName = (suffix) => `\`${tablePrefix ? `${tablePrefix}_${suffix}` : suffix}\``;
380
+ const prefixTables = (statement) => {
381
+ let result = statement;
382
+ for (const suffix of TABLE_SUFFIXES) {
383
+ result = result.replace(new RegExp(`\\b${suffix}\\b`, "g"), tableName(suffix));
384
+ }
385
+ return result;
386
+ };
387
+ return Object.fromEntries(Object.entries(UNPREFIXED_SQL).map(([name, statement]) => [
388
+ name,
389
+ prefixTables(statement),
390
+ ]));
391
+ }
392
+ //# sourceMappingURL=sql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.js","sourceRoot":"","sources":["../../src/sql.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Pool } from "mysql2/promise";
2
+ import { type SqlStatements } from "./sql.js";
3
+ export declare function sweepStaleJobs(pool: Pool, sql?: SqlStatements): Promise<number>;
4
+ //# sourceMappingURL=sweep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep.d.ts","sourceRoot":"","sources":["../../src/sweep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAkC,MAAM,gBAAgB,CAAC;AAG3E,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,UAAU,CAAC;AAQ9D,wBAAsB,cAAc,CACnC,IAAI,EAAE,IAAI,EACV,GAAG,GAAE,aAA8B,GACjC,OAAO,CAAC,MAAM,CAAC,CA0CjB"}
@@ -0,0 +1,43 @@
1
+ import { acquireConnection } from "./connection.js";
2
+ import { withDeadlockRetry } from "./retry-util.js";
3
+ import { UNPREFIXED_SQL } from "./sql.js";
4
+ export async function sweepStaleJobs(pool, sql = UNPREFIXED_SQL) {
5
+ return withDeadlockRetry(async () => {
6
+ const conn = await acquireConnection(pool);
7
+ try {
8
+ await conn.beginTransaction();
9
+ const [rows] = await conn.query(sql.SWEEP_SELECT);
10
+ if (rows.length === 0) {
11
+ await conn.commit();
12
+ return 0;
13
+ }
14
+ const retryable = [];
15
+ const exhausted = [];
16
+ for (const row of rows) {
17
+ if (row.retry_count < row.retry_limit) {
18
+ retryable.push(row.id);
19
+ }
20
+ else {
21
+ exhausted.push(row.id);
22
+ }
23
+ }
24
+ if (retryable.length > 0) {
25
+ await conn.query(sql.SWEEP_RETRY, [retryable]);
26
+ }
27
+ if (exhausted.length > 0) {
28
+ await conn.query(sql.SWEEP_DLQ_INSERT, [exhausted]);
29
+ await conn.query(sql.SWEEP_DLQ_DELETE, [exhausted]);
30
+ }
31
+ await conn.commit();
32
+ return rows.length;
33
+ }
34
+ catch (err) {
35
+ await conn.rollback().catch(() => { });
36
+ throw err;
37
+ }
38
+ finally {
39
+ conn.release();
40
+ }
41
+ });
42
+ }
43
+ //# sourceMappingURL=sweep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep.js","sourceRoot":"","sources":["../../src/sweep.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAsB,cAAc,EAAE,MAAM,UAAU,CAAC;AAQ9D,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,IAAU,EACV,GAAG,GAAkB,cAAc;IAEnC,OAAO,iBAAiB,CAAC,KAAK,IAAI,EAAE;QACnC,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAE9B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAa,GAAG,CAAC,YAAY,CAAC,CAAC;YAE9D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;gBACpB,OAAO,CAAC,CAAC;YACV,CAAC;YAED,MAAM,SAAS,GAAa,EAAE,CAAC;YAC/B,MAAM,SAAS,GAAa,EAAE,CAAC;YAE/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACxB,IAAI,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;oBACvC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACP,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxB,CAAC;YACF,CAAC;YAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;YAChD,CAAC;YAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;gBACpD,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;YACrD,CAAC;YAED,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,MAAM,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtC,MAAM,GAAG,CAAC;QACX,CAAC;gBAAS,CAAC;YACV,IAAI,CAAC,OAAO,EAAE,CAAC;QAChB,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Pool } from "mysql2/promise";
2
+ import { type SqlStatements } from "./sql.js";
3
+ export declare function runTick(pool: Pool, sql?: SqlStatements): Promise<number>;
4
+ export declare function upsertSchedule(pool: Pool, name: string, queue: string, cron: string, timezone: string, payload: unknown, jobOptions: {
5
+ priority?: number;
6
+ retryLimit?: number;
7
+ retryDelaySecs?: number;
8
+ retryBackoff?: boolean;
9
+ } | null, sql?: SqlStatements): Promise<void>;
10
+ export declare function deleteSchedule(pool: Pool, name: string, sql?: SqlStatements): Promise<void>;
11
+ //# sourceMappingURL=tick.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tick.d.ts","sourceRoot":"","sources":["../../src/tick.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAiB,MAAM,gBAAgB,CAAC;AAM1D,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,UAAU,CAAC;AAsB9D,wBAAsB,OAAO,CAC5B,IAAI,EAAE,IAAI,EACV,GAAG,GAAE,aAA8B,GACjC,OAAO,CAAC,MAAM,CAAC,CAqDjB;AAED,wBAAsB,cAAc,CACnC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,IAAI,EACR,GAAG,GAAE,aAA8B,GACjC,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED,wBAAsB,cAAc,CACnC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,aAA8B,GACjC,OAAO,CAAC,IAAI,CAAC,CAIf"}
@@ -0,0 +1,77 @@
1
+ import { acquireConnection, withConnection } from "./connection.js";
2
+ import { nextOccurrence } from "./cron/next.js";
3
+ import { parseCron } from "./cron/parse.js";
4
+ import { withDeadlockRetry } from "./retry-util.js";
5
+ import { UNPREFIXED_SQL } from "./sql.js";
6
+ import { toUtcString } from "./util.js";
7
+ export async function runTick(pool, sql = UNPREFIXED_SQL) {
8
+ return withDeadlockRetry(async () => {
9
+ const conn = await acquireConnection(pool);
10
+ try {
11
+ await conn.beginTransaction();
12
+ const [nowRows] = await conn.query(sql.DB_NOW);
13
+ const dbNow = new Date(Number(nowRows[0].db_now_unix) * 1000);
14
+ const [schedules] = await conn.query(sql.TICK_SELECT);
15
+ if (schedules.length === 0) {
16
+ await conn.commit();
17
+ return 0;
18
+ }
19
+ let fired = 0;
20
+ for (const sched of schedules) {
21
+ const opts = sched.job_options ?? {};
22
+ const priority = opts.priority ?? 0;
23
+ const retryLimit = opts.retryLimit ?? 2;
24
+ const retryDelaySecs = opts.retryDelaySecs ?? 30;
25
+ const retryBackoff = opts.retryBackoff ? 1 : 0;
26
+ await conn.query(sql.TICK_ENQUEUE, [
27
+ sched.queue,
28
+ priority,
29
+ sched.payload != null ? JSON.stringify(sched.payload) : null,
30
+ sched.name,
31
+ toUtcString(new Date(Number(sched.next_run_at_unix) * 1000)),
32
+ retryLimit,
33
+ retryDelaySecs,
34
+ retryBackoff,
35
+ ]);
36
+ const fields = parseCron(sched.cron);
37
+ const nextRunAt = new Date(Number(sched.next_run_at_unix) * 1000);
38
+ const base = dbNow > nextRunAt ? dbNow : nextRunAt;
39
+ const nextRun = nextOccurrence(fields, base, sched.timezone);
40
+ await conn.query(sql.TICK_ADVANCE, [toUtcString(nextRun), sched.name]);
41
+ fired++;
42
+ }
43
+ await conn.commit();
44
+ return fired;
45
+ }
46
+ catch (err) {
47
+ await conn.rollback().catch(() => { });
48
+ throw err;
49
+ }
50
+ finally {
51
+ conn.release();
52
+ }
53
+ });
54
+ }
55
+ export async function upsertSchedule(pool, name, queue, cron, timezone, payload, jobOptions, sql = UNPREFIXED_SQL) {
56
+ const fields = parseCron(cron);
57
+ await withConnection(pool, async (connection) => {
58
+ const [nowRows] = await connection.query(sql.DB_NOW);
59
+ const dbNow = new Date(Number(nowRows[0].db_now_unix) * 1000);
60
+ const nextRun = nextOccurrence(fields, dbNow, timezone);
61
+ await connection.query(sql.SCHEDULE_UPSERT, [
62
+ name,
63
+ queue,
64
+ cron,
65
+ timezone,
66
+ payload != null ? JSON.stringify(payload) : null,
67
+ jobOptions ? JSON.stringify(jobOptions) : null,
68
+ toUtcString(nextRun),
69
+ ]);
70
+ });
71
+ }
72
+ export async function deleteSchedule(pool, name, sql = UNPREFIXED_SQL) {
73
+ await withConnection(pool, async (connection) => {
74
+ await connection.query(sql.SCHEDULE_DELETE, [name]);
75
+ });
76
+ }
77
+ //# sourceMappingURL=tick.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tick.js","sourceRoot":"","sources":["../../src/tick.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function toUtcString(date: Date): string;
2
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE9C"}
@@ -0,0 +1,4 @@
1
+ export function toUtcString(date) {
2
+ return date.toISOString().slice(0, 23).replace("T", " ");
3
+ }
4
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,IAAU;IACrC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { Pool } from "mysql2/promise";
2
+ import type { JobHandler } from "./index.js";
3
+ import type { SqlStatements } from "./sql.js";
4
+ interface WorkerConfig {
5
+ pool: Pool;
6
+ workerId: string;
7
+ pollIntervalMs: number;
8
+ batchSize: number;
9
+ concurrency: number;
10
+ leaseSeconds: number;
11
+ heartbeatSeconds: number;
12
+ sweepIntervalMs: number;
13
+ drainTimeoutMs: number;
14
+ onError: (err: unknown, context: string) => void;
15
+ sql: SqlStatements;
16
+ }
17
+ export declare class WorkerManager {
18
+ private config;
19
+ private registrations;
20
+ private inFlight;
21
+ private pollTimers;
22
+ private heartbeatTimer;
23
+ private sweepTimer;
24
+ private stopped;
25
+ constructor(config: WorkerConfig);
26
+ registerQueue(queue: string, handler: JobHandler): void;
27
+ private ensureTimers;
28
+ private startPolling;
29
+ private poll;
30
+ private schedulePoll;
31
+ private dispatch;
32
+ private executeJob;
33
+ private handleHandlerFailure;
34
+ private reportError;
35
+ private heartbeat;
36
+ private sweep;
37
+ stop(drainTimeoutMs?: number): Promise<void>;
38
+ get inFlightCount(): number;
39
+ get isStopped(): boolean;
40
+ }
41
+ export {};
42
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAO3C,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,UAAU,YAAY;IACrB,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,GAAG,EAAE,aAAa,CAAC;CACnB;AASD,qBAAa,aAAa;IACzB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,UAAU,CAAoD;IACtE,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,OAAO,CAAS;IAExB,YAAY,MAAM,EAAE,YAAY,EAE/B;IAED,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI,CAOtD;IAED,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,YAAY;YAKN,IAAI;IA2ClB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,QAAQ;YAkBF,UAAU;YA2BV,oBAAoB;IA6BlC,OAAO,CAAC,WAAW;YAQL,SAAS;YAwBT,KAAK;IAQb,IAAI,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEjD;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;CACD"}