ff_backend_sqlite/queries/claim_grant.rs
1//! SQLite dialect-forked queries for RFC-024 `ff_claim_grant` table.
2//!
3//! Landed by PR-E of the RFC-024 series (SQLite lease-reclaim wiring).
4//! The SQL strings are module-level `const`s so `reclaim.rs` call
5//! sites reference them by name and cross-dialect review lines them
6//! up against the PG reference.
7//!
8//! # Transaction contract
9//!
10//! All callers wrap these statements in a `BEGIN IMMEDIATE` txn per
11//! RFC-023 §4.3 — SQLite's RESERVED lock covers the full read-modify-
12//! write window, so no explicit `FOR UPDATE` equivalent is needed.
13
14/// Read the execution's ownership + phase fields plus the current
15/// reclaim counter. Used by `issue_reclaim_grant_impl` to validate
16/// that the target execution is in a reclaimable state
17/// (`lifecycle_phase = 'active'` AND
18/// `ownership_state IN ('lease_expired_reclaimable', 'lease_revoked')`).
19pub(crate) const SELECT_EXEC_CORE_FOR_RECLAIM_SQL: &str = r#"
20 SELECT lifecycle_phase,
21 ownership_state,
22 eligibility_state,
23 attempt_state,
24 attempt_index,
25 lane_id,
26 lease_reclaim_count
27 FROM ff_exec_core
28 WHERE partition_key = ?1 AND execution_id = ?2
29"#;
30
31/// Insert a reclaim-kind grant row.
32pub(crate) const INSERT_RECLAIM_GRANT_SQL: &str = r#"
33 INSERT INTO ff_claim_grant (
34 partition_key,
35 grant_id,
36 execution_id,
37 kind,
38 worker_id,
39 worker_instance_id,
40 lane_id,
41 capability_hash,
42 worker_capabilities,
43 route_snapshot_json,
44 admission_summary,
45 grant_ttl_ms,
46 issued_at_ms,
47 expires_at_ms
48 ) VALUES (?1, ?2, ?3, 'reclaim', ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)
49"#;
50
51/// Read the reclaim-kind grant row for an execution under a partition.
52pub(crate) const SELECT_RECLAIM_GRANT_BY_EXEC_SQL: &str = r#"
53 SELECT grant_id,
54 worker_id,
55 worker_instance_id,
56 lane_id,
57 expires_at_ms
58 FROM ff_claim_grant
59 WHERE partition_key = ?1 AND execution_id = ?2 AND kind = 'reclaim'
60 ORDER BY issued_at_ms DESC
61 LIMIT 1
62"#;
63
64/// Consume (DELETE) a reclaim grant row.
65pub(crate) const DELETE_RECLAIM_GRANT_SQL: &str = r#"
66 DELETE FROM ff_claim_grant
67 WHERE partition_key = ?1 AND grant_id = ?2
68"#;
69
70/// Reclaim-time re-validation read. Used by
71/// `reclaim_execution_inner` after the grant has been located but
72/// before any state mutation, to defend against:
73///
74/// 1. **Lifecycle/ownership drift between grant issuance and grant
75/// consumption.** The exec may have transitioned to
76/// `terminal`/`cancelled` through another path (e.g. operator
77/// cancel) while the grant was in-flight. Mirrors PG PR-D
78/// `claim_grant.rs::reclaim_execution_once` and Lua
79/// `flowfabric.lua:3049+` gate.
80/// 2. **Caller-supplied stale `current_attempt_index`.** The Rust
81/// API takes this from caller args; a stale value could backward-
82/// pin `attempt_index` or PK-collide with an existing row.
83/// Returning the authoritative value lets the caller derive
84/// `new_attempt_index = stored + 1` server-side.
85/// 3. **Lease-epoch monotonicity.** The prior attempt row's
86/// `lease_epoch` is the floor for the new attempt's epoch
87/// (Lua `next_epoch = current_lease_epoch + 1`). The joined
88/// `ff_attempt.lease_epoch` covers the first-reclaim case where
89/// the `ff_exec_core` lease fields may already be cleared.
90pub(crate) const SELECT_EXEC_CORE_RECLAIM_GATE_SQL: &str = r#"
91 SELECT ec.lease_reclaim_count,
92 ec.lifecycle_phase,
93 ec.ownership_state,
94 ec.attempt_index,
95 COALESCE(a.lease_epoch, 0) AS prior_lease_epoch
96 FROM ff_exec_core ec
97 LEFT JOIN ff_attempt a
98 ON a.partition_key = ec.partition_key
99 AND a.execution_id = ec.execution_id
100 AND a.attempt_index = ec.attempt_index
101 WHERE ec.partition_key = ?1 AND ec.execution_id = ?2
102"#;
103
104/// Bump `lease_reclaim_count` and flip `ff_exec_core` to the
105/// new-attempt active/leased posture. Mirrors `UPDATE_EXEC_CORE_RECLAIM_SQL`
106/// in `queries/lease.rs` but also bumps `attempt_index` (new attempt)
107/// and `lease_reclaim_count` (RFC-024 §3.3 counter).
108pub(crate) const UPDATE_EXEC_CORE_FOR_NEW_RECLAIM_ATTEMPT_SQL: &str = r#"
109 UPDATE ff_exec_core
110 SET lifecycle_phase = 'active',
111 ownership_state = 'leased',
112 eligibility_state = 'not_applicable',
113 attempt_state = 'running_attempt',
114 attempt_index = ?1,
115 lease_reclaim_count = lease_reclaim_count + 1
116 WHERE partition_key = ?2 AND execution_id = ?3
117"#;
118
119/// Transition `ff_exec_core` to `terminal_failed` on reclaim-cap
120/// exceeded. Mirrors the Lua `max_reclaims_exceeded` branch at
121/// `flowfabric.lua:3049-3080`.
122pub(crate) const UPDATE_EXEC_CORE_RECLAIM_CAP_EXCEEDED_SQL: &str = r#"
123 UPDATE ff_exec_core
124 SET lifecycle_phase = 'terminal',
125 ownership_state = 'unowned',
126 eligibility_state = 'not_applicable',
127 attempt_state = 'attempt_terminal',
128 public_state = 'failed',
129 terminal_at_ms = ?1
130 WHERE partition_key = ?2 AND execution_id = ?3
131"#;
132
133/// Mark the prior attempt as `interrupted_reclaimed`. Mirrors the
134/// Valkey Lua at `flowfabric.lua:3112`.
135pub(crate) const UPDATE_PRIOR_ATTEMPT_INTERRUPTED_RECLAIMED_SQL: &str = r#"
136 UPDATE ff_attempt
137 SET outcome = 'interrupted_reclaimed',
138 terminal_at_ms = ?1
139 WHERE partition_key = ?2 AND execution_id = ?3 AND attempt_index = ?4
140"#;
141
142/// Insert a fresh `ff_attempt` row for the reclaimed attempt. The
143/// `lease_epoch` bind is the caller-derived `prior_lease_epoch + 1`
144/// (see `SELECT_EXEC_CORE_RECLAIM_GATE_SQL`), matching Lua
145/// `flowfabric.lua:3106` (`next_epoch = current_lease_epoch + 1`).
146/// Previous PR-E had this hard-coded to `0`; that broke epoch
147/// monotonicity for lease fencing across the distributed system.
148pub(crate) const INSERT_NEW_RECLAIM_ATTEMPT_SQL: &str = r#"
149 INSERT INTO ff_attempt (
150 partition_key,
151 execution_id,
152 attempt_index,
153 worker_id,
154 worker_instance_id,
155 lease_epoch,
156 lease_expires_at_ms,
157 started_at_ms,
158 policy
159 ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)
160"#;
161
162/// Clear lease fields on the prior attempt row when reclaim
163/// cap-exceeded fires. Mirrors Lua `flowfabric.lua:3064-3079`
164/// (clears `current_lease_id`/`current_worker_*` on exec_core +
165/// DEL on lease_current_key). On SQLite the lease-fencing fields
166/// live on the attempt row, so we clear there and leave the prior
167/// outcome = 'interrupted_reclaimed' for parity with the
168/// successful-reclaim branch.
169pub(crate) const CLEAR_PRIOR_ATTEMPT_LEASE_ON_CAP_EXCEEDED_SQL: &str = r#"
170 UPDATE ff_attempt
171 SET outcome = 'interrupted_reclaimed',
172 terminal_at_ms = ?1,
173 worker_id = NULL,
174 worker_instance_id = NULL,
175 lease_expires_at_ms = NULL
176 WHERE partition_key = ?2 AND execution_id = ?3 AND attempt_index = ?4
177"#;