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,82 @@
1
+ export declare const CREATE_JOBS = "\nCREATE TABLE IF NOT EXISTS jobs (\n id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,\n queue VARCHAR(128) NOT NULL,\n state ENUM('available','active') NOT NULL DEFAULT 'available',\n priority SMALLINT NOT NULL DEFAULT 0,\n payload JSON NULL,\n singleton_key VARCHAR(191) NULL,\n retry_count INT UNSIGNED NOT NULL DEFAULT 0,\n retry_limit INT UNSIGNED NOT NULL DEFAULT 2,\n retry_delay_secs INT UNSIGNED NOT NULL DEFAULT 30,\n retry_backoff TINYINT(1) NOT NULL DEFAULT 0,\n run_at DATETIME(6) NOT NULL,\n created_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),\n started_at DATETIME(6) NULL,\n locked_by BINARY(16) NULL,\n lease_expires_at DATETIME(6) NULL,\n last_error JSON NULL,\n PRIMARY KEY (id),\n UNIQUE KEY uq_jobs_singleton (queue, singleton_key),\n KEY ix_jobs_dequeue (queue, state, priority DESC, run_at, id),\n KEY ix_jobs_lease (state, lease_expires_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n";
2
+ export declare const CREATE_JOBS_ARCHIVE = "\nCREATE TABLE IF NOT EXISTS jobs_archive (\n id BIGINT UNSIGNED NOT NULL,\n queue VARCHAR(128) NOT NULL,\n priority SMALLINT NOT NULL,\n payload JSON NULL,\n singleton_key VARCHAR(191) NULL,\n retry_count INT UNSIGNED NOT NULL,\n created_at DATETIME(6) NOT NULL,\n started_at DATETIME(6) NOT NULL,\n completed_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),\n duration_ms INT UNSIGNED NOT NULL,\n PRIMARY KEY (id),\n KEY ix_archive_queue_time (queue, completed_at),\n KEY ix_archive_time (completed_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n";
3
+ export declare const CREATE_JOBS_DEAD = "\nCREATE TABLE IF NOT EXISTS jobs_dead (\n id BIGINT UNSIGNED NOT NULL,\n queue VARCHAR(128) NOT NULL,\n priority SMALLINT NOT NULL,\n payload JSON NULL,\n singleton_key VARCHAR(191) NULL,\n retry_count INT UNSIGNED NOT NULL,\n retry_limit INT UNSIGNED NOT NULL,\n retry_delay_secs INT UNSIGNED NOT NULL,\n retry_backoff TINYINT(1) NOT NULL,\n created_at DATETIME(6) NOT NULL,\n failed_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),\n last_error JSON NULL,\n PRIMARY KEY (id),\n KEY ix_dead_queue_time (queue, failed_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n";
4
+ export declare const CREATE_SCHEDULES = "\nCREATE TABLE IF NOT EXISTS schedules (\n name VARCHAR(128) NOT NULL,\n queue VARCHAR(128) NOT NULL,\n cron VARCHAR(64) NOT NULL,\n timezone VARCHAR(64) NOT NULL DEFAULT 'UTC',\n payload JSON NULL,\n job_options JSON NULL,\n next_run_at DATETIME(6) NOT NULL,\n last_enqueued_at DATETIME(6) NULL,\n updated_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6))\n ON UPDATE CURRENT_TIMESTAMP(6),\n PRIMARY KEY (name),\n KEY ix_schedules_due (next_run_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n";
5
+ export declare const ENQUEUE = "\nINSERT INTO jobs\n (queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, run_at)\nVALUES\n (?, ?, ?, ?, ?, ?, ?, COALESCE(?, UTC_TIMESTAMP(6)));\n";
6
+ export declare const ENQUEUE_SINGLETON = "\nINSERT IGNORE INTO jobs\n (queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, run_at)\nVALUES\n (?, ?, ?, ?, ?, ?, ?, COALESCE(?, UTC_TIMESTAMP(6)));\n";
7
+ export declare const LAST_INSERT_ID = "\nSELECT CAST(LAST_INSERT_ID() AS CHAR) AS id;\n";
8
+ export declare const CLAIM_SELECT = "\nSELECT CAST(id AS CHAR) AS id, queue, payload, retry_count, retry_limit,\n retry_delay_secs, retry_backoff\nFROM jobs\nWHERE queue = ?\n AND state = 'available'\n AND run_at <= UTC_TIMESTAMP(6)\nORDER BY priority DESC, run_at, id\nLIMIT ?\nFOR UPDATE SKIP LOCKED;\n";
9
+ export declare const CLAIM_UPDATE = "\nUPDATE jobs\nSET state = 'active',\n started_at = UTC_TIMESTAMP(6),\n locked_by = UUID_TO_BIN(?),\n lease_expires_at = UTC_TIMESTAMP(6) + INTERVAL ? SECOND\nWHERE id IN (?);\n";
10
+ export declare const COMPLETE_ARCHIVE = "\nINSERT INTO jobs_archive\n (id, queue, priority, payload, singleton_key, retry_count,\n created_at, started_at, duration_ms)\nSELECT id, queue, priority, payload, singleton_key, retry_count,\n created_at, started_at,\n TIMESTAMPDIFF(MICROSECOND, started_at, UTC_TIMESTAMP(6)) DIV 1000\nFROM jobs\nWHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
11
+ export declare const COMPLETE_DELETE = "\nDELETE FROM jobs\nWHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
12
+ export declare const FAIL_RETRY = "\nUPDATE jobs\nSET state = 'available',\n run_at = UTC_TIMESTAMP(6) + INTERVAL\n LEAST(\n 86400,\n IF(retry_backoff = 1,\n retry_delay_secs * POW(2, retry_count),\n retry_delay_secs)\n + FLOOR(RAND() * retry_delay_secs)\n ) SECOND,\n retry_count = retry_count + 1,\n locked_by = NULL,\n lease_expires_at = NULL,\n started_at = NULL,\n last_error = ?\nWHERE id = ?\n AND locked_by = UUID_TO_BIN(?)\n AND state = 'active'\n AND retry_count < retry_limit;\n";
13
+ export declare const DLQ_INSERT = "\nINSERT INTO jobs_dead\n (id, queue, priority, payload, singleton_key,\n retry_count, retry_limit, retry_delay_secs, retry_backoff,\n created_at, last_error)\nSELECT id, queue, priority, payload, singleton_key,\n retry_count + 1, retry_limit, retry_delay_secs, retry_backoff,\n created_at, ?\nFROM jobs\nWHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
14
+ export declare const DLQ_DELETE = "\nDELETE FROM jobs\nWHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
15
+ export declare const LIST_DEAD = "\nSELECT CAST(id AS CHAR) AS id, queue, priority, payload, retry_count,\n UNIX_TIMESTAMP(created_at) AS created_at_unix,\n UNIX_TIMESTAMP(failed_at) AS failed_at_unix,\n last_error\nFROM jobs_dead\nWHERE queue = ? AND failed_at BETWEEN ? AND ?\nORDER BY failed_at DESC\nLIMIT ? OFFSET ?;\n";
16
+ export declare const REPLAY_INSERT = "\nINSERT INTO jobs\n (queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, run_at)\nSELECT queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, UTC_TIMESTAMP(6)\nFROM jobs_dead\nWHERE id IN (?)\nFOR UPDATE;\n";
17
+ export declare const REPLAY_DELETE = "\nDELETE FROM jobs_dead WHERE id IN (?);\n";
18
+ export declare const DB_NOW = "SELECT UNIX_TIMESTAMP(UTC_TIMESTAMP(6)) AS db_now_unix;";
19
+ export declare const TICK_SELECT = "\nSELECT name, queue, cron, timezone, payload, job_options,\n next_run_at,\n UNIX_TIMESTAMP(next_run_at) AS next_run_at_unix\nFROM schedules\nWHERE next_run_at <= UTC_TIMESTAMP(6)\nORDER BY next_run_at\nLIMIT 20\nFOR UPDATE SKIP LOCKED;\n";
20
+ export declare const TICK_ENQUEUE = "\nINSERT IGNORE INTO jobs\n (queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, run_at)\nVALUES\n (?, ?, ?, CONCAT('cron:', ?, ':', DATE_FORMAT(?, '%Y%m%d%H%i%s')),\n ?, ?, ?, UTC_TIMESTAMP(6));\n";
21
+ export declare const TICK_ADVANCE = "\nUPDATE schedules\nSET next_run_at = ?, last_enqueued_at = UTC_TIMESTAMP(6)\nWHERE name = ?;\n";
22
+ export declare const SCHEDULE_UPSERT = "\nINSERT INTO schedules (name, queue, cron, timezone, payload, job_options, next_run_at)\nVALUES (?, ?, ?, ?, ?, ?, ?)\nON DUPLICATE KEY UPDATE\n queue = VALUES(queue),\n cron = VALUES(cron),\n timezone = VALUES(timezone),\n payload = VALUES(payload),\n job_options = VALUES(job_options),\n next_run_at = VALUES(next_run_at);\n";
23
+ export declare const SCHEDULE_DELETE = "\nDELETE FROM schedules WHERE name = ?;\n";
24
+ export declare const HEARTBEAT = "\nUPDATE jobs\nSET lease_expires_at = UTC_TIMESTAMP(6) + INTERVAL ? SECOND\nWHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
25
+ export declare const HEARTBEAT_OWNED = "\nSELECT CAST(id AS CHAR) AS id\nFROM jobs\nWHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
26
+ export declare const DRAIN_RELEASE = "\nUPDATE jobs\nSET state = 'available', run_at = UTC_TIMESTAMP(6),\n locked_by = NULL, lease_expires_at = NULL, started_at = NULL\nWHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
27
+ export declare const SWEEP_SELECT = "\nSELECT CAST(id AS CHAR) AS id, retry_count, retry_limit\nFROM jobs\nWHERE state = 'active' AND lease_expires_at < UTC_TIMESTAMP(6)\nORDER BY lease_expires_at\nLIMIT 100\nFOR UPDATE SKIP LOCKED;\n";
28
+ export declare const SWEEP_RETRY = "\nUPDATE jobs\nSET state = 'available',\n run_at = UTC_TIMESTAMP(6) + INTERVAL\n LEAST(\n 86400,\n IF(retry_backoff = 1,\n retry_delay_secs * POW(2, retry_count),\n retry_delay_secs)\n + FLOOR(RAND() * retry_delay_secs)\n ) SECOND,\n retry_count = retry_count + 1,\n locked_by = NULL, lease_expires_at = NULL, started_at = NULL,\n last_error = JSON_OBJECT('message', 'lease expired', 'at', UTC_TIMESTAMP(6))\nWHERE id IN (?) AND retry_count < retry_limit;\n";
29
+ export declare const SWEEP_DLQ_INSERT = "\nINSERT INTO jobs_dead\n (id, queue, priority, payload, singleton_key,\n retry_count, retry_limit, retry_delay_secs, retry_backoff,\n created_at, last_error)\nSELECT id, queue, priority, payload, singleton_key,\n retry_count + 1, retry_limit, retry_delay_secs, retry_backoff,\n created_at, JSON_OBJECT('message', 'lease expired', 'at', UTC_TIMESTAMP(6))\nFROM jobs\nWHERE id IN (?);\n";
30
+ export declare const SWEEP_DLQ_DELETE = "\nDELETE FROM jobs WHERE id IN (?);\n";
31
+ export declare const ARCHIVE_PRUNE = "\nDELETE FROM jobs_archive\nWHERE completed_at < UTC_TIMESTAMP(6) - INTERVAL ? DAY\nORDER BY completed_at\nLIMIT 5000;\n";
32
+ export declare const GET_ARCHIVED_JOB = "\nSELECT CAST(id AS CHAR) AS id, queue, priority, payload, singleton_key, retry_count,\n UNIX_TIMESTAMP(created_at) AS created_at_unix,\n UNIX_TIMESTAMP(started_at) AS started_at_unix,\n UNIX_TIMESTAMP(completed_at) AS completed_at_unix,\n duration_ms\nFROM jobs_archive\nWHERE id = ?;\n";
33
+ export declare const LIST_ARCHIVE = "\nSELECT CAST(id AS CHAR) AS id, queue, priority, payload, singleton_key, retry_count,\n UNIX_TIMESTAMP(created_at) AS created_at_unix,\n UNIX_TIMESTAMP(started_at) AS started_at_unix,\n UNIX_TIMESTAMP(completed_at) AS completed_at_unix,\n duration_ms\nFROM jobs_archive\nWHERE queue = ? AND completed_at < ?\nORDER BY completed_at DESC\nLIMIT ?;\n";
34
+ export declare const INIT_SESSION = "\nSET SESSION transaction_isolation = 'READ-COMMITTED',\n SESSION time_zone = '+00:00';\n";
35
+ export declare const DEFAULT_TABLE_PREFIX = "mysql_boss";
36
+ export declare const UNPREFIXED_SQL: {
37
+ readonly CREATE_JOBS: "\nCREATE TABLE IF NOT EXISTS jobs (\n id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,\n queue VARCHAR(128) NOT NULL,\n state ENUM('available','active') NOT NULL DEFAULT 'available',\n priority SMALLINT NOT NULL DEFAULT 0,\n payload JSON NULL,\n singleton_key VARCHAR(191) NULL,\n retry_count INT UNSIGNED NOT NULL DEFAULT 0,\n retry_limit INT UNSIGNED NOT NULL DEFAULT 2,\n retry_delay_secs INT UNSIGNED NOT NULL DEFAULT 30,\n retry_backoff TINYINT(1) NOT NULL DEFAULT 0,\n run_at DATETIME(6) NOT NULL,\n created_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),\n started_at DATETIME(6) NULL,\n locked_by BINARY(16) NULL,\n lease_expires_at DATETIME(6) NULL,\n last_error JSON NULL,\n PRIMARY KEY (id),\n UNIQUE KEY uq_jobs_singleton (queue, singleton_key),\n KEY ix_jobs_dequeue (queue, state, priority DESC, run_at, id),\n KEY ix_jobs_lease (state, lease_expires_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n";
38
+ readonly CREATE_JOBS_ARCHIVE: "\nCREATE TABLE IF NOT EXISTS jobs_archive (\n id BIGINT UNSIGNED NOT NULL,\n queue VARCHAR(128) NOT NULL,\n priority SMALLINT NOT NULL,\n payload JSON NULL,\n singleton_key VARCHAR(191) NULL,\n retry_count INT UNSIGNED NOT NULL,\n created_at DATETIME(6) NOT NULL,\n started_at DATETIME(6) NOT NULL,\n completed_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),\n duration_ms INT UNSIGNED NOT NULL,\n PRIMARY KEY (id),\n KEY ix_archive_queue_time (queue, completed_at),\n KEY ix_archive_time (completed_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n";
39
+ readonly CREATE_JOBS_DEAD: "\nCREATE TABLE IF NOT EXISTS jobs_dead (\n id BIGINT UNSIGNED NOT NULL,\n queue VARCHAR(128) NOT NULL,\n priority SMALLINT NOT NULL,\n payload JSON NULL,\n singleton_key VARCHAR(191) NULL,\n retry_count INT UNSIGNED NOT NULL,\n retry_limit INT UNSIGNED NOT NULL,\n retry_delay_secs INT UNSIGNED NOT NULL,\n retry_backoff TINYINT(1) NOT NULL,\n created_at DATETIME(6) NOT NULL,\n failed_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),\n last_error JSON NULL,\n PRIMARY KEY (id),\n KEY ix_dead_queue_time (queue, failed_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n";
40
+ readonly CREATE_SCHEDULES: "\nCREATE TABLE IF NOT EXISTS schedules (\n name VARCHAR(128) NOT NULL,\n queue VARCHAR(128) NOT NULL,\n cron VARCHAR(64) NOT NULL,\n timezone VARCHAR(64) NOT NULL DEFAULT 'UTC',\n payload JSON NULL,\n job_options JSON NULL,\n next_run_at DATETIME(6) NOT NULL,\n last_enqueued_at DATETIME(6) NULL,\n updated_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6))\n ON UPDATE CURRENT_TIMESTAMP(6),\n PRIMARY KEY (name),\n KEY ix_schedules_due (next_run_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n";
41
+ readonly ENQUEUE: "\nINSERT INTO jobs\n (queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, run_at)\nVALUES\n (?, ?, ?, ?, ?, ?, ?, COALESCE(?, UTC_TIMESTAMP(6)));\n";
42
+ readonly ENQUEUE_SINGLETON: "\nINSERT IGNORE INTO jobs\n (queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, run_at)\nVALUES\n (?, ?, ?, ?, ?, ?, ?, COALESCE(?, UTC_TIMESTAMP(6)));\n";
43
+ readonly LAST_INSERT_ID: "\nSELECT CAST(LAST_INSERT_ID() AS CHAR) AS id;\n";
44
+ readonly CLAIM_SELECT: "\nSELECT CAST(id AS CHAR) AS id, queue, payload, retry_count, retry_limit,\n retry_delay_secs, retry_backoff\nFROM jobs\nWHERE queue = ?\n AND state = 'available'\n AND run_at <= UTC_TIMESTAMP(6)\nORDER BY priority DESC, run_at, id\nLIMIT ?\nFOR UPDATE SKIP LOCKED;\n";
45
+ readonly CLAIM_UPDATE: "\nUPDATE jobs\nSET state = 'active',\n started_at = UTC_TIMESTAMP(6),\n locked_by = UUID_TO_BIN(?),\n lease_expires_at = UTC_TIMESTAMP(6) + INTERVAL ? SECOND\nWHERE id IN (?);\n";
46
+ readonly COMPLETE_ARCHIVE: "\nINSERT INTO jobs_archive\n (id, queue, priority, payload, singleton_key, retry_count,\n created_at, started_at, duration_ms)\nSELECT id, queue, priority, payload, singleton_key, retry_count,\n created_at, started_at,\n TIMESTAMPDIFF(MICROSECOND, started_at, UTC_TIMESTAMP(6)) DIV 1000\nFROM jobs\nWHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
47
+ readonly COMPLETE_DELETE: "\nDELETE FROM jobs\nWHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
48
+ readonly FAIL_RETRY: "\nUPDATE jobs\nSET state = 'available',\n run_at = UTC_TIMESTAMP(6) + INTERVAL\n LEAST(\n 86400,\n IF(retry_backoff = 1,\n retry_delay_secs * POW(2, retry_count),\n retry_delay_secs)\n + FLOOR(RAND() * retry_delay_secs)\n ) SECOND,\n retry_count = retry_count + 1,\n locked_by = NULL,\n lease_expires_at = NULL,\n started_at = NULL,\n last_error = ?\nWHERE id = ?\n AND locked_by = UUID_TO_BIN(?)\n AND state = 'active'\n AND retry_count < retry_limit;\n";
49
+ readonly DLQ_INSERT: "\nINSERT INTO jobs_dead\n (id, queue, priority, payload, singleton_key,\n retry_count, retry_limit, retry_delay_secs, retry_backoff,\n created_at, last_error)\nSELECT id, queue, priority, payload, singleton_key,\n retry_count + 1, retry_limit, retry_delay_secs, retry_backoff,\n created_at, ?\nFROM jobs\nWHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
50
+ readonly DLQ_DELETE: "\nDELETE FROM jobs\nWHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
51
+ readonly LIST_DEAD: "\nSELECT CAST(id AS CHAR) AS id, queue, priority, payload, retry_count,\n UNIX_TIMESTAMP(created_at) AS created_at_unix,\n UNIX_TIMESTAMP(failed_at) AS failed_at_unix,\n last_error\nFROM jobs_dead\nWHERE queue = ? AND failed_at BETWEEN ? AND ?\nORDER BY failed_at DESC\nLIMIT ? OFFSET ?;\n";
52
+ readonly REPLAY_INSERT: "\nINSERT INTO jobs\n (queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, run_at)\nSELECT queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, UTC_TIMESTAMP(6)\nFROM jobs_dead\nWHERE id IN (?)\nFOR UPDATE;\n";
53
+ readonly REPLAY_DELETE: "\nDELETE FROM jobs_dead WHERE id IN (?);\n";
54
+ readonly DB_NOW: "SELECT UNIX_TIMESTAMP(UTC_TIMESTAMP(6)) AS db_now_unix;";
55
+ readonly TICK_SELECT: "\nSELECT name, queue, cron, timezone, payload, job_options,\n next_run_at,\n UNIX_TIMESTAMP(next_run_at) AS next_run_at_unix\nFROM schedules\nWHERE next_run_at <= UTC_TIMESTAMP(6)\nORDER BY next_run_at\nLIMIT 20\nFOR UPDATE SKIP LOCKED;\n";
56
+ readonly TICK_ENQUEUE: "\nINSERT IGNORE INTO jobs\n (queue, priority, payload, singleton_key,\n retry_limit, retry_delay_secs, retry_backoff, run_at)\nVALUES\n (?, ?, ?, CONCAT('cron:', ?, ':', DATE_FORMAT(?, '%Y%m%d%H%i%s')),\n ?, ?, ?, UTC_TIMESTAMP(6));\n";
57
+ readonly TICK_ADVANCE: "\nUPDATE schedules\nSET next_run_at = ?, last_enqueued_at = UTC_TIMESTAMP(6)\nWHERE name = ?;\n";
58
+ readonly SCHEDULE_UPSERT: "\nINSERT INTO schedules (name, queue, cron, timezone, payload, job_options, next_run_at)\nVALUES (?, ?, ?, ?, ?, ?, ?)\nON DUPLICATE KEY UPDATE\n queue = VALUES(queue),\n cron = VALUES(cron),\n timezone = VALUES(timezone),\n payload = VALUES(payload),\n job_options = VALUES(job_options),\n next_run_at = VALUES(next_run_at);\n";
59
+ readonly SCHEDULE_DELETE: "\nDELETE FROM schedules WHERE name = ?;\n";
60
+ readonly HEARTBEAT: "\nUPDATE jobs\nSET lease_expires_at = UTC_TIMESTAMP(6) + INTERVAL ? SECOND\nWHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
61
+ readonly HEARTBEAT_OWNED: "\nSELECT CAST(id AS CHAR) AS id\nFROM jobs\nWHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
62
+ readonly DRAIN_RELEASE: "\nUPDATE jobs\nSET state = 'available', run_at = UTC_TIMESTAMP(6),\n locked_by = NULL, lease_expires_at = NULL, started_at = NULL\nWHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';\n";
63
+ readonly SWEEP_SELECT: "\nSELECT CAST(id AS CHAR) AS id, retry_count, retry_limit\nFROM jobs\nWHERE state = 'active' AND lease_expires_at < UTC_TIMESTAMP(6)\nORDER BY lease_expires_at\nLIMIT 100\nFOR UPDATE SKIP LOCKED;\n";
64
+ readonly SWEEP_RETRY: "\nUPDATE jobs\nSET state = 'available',\n run_at = UTC_TIMESTAMP(6) + INTERVAL\n LEAST(\n 86400,\n IF(retry_backoff = 1,\n retry_delay_secs * POW(2, retry_count),\n retry_delay_secs)\n + FLOOR(RAND() * retry_delay_secs)\n ) SECOND,\n retry_count = retry_count + 1,\n locked_by = NULL, lease_expires_at = NULL, started_at = NULL,\n last_error = JSON_OBJECT('message', 'lease expired', 'at', UTC_TIMESTAMP(6))\nWHERE id IN (?) AND retry_count < retry_limit;\n";
65
+ readonly SWEEP_DLQ_INSERT: "\nINSERT INTO jobs_dead\n (id, queue, priority, payload, singleton_key,\n retry_count, retry_limit, retry_delay_secs, retry_backoff,\n created_at, last_error)\nSELECT id, queue, priority, payload, singleton_key,\n retry_count + 1, retry_limit, retry_delay_secs, retry_backoff,\n created_at, JSON_OBJECT('message', 'lease expired', 'at', UTC_TIMESTAMP(6))\nFROM jobs\nWHERE id IN (?);\n";
66
+ readonly SWEEP_DLQ_DELETE: "\nDELETE FROM jobs WHERE id IN (?);\n";
67
+ readonly ARCHIVE_PRUNE: "\nDELETE FROM jobs_archive\nWHERE completed_at < UTC_TIMESTAMP(6) - INTERVAL ? DAY\nORDER BY completed_at\nLIMIT 5000;\n";
68
+ readonly GET_ARCHIVED_JOB: "\nSELECT CAST(id AS CHAR) AS id, queue, priority, payload, singleton_key, retry_count,\n UNIX_TIMESTAMP(created_at) AS created_at_unix,\n UNIX_TIMESTAMP(started_at) AS started_at_unix,\n UNIX_TIMESTAMP(completed_at) AS completed_at_unix,\n duration_ms\nFROM jobs_archive\nWHERE id = ?;\n";
69
+ readonly LIST_ARCHIVE: "\nSELECT CAST(id AS CHAR) AS id, queue, priority, payload, singleton_key, retry_count,\n UNIX_TIMESTAMP(created_at) AS created_at_unix,\n UNIX_TIMESTAMP(started_at) AS started_at_unix,\n UNIX_TIMESTAMP(completed_at) AS completed_at_unix,\n duration_ms\nFROM jobs_archive\nWHERE queue = ? AND completed_at < ?\nORDER BY completed_at DESC\nLIMIT ?;\n";
70
+ };
71
+ export type SqlStatements = {
72
+ [K in keyof typeof UNPREFIXED_SQL]: string;
73
+ };
74
+ /**
75
+ * Builds the SQL used by one MysqlBoss instance.
76
+ *
77
+ * Prefixes are deliberately limited to portable identifier characters. This
78
+ * lets us quote every generated table name safely instead of interpolating an
79
+ * arbitrary SQL identifier.
80
+ */
81
+ export declare function createSql(tablePrefix?: string): SqlStatements;
82
+ //# sourceMappingURL=sql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../../src/sql.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,mnCAuBvB,CAAC;AAEF,eAAO,MAAM,mBAAmB,6qBAgB/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,6uBAiB5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,ipBAe5B,CAAC;AAIF,eAAO,MAAM,OAAO,iMAMnB,CAAC;AAEF,eAAO,MAAM,iBAAiB,wMAM7B,CAAC;AAEF,eAAO,MAAM,cAAc,qDAE1B,CAAC;AAIF,eAAO,MAAM,YAAY,wRAUxB,CAAC;AAEF,eAAO,MAAM,YAAY,+LAOxB,CAAC;AAIF,eAAO,MAAM,gBAAgB,kYAS5B,CAAC;AAEF,eAAO,MAAM,eAAe,4FAG3B,CAAC;AAIF,eAAO,MAAM,UAAU,mhBAoBtB,CAAC;AAIF,eAAO,MAAM,UAAU,0YAUtB,CAAC;AAEF,eAAO,MAAM,UAAU,4FAGtB,CAAC;AAIF,eAAO,MAAM,SAAS,wTASrB,CAAC;AAIF,eAAO,MAAM,aAAa,sSASzB,CAAC;AAEF,eAAO,MAAM,aAAa,+CAEzB,CAAC;AAIF,eAAO,MAAM,MAAM,4DAA4D,CAAC;AAEhF,eAAO,MAAM,WAAW,+PASvB,CAAC;AAEF,eAAO,MAAM,YAAY,qPAOxB,CAAC;AAEF,eAAO,MAAM,YAAY,oGAIxB,CAAC;AAIF,eAAO,MAAM,eAAe,kVAU3B,CAAC;AAEF,eAAO,MAAM,eAAe,8CAE3B,CAAC;AAIF,eAAO,MAAM,SAAS,uJAIrB,CAAC;AAEF,eAAO,MAAM,eAAe,uHAI3B,CAAC;AAIF,eAAO,MAAM,aAAa,iNAKzB,CAAC;AAIF,eAAO,MAAM,YAAY,0MAOxB,CAAC;AAEF,eAAO,MAAM,WAAW,6gBAevB,CAAC;AAEF,eAAO,MAAM,gBAAgB,uZAU5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,0CAE5B,CAAC;AAIF,eAAO,MAAM,aAAa,6HAKzB,CAAC;AAIF,eAAO,MAAM,gBAAgB,4TAQ5B,CAAC;AAEF,eAAO,MAAM,YAAY,yXAUxB,CAAC;AAIF,eAAO,MAAM,YAAY,yGAGxB,CAAC;AAEF,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAEjD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCjB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG;KAC1B,CAAC,IAAI,MAAM,OAAO,cAAc,GAAG,MAAM;CAC1C,CAAC;AASF;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,WAAW,SAAuB,GAAG,aAAa,CA8B3E"}
@@ -0,0 +1,396 @@
1
+ "use strict";
2
+ // §1.1 — DDL
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.UNPREFIXED_SQL = exports.DEFAULT_TABLE_PREFIX = exports.INIT_SESSION = exports.LIST_ARCHIVE = exports.GET_ARCHIVED_JOB = exports.ARCHIVE_PRUNE = exports.SWEEP_DLQ_DELETE = exports.SWEEP_DLQ_INSERT = exports.SWEEP_RETRY = exports.SWEEP_SELECT = exports.DRAIN_RELEASE = exports.HEARTBEAT_OWNED = exports.HEARTBEAT = exports.SCHEDULE_DELETE = exports.SCHEDULE_UPSERT = exports.TICK_ADVANCE = exports.TICK_ENQUEUE = exports.TICK_SELECT = exports.DB_NOW = exports.REPLAY_DELETE = exports.REPLAY_INSERT = exports.LIST_DEAD = exports.DLQ_DELETE = exports.DLQ_INSERT = exports.FAIL_RETRY = exports.COMPLETE_DELETE = exports.COMPLETE_ARCHIVE = exports.CLAIM_UPDATE = exports.CLAIM_SELECT = exports.LAST_INSERT_ID = exports.ENQUEUE_SINGLETON = exports.ENQUEUE = exports.CREATE_SCHEDULES = exports.CREATE_JOBS_DEAD = exports.CREATE_JOBS_ARCHIVE = exports.CREATE_JOBS = void 0;
5
+ exports.createSql = createSql;
6
+ exports.CREATE_JOBS = `
7
+ CREATE TABLE IF NOT EXISTS jobs (
8
+ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
9
+ queue VARCHAR(128) NOT NULL,
10
+ state ENUM('available','active') NOT NULL DEFAULT 'available',
11
+ priority SMALLINT NOT NULL DEFAULT 0,
12
+ payload JSON NULL,
13
+ singleton_key VARCHAR(191) NULL,
14
+ retry_count INT UNSIGNED NOT NULL DEFAULT 0,
15
+ retry_limit INT UNSIGNED NOT NULL DEFAULT 2,
16
+ retry_delay_secs INT UNSIGNED NOT NULL DEFAULT 30,
17
+ retry_backoff TINYINT(1) NOT NULL DEFAULT 0,
18
+ run_at DATETIME(6) NOT NULL,
19
+ created_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),
20
+ started_at DATETIME(6) NULL,
21
+ locked_by BINARY(16) NULL,
22
+ lease_expires_at DATETIME(6) NULL,
23
+ last_error JSON NULL,
24
+ PRIMARY KEY (id),
25
+ UNIQUE KEY uq_jobs_singleton (queue, singleton_key),
26
+ KEY ix_jobs_dequeue (queue, state, priority DESC, run_at, id),
27
+ KEY ix_jobs_lease (state, lease_expires_at)
28
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
29
+ `;
30
+ exports.CREATE_JOBS_ARCHIVE = `
31
+ CREATE TABLE IF NOT EXISTS jobs_archive (
32
+ id BIGINT UNSIGNED NOT NULL,
33
+ queue VARCHAR(128) NOT NULL,
34
+ priority SMALLINT NOT NULL,
35
+ payload JSON NULL,
36
+ singleton_key VARCHAR(191) NULL,
37
+ retry_count INT UNSIGNED NOT NULL,
38
+ created_at DATETIME(6) NOT NULL,
39
+ started_at DATETIME(6) NOT NULL,
40
+ completed_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),
41
+ duration_ms INT UNSIGNED NOT NULL,
42
+ PRIMARY KEY (id),
43
+ KEY ix_archive_queue_time (queue, completed_at),
44
+ KEY ix_archive_time (completed_at)
45
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
46
+ `;
47
+ exports.CREATE_JOBS_DEAD = `
48
+ CREATE TABLE IF NOT EXISTS jobs_dead (
49
+ id BIGINT UNSIGNED NOT NULL,
50
+ queue VARCHAR(128) NOT NULL,
51
+ priority SMALLINT NOT NULL,
52
+ payload JSON NULL,
53
+ singleton_key VARCHAR(191) NULL,
54
+ retry_count INT UNSIGNED NOT NULL,
55
+ retry_limit INT UNSIGNED NOT NULL,
56
+ retry_delay_secs INT UNSIGNED NOT NULL,
57
+ retry_backoff TINYINT(1) NOT NULL,
58
+ created_at DATETIME(6) NOT NULL,
59
+ failed_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6)),
60
+ last_error JSON NULL,
61
+ PRIMARY KEY (id),
62
+ KEY ix_dead_queue_time (queue, failed_at)
63
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
64
+ `;
65
+ exports.CREATE_SCHEDULES = `
66
+ CREATE TABLE IF NOT EXISTS schedules (
67
+ name VARCHAR(128) NOT NULL,
68
+ queue VARCHAR(128) NOT NULL,
69
+ cron VARCHAR(64) NOT NULL,
70
+ timezone VARCHAR(64) NOT NULL DEFAULT 'UTC',
71
+ payload JSON NULL,
72
+ job_options JSON NULL,
73
+ next_run_at DATETIME(6) NOT NULL,
74
+ last_enqueued_at DATETIME(6) NULL,
75
+ updated_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6))
76
+ ON UPDATE CURRENT_TIMESTAMP(6),
77
+ PRIMARY KEY (name),
78
+ KEY ix_schedules_due (next_run_at)
79
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
80
+ `;
81
+ // §1.2 — Enqueue
82
+ exports.ENQUEUE = `
83
+ INSERT INTO jobs
84
+ (queue, priority, payload, singleton_key,
85
+ retry_limit, retry_delay_secs, retry_backoff, run_at)
86
+ VALUES
87
+ (?, ?, ?, ?, ?, ?, ?, COALESCE(?, UTC_TIMESTAMP(6)));
88
+ `;
89
+ exports.ENQUEUE_SINGLETON = `
90
+ INSERT IGNORE INTO jobs
91
+ (queue, priority, payload, singleton_key,
92
+ retry_limit, retry_delay_secs, retry_backoff, run_at)
93
+ VALUES
94
+ (?, ?, ?, ?, ?, ?, ?, COALESCE(?, UTC_TIMESTAMP(6)));
95
+ `;
96
+ exports.LAST_INSERT_ID = `
97
+ SELECT CAST(LAST_INSERT_ID() AS CHAR) AS id;
98
+ `;
99
+ // §1.2 — Dequeue / claim
100
+ exports.CLAIM_SELECT = `
101
+ SELECT CAST(id AS CHAR) AS id, queue, payload, retry_count, retry_limit,
102
+ retry_delay_secs, retry_backoff
103
+ FROM jobs
104
+ WHERE queue = ?
105
+ AND state = 'available'
106
+ AND run_at <= UTC_TIMESTAMP(6)
107
+ ORDER BY priority DESC, run_at, id
108
+ LIMIT ?
109
+ FOR UPDATE SKIP LOCKED;
110
+ `;
111
+ exports.CLAIM_UPDATE = `
112
+ UPDATE jobs
113
+ SET state = 'active',
114
+ started_at = UTC_TIMESTAMP(6),
115
+ locked_by = UUID_TO_BIN(?),
116
+ lease_expires_at = UTC_TIMESTAMP(6) + INTERVAL ? SECOND
117
+ WHERE id IN (?);
118
+ `;
119
+ // §1.2 — Complete (archive move)
120
+ exports.COMPLETE_ARCHIVE = `
121
+ INSERT INTO jobs_archive
122
+ (id, queue, priority, payload, singleton_key, retry_count,
123
+ created_at, started_at, duration_ms)
124
+ SELECT id, queue, priority, payload, singleton_key, retry_count,
125
+ created_at, started_at,
126
+ TIMESTAMPDIFF(MICROSECOND, started_at, UTC_TIMESTAMP(6)) DIV 1000
127
+ FROM jobs
128
+ WHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';
129
+ `;
130
+ exports.COMPLETE_DELETE = `
131
+ DELETE FROM jobs
132
+ WHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';
133
+ `;
134
+ // §2.2 — Fail with retries remaining
135
+ exports.FAIL_RETRY = `
136
+ UPDATE jobs
137
+ SET state = 'available',
138
+ run_at = UTC_TIMESTAMP(6) + INTERVAL
139
+ LEAST(
140
+ 86400,
141
+ IF(retry_backoff = 1,
142
+ retry_delay_secs * POW(2, retry_count),
143
+ retry_delay_secs)
144
+ + FLOOR(RAND() * retry_delay_secs)
145
+ ) SECOND,
146
+ retry_count = retry_count + 1,
147
+ locked_by = NULL,
148
+ lease_expires_at = NULL,
149
+ started_at = NULL,
150
+ last_error = ?
151
+ WHERE id = ?
152
+ AND locked_by = UUID_TO_BIN(?)
153
+ AND state = 'active'
154
+ AND retry_count < retry_limit;
155
+ `;
156
+ // §3.2 — Dead-letter move
157
+ exports.DLQ_INSERT = `
158
+ INSERT INTO jobs_dead
159
+ (id, queue, priority, payload, singleton_key,
160
+ retry_count, retry_limit, retry_delay_secs, retry_backoff,
161
+ created_at, last_error)
162
+ SELECT id, queue, priority, payload, singleton_key,
163
+ retry_count + 1, retry_limit, retry_delay_secs, retry_backoff,
164
+ created_at, ?
165
+ FROM jobs
166
+ WHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';
167
+ `;
168
+ exports.DLQ_DELETE = `
169
+ DELETE FROM jobs
170
+ WHERE id = ? AND locked_by = UUID_TO_BIN(?) AND state = 'active';
171
+ `;
172
+ // §3.2 — DLQ query
173
+ exports.LIST_DEAD = `
174
+ SELECT CAST(id AS CHAR) AS id, queue, priority, payload, retry_count,
175
+ UNIX_TIMESTAMP(created_at) AS created_at_unix,
176
+ UNIX_TIMESTAMP(failed_at) AS failed_at_unix,
177
+ last_error
178
+ FROM jobs_dead
179
+ WHERE queue = ? AND failed_at BETWEEN ? AND ?
180
+ ORDER BY failed_at DESC
181
+ LIMIT ? OFFSET ?;
182
+ `;
183
+ // §3.2 — Replay
184
+ exports.REPLAY_INSERT = `
185
+ INSERT INTO jobs
186
+ (queue, priority, payload, singleton_key,
187
+ retry_limit, retry_delay_secs, retry_backoff, run_at)
188
+ SELECT queue, priority, payload, singleton_key,
189
+ retry_limit, retry_delay_secs, retry_backoff, UTC_TIMESTAMP(6)
190
+ FROM jobs_dead
191
+ WHERE id IN (?)
192
+ FOR UPDATE;
193
+ `;
194
+ exports.REPLAY_DELETE = `
195
+ DELETE FROM jobs_dead WHERE id IN (?);
196
+ `;
197
+ // §4.2 — Cron tick
198
+ exports.DB_NOW = "SELECT UNIX_TIMESTAMP(UTC_TIMESTAMP(6)) AS db_now_unix;";
199
+ exports.TICK_SELECT = `
200
+ SELECT name, queue, cron, timezone, payload, job_options,
201
+ next_run_at,
202
+ UNIX_TIMESTAMP(next_run_at) AS next_run_at_unix
203
+ FROM schedules
204
+ WHERE next_run_at <= UTC_TIMESTAMP(6)
205
+ ORDER BY next_run_at
206
+ LIMIT 20
207
+ FOR UPDATE SKIP LOCKED;
208
+ `;
209
+ exports.TICK_ENQUEUE = `
210
+ INSERT IGNORE INTO jobs
211
+ (queue, priority, payload, singleton_key,
212
+ retry_limit, retry_delay_secs, retry_backoff, run_at)
213
+ VALUES
214
+ (?, ?, ?, CONCAT('cron:', ?, ':', DATE_FORMAT(?, '%Y%m%d%H%i%s')),
215
+ ?, ?, ?, UTC_TIMESTAMP(6));
216
+ `;
217
+ exports.TICK_ADVANCE = `
218
+ UPDATE schedules
219
+ SET next_run_at = ?, last_enqueued_at = UTC_TIMESTAMP(6)
220
+ WHERE name = ?;
221
+ `;
222
+ // §4 — Schedule CRUD
223
+ exports.SCHEDULE_UPSERT = `
224
+ INSERT INTO schedules (name, queue, cron, timezone, payload, job_options, next_run_at)
225
+ VALUES (?, ?, ?, ?, ?, ?, ?)
226
+ ON DUPLICATE KEY UPDATE
227
+ queue = VALUES(queue),
228
+ cron = VALUES(cron),
229
+ timezone = VALUES(timezone),
230
+ payload = VALUES(payload),
231
+ job_options = VALUES(job_options),
232
+ next_run_at = VALUES(next_run_at);
233
+ `;
234
+ exports.SCHEDULE_DELETE = `
235
+ DELETE FROM schedules WHERE name = ?;
236
+ `;
237
+ // §6.1 — Heartbeat
238
+ exports.HEARTBEAT = `
239
+ UPDATE jobs
240
+ SET lease_expires_at = UTC_TIMESTAMP(6) + INTERVAL ? SECOND
241
+ WHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';
242
+ `;
243
+ exports.HEARTBEAT_OWNED = `
244
+ SELECT CAST(id AS CHAR) AS id
245
+ FROM jobs
246
+ WHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';
247
+ `;
248
+ // §6.2 — Drain release
249
+ exports.DRAIN_RELEASE = `
250
+ UPDATE jobs
251
+ SET state = 'available', run_at = UTC_TIMESTAMP(6),
252
+ locked_by = NULL, lease_expires_at = NULL, started_at = NULL
253
+ WHERE id IN (?) AND locked_by = UUID_TO_BIN(?) AND state = 'active';
254
+ `;
255
+ // §6.3 — Stale sweep
256
+ exports.SWEEP_SELECT = `
257
+ SELECT CAST(id AS CHAR) AS id, retry_count, retry_limit
258
+ FROM jobs
259
+ WHERE state = 'active' AND lease_expires_at < UTC_TIMESTAMP(6)
260
+ ORDER BY lease_expires_at
261
+ LIMIT 100
262
+ FOR UPDATE SKIP LOCKED;
263
+ `;
264
+ exports.SWEEP_RETRY = `
265
+ UPDATE jobs
266
+ SET state = 'available',
267
+ run_at = UTC_TIMESTAMP(6) + INTERVAL
268
+ LEAST(
269
+ 86400,
270
+ IF(retry_backoff = 1,
271
+ retry_delay_secs * POW(2, retry_count),
272
+ retry_delay_secs)
273
+ + FLOOR(RAND() * retry_delay_secs)
274
+ ) SECOND,
275
+ retry_count = retry_count + 1,
276
+ locked_by = NULL, lease_expires_at = NULL, started_at = NULL,
277
+ last_error = JSON_OBJECT('message', 'lease expired', 'at', UTC_TIMESTAMP(6))
278
+ WHERE id IN (?) AND retry_count < retry_limit;
279
+ `;
280
+ exports.SWEEP_DLQ_INSERT = `
281
+ INSERT INTO jobs_dead
282
+ (id, queue, priority, payload, singleton_key,
283
+ retry_count, retry_limit, retry_delay_secs, retry_backoff,
284
+ created_at, last_error)
285
+ SELECT id, queue, priority, payload, singleton_key,
286
+ retry_count + 1, retry_limit, retry_delay_secs, retry_backoff,
287
+ created_at, JSON_OBJECT('message', 'lease expired', 'at', UTC_TIMESTAMP(6))
288
+ FROM jobs
289
+ WHERE id IN (?);
290
+ `;
291
+ exports.SWEEP_DLQ_DELETE = `
292
+ DELETE FROM jobs WHERE id IN (?);
293
+ `;
294
+ // §6.3 — Archive retention
295
+ exports.ARCHIVE_PRUNE = `
296
+ DELETE FROM jobs_archive
297
+ WHERE completed_at < UTC_TIMESTAMP(6) - INTERVAL ? DAY
298
+ ORDER BY completed_at
299
+ LIMIT 5000;
300
+ `;
301
+ // Archive query
302
+ exports.GET_ARCHIVED_JOB = `
303
+ SELECT CAST(id AS CHAR) AS id, queue, priority, payload, singleton_key, retry_count,
304
+ UNIX_TIMESTAMP(created_at) AS created_at_unix,
305
+ UNIX_TIMESTAMP(started_at) AS started_at_unix,
306
+ UNIX_TIMESTAMP(completed_at) AS completed_at_unix,
307
+ duration_ms
308
+ FROM jobs_archive
309
+ WHERE id = ?;
310
+ `;
311
+ exports.LIST_ARCHIVE = `
312
+ SELECT CAST(id AS CHAR) AS id, queue, priority, payload, singleton_key, retry_count,
313
+ UNIX_TIMESTAMP(created_at) AS created_at_unix,
314
+ UNIX_TIMESTAMP(started_at) AS started_at_unix,
315
+ UNIX_TIMESTAMP(completed_at) AS completed_at_unix,
316
+ duration_ms
317
+ FROM jobs_archive
318
+ WHERE queue = ? AND completed_at < ?
319
+ ORDER BY completed_at DESC
320
+ LIMIT ?;
321
+ `;
322
+ // Connection setup
323
+ exports.INIT_SESSION = `
324
+ SET SESSION transaction_isolation = 'READ-COMMITTED',
325
+ SESSION time_zone = '+00:00';
326
+ `;
327
+ exports.DEFAULT_TABLE_PREFIX = "mysql_boss";
328
+ exports.UNPREFIXED_SQL = {
329
+ CREATE_JOBS: exports.CREATE_JOBS,
330
+ CREATE_JOBS_ARCHIVE: exports.CREATE_JOBS_ARCHIVE,
331
+ CREATE_JOBS_DEAD: exports.CREATE_JOBS_DEAD,
332
+ CREATE_SCHEDULES: exports.CREATE_SCHEDULES,
333
+ ENQUEUE: exports.ENQUEUE,
334
+ ENQUEUE_SINGLETON: exports.ENQUEUE_SINGLETON,
335
+ LAST_INSERT_ID: exports.LAST_INSERT_ID,
336
+ CLAIM_SELECT: exports.CLAIM_SELECT,
337
+ CLAIM_UPDATE: exports.CLAIM_UPDATE,
338
+ COMPLETE_ARCHIVE: exports.COMPLETE_ARCHIVE,
339
+ COMPLETE_DELETE: exports.COMPLETE_DELETE,
340
+ FAIL_RETRY: exports.FAIL_RETRY,
341
+ DLQ_INSERT: exports.DLQ_INSERT,
342
+ DLQ_DELETE: exports.DLQ_DELETE,
343
+ LIST_DEAD: exports.LIST_DEAD,
344
+ REPLAY_INSERT: exports.REPLAY_INSERT,
345
+ REPLAY_DELETE: exports.REPLAY_DELETE,
346
+ DB_NOW: exports.DB_NOW,
347
+ TICK_SELECT: exports.TICK_SELECT,
348
+ TICK_ENQUEUE: exports.TICK_ENQUEUE,
349
+ TICK_ADVANCE: exports.TICK_ADVANCE,
350
+ SCHEDULE_UPSERT: exports.SCHEDULE_UPSERT,
351
+ SCHEDULE_DELETE: exports.SCHEDULE_DELETE,
352
+ HEARTBEAT: exports.HEARTBEAT,
353
+ HEARTBEAT_OWNED: exports.HEARTBEAT_OWNED,
354
+ DRAIN_RELEASE: exports.DRAIN_RELEASE,
355
+ SWEEP_SELECT: exports.SWEEP_SELECT,
356
+ SWEEP_RETRY: exports.SWEEP_RETRY,
357
+ SWEEP_DLQ_INSERT: exports.SWEEP_DLQ_INSERT,
358
+ SWEEP_DLQ_DELETE: exports.SWEEP_DLQ_DELETE,
359
+ ARCHIVE_PRUNE: exports.ARCHIVE_PRUNE,
360
+ GET_ARCHIVED_JOB: exports.GET_ARCHIVED_JOB,
361
+ LIST_ARCHIVE: exports.LIST_ARCHIVE,
362
+ };
363
+ const TABLE_SUFFIXES = [
364
+ "jobs_archive",
365
+ "jobs_dead",
366
+ "schedules",
367
+ "jobs",
368
+ ];
369
+ /**
370
+ * Builds the SQL used by one MysqlBoss instance.
371
+ *
372
+ * Prefixes are deliberately limited to portable identifier characters. This
373
+ * lets us quote every generated table name safely instead of interpolating an
374
+ * arbitrary SQL identifier.
375
+ */
376
+ function createSql(tablePrefix = exports.DEFAULT_TABLE_PREFIX) {
377
+ if (!/^[A-Za-z0-9_]*$/.test(tablePrefix)) {
378
+ throw new Error("tablePrefix may contain only ASCII letters, numbers, and underscores");
379
+ }
380
+ if (tablePrefix.length > 50) {
381
+ throw new Error("tablePrefix must be 50 characters or fewer");
382
+ }
383
+ const tableName = (suffix) => `\`${tablePrefix ? `${tablePrefix}_${suffix}` : suffix}\``;
384
+ const prefixTables = (statement) => {
385
+ let result = statement;
386
+ for (const suffix of TABLE_SUFFIXES) {
387
+ result = result.replace(new RegExp(`\\b${suffix}\\b`, "g"), tableName(suffix));
388
+ }
389
+ return result;
390
+ };
391
+ return Object.fromEntries(Object.entries(exports.UNPREFIXED_SQL).map(([name, statement]) => [
392
+ name,
393
+ prefixTables(statement),
394
+ ]));
395
+ }
396
+ //# 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,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sweepStaleJobs = sweepStaleJobs;
4
+ const connection_js_1 = require("./connection.js");
5
+ const retry_util_js_1 = require("./retry-util.js");
6
+ const sql_js_1 = require("./sql.js");
7
+ async function sweepStaleJobs(pool, sql = sql_js_1.UNPREFIXED_SQL) {
8
+ return (0, retry_util_js_1.withDeadlockRetry)(async () => {
9
+ const conn = await (0, connection_js_1.acquireConnection)(pool);
10
+ try {
11
+ await conn.beginTransaction();
12
+ const [rows] = await conn.query(sql.SWEEP_SELECT);
13
+ if (rows.length === 0) {
14
+ await conn.commit();
15
+ return 0;
16
+ }
17
+ const retryable = [];
18
+ const exhausted = [];
19
+ for (const row of rows) {
20
+ if (row.retry_count < row.retry_limit) {
21
+ retryable.push(row.id);
22
+ }
23
+ else {
24
+ exhausted.push(row.id);
25
+ }
26
+ }
27
+ if (retryable.length > 0) {
28
+ await conn.query(sql.SWEEP_RETRY, [retryable]);
29
+ }
30
+ if (exhausted.length > 0) {
31
+ await conn.query(sql.SWEEP_DLQ_INSERT, [exhausted]);
32
+ await conn.query(sql.SWEEP_DLQ_DELETE, [exhausted]);
33
+ }
34
+ await conn.commit();
35
+ return rows.length;
36
+ }
37
+ catch (err) {
38
+ await conn.rollback().catch(() => { });
39
+ throw err;
40
+ }
41
+ finally {
42
+ conn.release();
43
+ }
44
+ });
45
+ }
46
+ //# sourceMappingURL=sweep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep.js","sourceRoot":"","sources":["../../src/sweep.ts"],"names":[],"mappings":";;;AACA,mDAAoD;AACpD,mDAAoD;AACpD,qCAA8D;AAQvD,KAAK,yBACX,IAAU,EACV,GAAG,GAAkB,uBAAc;IAEnC,OAAO,IAAA,iCAAiB,EAAC,KAAK,IAAI,EAAE;QACnC,MAAM,IAAI,GAAG,MAAM,IAAA,iCAAiB,EAAC,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"}