Skip to main content

LockingPlugin

Trait LockingPlugin 

Source
pub trait LockingPlugin: Send + Sync {
    // Required methods
    fn name(&self) -> &str;
    fn try_lock(
        &self,
        key: &str,
        ttl_ms: u64,
    ) -> Result<Option<LockHandle>, String>;
    fn renew(&self, handle: &LockHandle) -> Result<(), String>;
    fn release(&self, handle: LockHandle) -> Result<(), String>;

    // Provided method
    fn cleanup(&self) -> Result<(), String> { ... }
}
Expand description

A plugin that provides distributed mutual exclusion.

Compile-time and WASM execution. All methods use JSON-friendly POD types so the trait is ABI-compatible with WASM guest plugins (matches the convention used by the other capability traits in this crate). Backends that need a real async client run their own runtime inside the call.

Concurrency: implementations MUST be safe to call from multiple threads simultaneously. The host may contend on the same key from different request-handling threads.

Required Methods§

Source

fn name(&self) -> &str

Unique plugin name (e.g., "memory", "redis", "pg"). Used by the dev dashboard, metrics labels, and cap_conformance.

Source

fn try_lock(&self, key: &str, ttl_ms: u64) -> Result<Option<LockHandle>, String>

Attempt to acquire the lock identified by key for at most ttl_ms milliseconds.

§Return shape
  • Ok(Some(handle)) — the lock was acquired. The caller owns it for ttl_ms and may renew or release.
  • Ok(None)contention. Another owner holds the lock. The caller typically backs off and retries later, or simply skips this run (the Scheduled capability skips).
  • Err(message) — backend failure (network, protocol, configuration). The caller cannot meaningfully retry without operator intervention.

The Ok(None) vs Err(..) distinction is the reason this trait does not use a typed LockError enum — it is the only branch that matters to 99% of callers, and encoding it in the outer Result is cleaner than a LockError::Held variant they would have to match every single call site.

Source

fn renew(&self, handle: &LockHandle) -> Result<(), String>

Extend the lifetime of an existing lock.

On success the lock’s TTL is reset to handle.ttl_ms. On failure — either because the lock has already expired or the backend is broken — returns Err(message). Callers treat the failure uniformly: “you no longer own this lock; stop holding it.” The default retry policy is to abandon the work and try try_lock again from scratch on the next opportunity.

Source

fn release(&self, handle: LockHandle) -> Result<(), String>

Release the lock.

Implementations MUST verify that the lock is still held under the caller’s handle.lock_id before releasing (check-and-set), so a stale call after the TTL expired cannot clobber a newer holder. Releasing a lock the caller does not own is a silent no-op, not an error.

Provided Methods§

Source

fn cleanup(&self) -> Result<(), String>

Called before the plugin is unloaded. Release backend resources (Redis connection, Postgres pool). Default: no-op.

Implementors§