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 outbox helper handle (ADR-019 §1; the outbox section of
//! core-contract.md).
//!
//! A helper over queues, not a separate mechanism: the tx-side
//! transactional enqueue is `TxHandle::outbox_enqueue_tx` (ADR-014);
//! this handle carries the auto-commit enqueue and the delivery
//! worker entry point.

use serde_json::Value;

use crate::Result;
use crate::future::BoxedFuture;
use crate::job_handle::JobHandle;
use crate::opts::EnqueueOpts;

/// The delivery callable [`Outbox::run_once`] takes.
///
/// A consumer-supplied async callable taking [`Box<dyn JobHandle>`],
/// returning the boxed future of `Result<()>` (ADR-019 §5). Object
/// safety encoded as a named one-method trait object. Outcome
/// posture: `Ok` ⇒ the engine acks the claim; `Err(e)` ⇒ the engine
/// retries with the queue's curve (`retry(err, None)`).
///
/// No engine-issued heartbeat inside delivery — the boxed
/// [`JobHandle`]'s own `heartbeat` remains available to the closure;
/// renewal inside the deadline is the consumer's obligation.
pub trait Delivery: Send {
    /// Process the claimed job's work. Returns the boxed future of
    /// `Result<()>`.
    fn deliver<'a>(&'a mut self, job: Box<dyn JobHandle>) -> BoxedFuture<'a, Result<()>>;
}

/// The outbox-scoped handle for one outbox name.
///
/// The backing queue is derived engine-side under the reserved prefix
/// (`__alkstore_outbox:{name}`) — reachable only through this surface
/// and `outbox_enqueue_tx`; enqueue stamps the outbox's derived
/// `QueueOpts` set (60/5/5, ADR-010 §3).
pub trait Outbox: Send + Sync {
    /// The outbox name the handle was constructed with.
    fn name(&self) -> &str;

    /// Enqueue into the derived backing queue (auto-commit; the
    /// transactional path is `TxHandle::outbox_enqueue_tx`).
    fn enqueue<'a>(&'a self, payload: Value, opts: EnqueueOpts) -> BoxedFuture<'a, Result<i64>>;

    /// Pull op: claim one job, run `delivery`, ack on `Ok`,
    /// `retry(err, None)` (the queue curve) on `Err`. The consumer
    /// calls it in its own loop. `true` = claimed and processed;
    /// `false` = no work (a value, not an error). `worker_id` is
    /// consumer-local, non-empty only (`InvalidName`; ADR-019 §2).
    fn run_once<'a>(
        &'a mut self,
        worker_id: &str,
        delivery: &'a mut dyn Delivery,
    ) -> BoxedFuture<'a, Result<bool>>;
}