substrate_core/claim_port.rs
1//! ClaimPort — atomic work-queue with fuzzy near-duplicate detection.
2//!
3//! Core defines the contract; `store-sqlite` implements BEGIN IMMEDIATE CAS
4//! claiming and strsim-backed deduplication.
5
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9/// Lifecycle state of a queued work item.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11pub enum WorkItemState {
12 /// Waiting to be claimed.
13 Pending,
14 /// Claimed by a worker.
15 Claimed,
16 /// Finished.
17 Completed,
18}
19
20/// A unit of claimable work.
21#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
22pub struct WorkItem {
23 /// Stable identity.
24 pub id: Uuid,
25 /// Named queue (tenant/lane).
26 pub queue: String,
27 /// Payload text used for fuzzy dedup.
28 pub body: String,
29 /// Current state.
30 pub state: WorkItemState,
31 /// Worker that holds the claim, if any.
32 pub claimed_by: Option<String>,
33}
34
35/// Atomic work-queue port.
36///
37/// Implementations MUST guarantee that at most one worker wins a concurrent
38/// claim race for a given item (`BEGIN IMMEDIATE` + conditional `UPDATE`).
39pub trait ClaimPort: Send + Sync {
40 /// Error type returned by store operations.
41 type Error: std::error::Error + Send + Sync + 'static;
42
43 /// Enqueue a new pending item; returns its id.
44 ///
45 /// Returns an error if `body` is a near-duplicate of an existing pending
46 /// or claimed item in the same queue.
47 fn enqueue(&self, queue: &str, body: &str) -> Result<Uuid, Self::Error>;
48
49 /// Atomically claim the oldest pending item in `queue` for `worker_id`.
50 ///
51 /// Returns `None` when the queue is empty.
52 fn claim_next(&self, queue: &str, worker_id: &str) -> Result<Option<WorkItem>, Self::Error>;
53
54 /// Returns `true` if `body` is a near-duplicate of an existing item.
55 fn is_near_duplicate(&self, queue: &str, body: &str) -> Result<bool, Self::Error>;
56}