-- Per-lease generation token to close the lease-identity race that
-- 0.87.20 only partially addressed.
--
-- Before this, `ack_done` / `ack_failed` / `renew` matched on
-- `(id, state='running')`. A worker whose lease was released mid-
-- flight (force-analyze, reclaim) could still ack-done the row once a
-- successor leased it back to `state='running'` — clobbering the
-- successor's lease with the original's stale result. The bug class is
-- ack-from-a-dead-lease.
--
-- Adding `lease_generation` makes lease identity = `(id, generation)`:
--   * `lease`/`lease_kinds` bump generation by 1 at lease time
--   * `release` (force-analyze, graceful shutdown) bumps generation too
--   * `reclaim_orphaned` bumps generation for every reclaimed row
--   * `ack_done` / `ack_failed` / `renew` match on `(id, generation,
--     state='running')`, so a stale ack from a prior generation finds
--     no row and falls back to the existing warn-and-skip branch.
--
-- BIGINT so the counter can't realistically overflow even for a row
-- that's been crash-leased thousands of times.

ALTER TABLE crawler_jobs
    ADD COLUMN lease_generation BIGINT NOT NULL DEFAULT 0;
