You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-`retryJob` does not touch the dedup entry — a retried job continues to occupy the dedup slot. TTL runs on wall-clock time, so long-running retries may outlive the TTL window. Use a generous TTL or no TTL if retries must stay deduped.
268
268
- Atomic and race-free:
269
269
-**Redis**: a single Lua script per dispatch performs the dedup-key lookup, state check (pending/delayed ZSCORE), payload swap, and TTL refresh atomically.
270
-
-**Knex**: transactional `SELECT ... FOR UPDATE` + insert/update inside a transaction. A nested savepoint catches unique-constraint violations under concurrent inserts and returns `{ deduped: 'skipped' }` pointing at the winner.
270
+
-**Knex/Kysely**: transactional `SELECT ... FOR UPDATE` + insert/update inside a transaction. A savepoint catches unique-constraint violations under concurrent inserts and returns `{ deduped: 'skipped' }` pointing at the winner.
271
271
-**SyncAdapter**: executes inline, no dedup support.
272
272
273
273
### Caveats
274
274
275
275
- Without `.dedup()`, jobs use auto-generated UUIDs and are never deduplicated.
276
-
- The **Sync adapter** ignores `.dedup()` entirely — every dispatch executes inline and `deduped` is always `undefined` on the result. Use Redisor Knex if you need real deduplication.
276
+
- The **Sync adapter** ignores `.dedup()` entirely — every dispatch executes inline and `deduped` is always `undefined` on the result. Use Redis, Knex, or Kysely if you need real deduplication.
277
277
-`.dedup()` is only available on single dispatch. `dispatchMany` / `pushManyOn` reject jobs with a `dedup` field.
278
278
- Scheduled jobs (`.schedule()`) do not support dedup — each cron/interval fire is an independent dispatch.
279
279
- With no `ttl`, dedup persists until the job is removed (completed/failed without retention). When retention keeps the record, re-dispatch stays blocked until the record is pruned.
280
280
- With `ttl`, dedup expires after the window — a new job (new UUID) is created. The old job still runs.
281
-
- Knex MySQL concurrent race: MySQL does not support partial unique indexes, so two `pushOn` calls with the same dedup id firing at the exact same instant can both succeed. Serialize at the app layer if strict guarantees are required, or use Postgres / SQLite / Redis (all of which serialize correctly via the partial unique index or Lua atomicity).
281
+
- Knex/Kysely MySQL concurrent race: MySQL does not support partial unique indexes, so two `pushOn` calls with the same dedup id firing at the exact same instant can both succeed. Serialize at the app layer if strict guarantees are required, or use Postgres / SQLite / Redis (all of which serialize correctly via the partial unique index or Lua atomicity).
282
282
283
283
## Job History & Retention
284
284
@@ -405,6 +405,43 @@ export default class extends BaseSchema {
405
405
406
406
</details>
407
407
408
+
### Kysely (PostgreSQL, MySQL, SQLite)
409
+
410
+
Pass the application-owned Kysely instance to the adapter factory.
0 commit comments