alkstore 0.1.0

The alkstore contract crate: one reactive store trait surface — notify, streams, durable queues, TTL locks, outbox, scheduler — implemented by the alkstore-sqlite/-postgres/-mem engine crates; no driver dependencies
Documentation
//! The boxed job handle a claim returns (ADR-019 §3; ADR-010 §2).
//!
//! One-shot/repeatable split, deliberate — do not "fix" it at
//! implementation: `ack`/`retry`/`fail` consume the handle
//! (`self: Box<Self>` — each is a terminal transition of the claim);
//! `heartbeat` takes `&self` and is repeatable (renewal is inherently
//! repeated within one claim).

use crate::Result;
use crate::future::BoxedFuture;
use crate::job::Job;

/// The claim handle: the row value plus its ops.
///
/// # The uniform validity predicate
///
/// Every op succeeds only while the row is `processing` **and** the
/// caller's claim deadline is unexpired (ADR-010 §2) — deadline lapse
/// refuses all ops (heartbeats, acks included) and a reclaim does
/// too. `false`, not an error: the dual-execution window's worker may
/// still complete its work, but its op will not land — at-least-once,
/// as documented.
pub trait JobHandle: Send {
    /// The job row, as a value (the [`Job`] the claim returned).
    fn job(&self) -> &Job;

    /// Ack: deletes the row (completed work leaves no row, ADR-010
    /// §1). `true` = the op landed under the validity predicate.
    fn ack(self: Box<Self>) -> BoxedFuture<'static, Result<bool>>;

    /// Retry: return the row to `pending` for redelivery. `None`
    /// delay = the queue's equal-jitter exponential curve computed
    /// engine-side; `Some(d)` overrides it (ADR-010 §3). Exhausting
    /// the attempt budget dead-letters instead. `false` = refused
    /// under the validity predicate — the row keeps its pre-call
    /// state (at-least-once redelivery governs).
    fn retry(
        self: Box<Self>,
        err: Option<String>,
        delay: Option<i64>,
    ) -> BoxedFuture<'static, Result<bool>>;

    /// Fail: immediate dead-letter — the "stop retrying this"
    /// operator (ADR-010 §3). `None` err records the engine's
    /// documented-default string `"failed"` (row content, not a
    /// matched error variant). `false` = refused under the validity
    /// predicate.
    fn fail(self: Box<Self>, err: Option<String>) -> BoxedFuture<'static, Result<bool>>;

    /// Heartbeat: renewal — an **absolute reset** of the claim
    /// deadline from now (`extend` is the new full deadline in
    /// seconds, *not* additive to elapsed time; ADR-010 §2). Repeatable
    /// (`&self`); late heartbeat refused (`false`) — it can never
    /// steal the job back from a reclaimer; a reclaim consumes an
    /// attempt.
    fn heartbeat<'a>(&'a self, extend: i64) -> BoxedFuture<'a, Result<bool>>;
}