mod.rs
Overview
This file defines the ActionLockStorage struct, which provides a persistent key-value storage interface specialized for storing and retrieving serialized data blobs. It uses an underlying KeyValueStore trait object to abstract the actual storage mechanism, enabling flexibility in storage backend implementations. The primary use case of this module is to handle cross-action locks or similar data structures serialized as binary blobs, stored under a namespace and set prefix.
Structs and Implementations
ActionLockStorage
A storage wrapper around a generic key-value store focused on managing serialized blobs under a specified Aerospike namespace and set prefix.
Fields
store: Arc<dyn KeyValueStore>
An Arc-wrapped trait object representing the underlying key-value store implementation. This allows sharing the same store instance safely across threads.set_prefix: String
A string prefix used as the Aerospike set name to organize stored records under different logical groups.
Methods
new(store: impl KeyValueStore + 'static, set_prefix: &str) -> Self
Creates a new ActionLockStorage instance wrapping the given key-value store and using the specified set prefix.
Parameters:
store: An instance implementing theKeyValueStoretrait.set_prefix: A string slice specifying the set name prefix.
Returns:
A new
ActionLockStorageinstance.
Example:
let mem_store = MemStore::new();
let storage = ActionLockStorage::new(mem_store, "my_set");
mem() -> Self
A convenience constructor that creates an ActionLockStorage instance backed by an in-memory store (MemStore) with the set prefix "mem".
Returns:
A new
ActionLockStorageusing in-memory storage.
Example:
let storage = ActionLockStorage::mem();
message_key(&self, hash: &str) -> Key
Generates an Aerospike key for a given string hash, using the configured namespace and set prefix.
Parameters:
hash: A string slice used as the primary key value.
Returns:
An Aerospike
Keyconstructed with the namespace, set prefix, and hash.
Usage:
This method is internal and used to standardize key generation for all stored records.
read_blob<T: for<'de> Deserialize<'de>>(&self, path: &str) -> anyhow::Result<Option<T>>
Reads and deserializes a blob value from the store given a key path.
Parameters:
path: The key (hash) string identifying the record.
Returns:
Ok(Some(T))if the record exists and deserialization succeeds.Ok(None)if no record is found.Errif there is a failure in reading or deserializing the record.
Implementation Details:
Constructs the Aerospike key via
message_key.Fetches the record bins for
BIN_BLOB.Extracts the blob value and deserializes it using
bincode.Returns an error if the blob bin is missing or deserialization fails.
Example:
let maybe_lock: Option<MyLockStruct> = storage.read_blob("lock_key")?;
if let Some(lock) = maybe_lock {
// Use the lock data
}
write_blob<T: Serialize>(&self, path: &str, data: T, until_success: bool) -> anyhow::Result<()>
Serializes and writes a data blob to the key-value store.
Parameters:
path: The key (hash) string identifying where to store the data.data: The serializable data to be stored.until_success: A boolean indicating whether the write operation should retry until it succeeds.
Returns:
Ok(())if the write operation is successful.Errif serialization or writing fails.
Implementation Details:
Serializes the
datausingbincode.Constructs the Aerospike key via
message_key.Writes the serialized blob into the bin
BIN_BLOBof the record.Uses the
until_successflag to control write retry behavior.
Example:
storage.write_blob("lock_key", my_lock_data, true)?;
Important Implementation Details
The module leverages the
KeyValueStoretrait abstraction to remain backend-agnostic. This design allows switching storage implementations transparently.Serialization and deserialization are performed using the
bincodecrate for efficient binary encoding.Aerospike's namespace and set concepts are used to organize data. The namespace is fixed to
NAMESPACE(imported from elsewhere), while the set name is customizable viaset_prefix.The binary blob is stored under the bin name
BIN_BLOB, consistent with the storage conventions established in the system.Error handling utilizes the
anyhowcrate for flexible error propagation and contextual messages.
Interaction with Other System Components
Relies on the
KeyValueStoretrait and its implementations such asMemStorefor actual data storage.Uses Aerospike client types (
Key,Value, and macros likeas_key!andas_bin!) from the Aerospike Rust client crate to interact with Aerospike database objects.Imports constants like
NAMESPACE,BIN_BLOB, andAEROSPIKE_OBJECT_TYPE_CROSS_ACTION_LOCKto ensure consistent namespace, bin names, and metrics tagging across the application.Serialization and deserialization dependencies (
serde::Serialize,serde::Deserialize) enable storing arbitrary typed data blobs.This module is likely used by higher-level components requiring durable lock storage or cross-action state persistence, integrating into the system's locking and concurrency control mechanisms.
File Structure and Workflow Diagram
flowchart TD
A[ActionLockStorage] --> B[store: KeyValueStore]
A --> C[set_prefix: String]
A --> D["new()"]
A --> E["mem()"]
A --> F["message_key()"]
A --> G["read_blob()"]
A --> H["write_blob()"]
G --> I[Deserialize blob via bincode]
H --> J[Serialize data via bincode]
D --> B
E --> B
This diagram illustrates the main components and methods of the ActionLockStorage struct, highlighting how it composes a key-value store and exposes methods to read and write serialized blobs keyed by a message key constructed from the set prefix. Serialization and deserialization are key workflows encapsulated in write_blob and read_blob methods respectively.