read.rs
Overview
This file defines abstractions and error handling for reading data from durable storage in a generic and type-safe manner. It provides an enumeration for load errors (LoadErr) and a trait (DurableStorageRead) that specifies an interface for reading messages identified by keys from a persistent store. The trait supports operations to load an individual message, retrieve the next message key in sequence, and obtain a batch of messages starting from a given key.
This design facilitates implementing different storage backends while maintaining a consistent API for reading stored messages. The generic parameters allow flexibility in the types used for message keys and messages themselves.
Enumerations
LoadErr
#[derive(Clone, Debug)]
pub enum LoadErr {
NoState,
DeserializationError,
}
Description
LoadErr defines common error cases encountered when attempting to load data from durable storage:
NoState: Indicates that there is no stored state or the requested data does not exist.DeserializationError: Indicates a failure to deserialize stored data into the expected message format.
Usage
This enum is used as a standard error representation for loading operations, allowing implementations to map their specific errors to these generic categories.
Traits
DurableStorageRead<MessageKey, Message>
pub trait DurableStorageRead<MessageKey, Message> {
type LoadError: Into<LoadErr> + Clone;
fn load_message(&self, key: &MessageKey) -> Result<Message, Self::LoadError>;
fn next(&self, key: &MessageKey) -> Result<Option<MessageKey>, Self::LoadError>;
fn remaining_messages(
&self,
starting_key: &MessageKey,
limit: usize,
) -> Result<Vec<Message>, Self::LoadError>;
}
Description
This trait defines a generic interface for reading messages from durable storage:
Type Parameters:
MessageKey: The type used to identify individual messages in storage.Message: The type of the stored messages.
Associated Types:
LoadError: The error type for load operations. It must be convertible intoLoadErrand cloneable.
Methods
load_message
fn load_message(&self, key: &MessageKey) -> Result<Message, Self::LoadError>;
Purpose: Retrieves the message associated with the given key.
Parameters:
key: Reference to the key identifying the message.
Returns:
Ok(Message): The message if found and successfully loaded.Err(Self::LoadError): If the message is not found or cannot be loaded.
Example Usage:
let message = storage.load_message(&some_key)?;
next
fn next(&self, key: &MessageKey) -> Result<Option<MessageKey>, Self::LoadError>;
Purpose: Retrieves the key of the message that follows the given key.
Parameters:
key: Reference to the current message key.
Returns:
Ok(Some(MessageKey)): The next message key in sequence.Ok(None): If there is no next message.Err(Self::LoadError): If an error occurs during the lookup.
Example Usage:
if let Some(next_key) = storage.next(¤t_key)? {
// process next_key
}
remaining_messages
fn remaining_messages(
&self,
starting_key: &MessageKey,
limit: usize,
) -> Result<Vec<Message>, Self::LoadError>;
Purpose: Retrieves a batch of messages starting from
starting_key, up to a maximum oflimitmessages.Parameters:
starting_key: Reference to the key at which to start loading messages.limit: Maximum number of messages to retrieve.
Returns:
Ok(Vec<Message>): Vector of loaded messages, possibly fewer thanlimitif storage is exhausted.Err(Self::LoadError): If an error occurs during loading.
Example Usage:
let batch = storage.remaining_messages(&start_key, 10)?;
Implementation Details
The trait is designed to be generic over both message keys and messages, allowing reuse across different data types and storage implementations.
The associated
LoadErrortype allows implementors to use their internal error types and convert them into the providedLoadErrenum for standardization.The
nextmethod supports sequential iteration over stored messages by providing the key of the subsequent message.The
remaining_messagesmethod optimizes bulk retrieval of messages, which is useful for batch processing or pagination scenarios.No concrete implementations are provided in this file; it serves purely as an interface definition and error type.
Interaction with Other Parts of the System
This trait is intended to be implemented by storage modules that persist messages and expose read access.
Consumers of this trait can be processing components that require reliable access to persisted messages by key.
The error enum
LoadErrcan be used system-wide to unify error handling in components that read from durable storage.The generic design allows this interface to be used with a variety of storage backends, such as databases, file systems, or in-memory caches.
The interface supports sequential access patterns, enabling components to iterate over stored messages without exposing internal storage details.
Mermaid Diagram
classDiagram
class LoadErr {
<<enum>>
+NoState
+DeserializationError
}
class DurableStorageRead~MessageKey, Message~ {
<<trait>>
+LoadError: Into<LoadErr> + Clone
+load_message(key: &MessageKey) Result<Message, LoadError>
+next(key: &MessageKey) Result<Option<MessageKey>, LoadError>
+remaining_messages(starting_key: &MessageKey, limit: usize) Result<Vec<Message>, LoadError>
}