Skip to content

Lock

Named locks live in serenade-lock (#185, #190, #191).

Symfony Lock analogue for critical sections (cron, inventory, mail blast). Apps own lock key naming.

Type Role
LockStore Persist ownership (save / delete / exists / put_off_expiration)
LockFactory / Lock Create handles; acquire / release / refresh / is_acquired
LockKey Resource name + opaque owner token
LockError Invalid key, conflict, not held, generation, store failures
Store Role
InMemoryLockStore Process-local (default DI)
FilesystemLockStore Disk files under {directory}/{prefix}/{hex}.lock
RedisLockStore Redis via redis-rs + r2d2 (Cargo feature redis)

FrameworkExtension adds [RegisterDefaultLockPass], which registers service id lock.store (DEFAULT_LOCK_STORE_SERVICE) tagged lock.store with an InMemoryLockStore when missing. Resolve LockStoreService and call factory().

Apps replace the default by registering filesystem or Redis stores under the same id before compile.

use std::sync::Arc;
use std::time::Duration;
use serenade_lock::{InMemoryLockStore, LockFactory, LockStore};
let store = Arc::new(InMemoryLockStore::new());
let factory = LockFactory::new(store);
let lock = factory.create_lock("cron:mail-blast", Some(Duration::from_secs(30)), true)?;
if lock.acquire()? {
// critical section
lock.release()?;
}

Filesystem:

use serenade_lock::{FilesystemLockStore, FilesystemLockStoreConfig};
let store = FilesystemLockStore::open(
FilesystemLockStoreConfig::new("var/lock").with_prefix("serenade"),
)?;

Redis (feature redis):

use serenade_lock::{RedisLockStore, RedisLockStoreConfig};
let store = RedisLockStore::connect(
RedisLockStoreConfig::new("redis://127.0.0.1:6379/0").with_prefix("serenade:lock:"),
)?;