diff --git a/site/src/content/docs/concepts/the-scheduler.md b/site/src/content/docs/concepts/the-scheduler.md index 86fed78..ffd8ded 100644 --- a/site/src/content/docs/concepts/the-scheduler.md +++ b/site/src/content/docs/concepts/the-scheduler.md @@ -41,7 +41,7 @@ The lock TTL is generous (default 30s). If the lock-holder crashes mid-tick, the ## The scheduler (repeatable specs) -The scheduler is the same shape as the promoter, but operating on `{chasqui:}:repeat` (a sorted set scored by next-fire-ms) plus `{chasqui:}:repeat:specs` (a hash mapping spec key → encoded `RepeatSpec`). +The scheduler is the same shape as the promoter, but operating on `{chasqui:}:repeat` (a sorted set scored by next-fire-ms) plus a per-spec `{chasqui:}:repeat:spec:` hash holding the encoded `RepeatSpec`. Each tick: diff --git a/site/src/content/docs/concepts/thinking-in-chasquimq.mdx b/site/src/content/docs/concepts/thinking-in-chasquimq.mdx index 622cf52..7a22079 100644 --- a/site/src/content/docs/concepts/thinking-in-chasquimq.mdx +++ b/site/src/content/docs/concepts/thinking-in-chasquimq.mdx @@ -42,7 +42,7 @@ Five tasks: producer, reader, workers, retry relocator, DLQ relocator. The reade Edge cases: - `delay > 0` → instead of `XADD`, the engine writes to the delayed sorted set (`{...}:delayed`, scored by run-at-ms). The promoter task, embedded in every `Worker`, periodically `ZRANGEBYSCORE`s due entries and atomically promotes them via Lua. -- `repeat: { ... }` → no immediate enqueue. Instead, the producer upserts a *spec* into `{...}:repeat` (sorted set keyed by next fire time) plus `{...}:repeat:specs` (hash of full spec body). The scheduler — also auto-spawned by `Worker` — fires fresh jobs from the spec on each window. +- `repeat: { ... }` → no immediate enqueue. Instead, the producer upserts a *spec* into `{...}:repeat` (sorted set keyed by next fire time) plus a per-spec `{...}:repeat:spec:` hash holding the full spec body. The scheduler — also auto-spawned by `Worker` — fires fresh jobs from the spec on each window. - `addUnique(name, data, { jobId })` → the producer pre-pends a Lua-gated `SET NX EX` dedup marker (`{...}:dlid:`) for delayed jobs, or uses Redis 8.6 `XADD ... IDMP ` for immediate jobs. Either way, a duplicate `addUnique` returns the same id, no second entry. ## What happens on the consumer side @@ -74,7 +74,7 @@ The CLAIM path is the safety net for crashed workers. If a worker dies after rea ## Repeatable specs are not jobs -A repeatable spec is a *recipe*. The engine fires fresh jobs from it on each window — a new ULID, a new entry on the stream, a new ack/retry/DLQ lifecycle. The spec itself lives in the `:repeat` ZSET and the `:repeat:specs` hash; it never enters the stream. +A repeatable spec is a *recipe*. The engine fires fresh jobs from it on each window — a new ULID, a new entry on the stream, a new ack/retry/DLQ lifecycle. The spec itself lives in the `:repeat` ZSET and a per-spec `:repeat:spec:` hash; it never enters the stream. This is why `chasqui repeatable list` reports specs by their resolved key (`::`), not by job id — there is no single id, just the recipe. diff --git a/site/src/content/docs/guides/schedule-repeatable-jobs.mdx b/site/src/content/docs/guides/schedule-repeatable-jobs.mdx index e7e81e7..0df2bc9 100644 --- a/site/src/content/docs/guides/schedule-repeatable-jobs.mdx +++ b/site/src/content/docs/guides/schedule-repeatable-jobs.mdx @@ -7,7 +7,7 @@ sidebar: import { Tabs, TabItem } from "@astrojs/starlight/components"; -Repeatable specs upsert a *recipe* — `(name, payload, pattern)` — and the engine fires fresh jobs from it on each window. The spec lives in `{chasqui:}:repeat` (sorted set keyed by next fire time) plus `{chasqui:}:repeat:specs` (hash). +Repeatable specs upsert a *recipe* — `(name, payload, pattern)` — and the engine fires fresh jobs from it on each window. The spec lives in `{chasqui:}:repeat` (sorted set keyed by next fire time) plus a per-spec `{chasqui:}:repeat:spec:` hash holding the encoded spec body. ## Cron pattern