Skip to main content

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}