Crate mas_storage
source ·Expand description
Interactions with the storage backend
This crate provides a set of traits that can be implemented to interact with the storage backend. Those traits are called repositories and are grouped by the type of data they manage.
Each of those reposotories can be accessed via the RepositoryAccess
trait. This trait can be wrapped in a BoxRepository
to allow using it
without caring about the underlying storage backend, and without carrying
around the generic type parameter.
This crate also defines a Clock
trait that can be used to abstract the
way the current time is retrieved. It has two implementation:
SystemClock
that uses the system time and MockClock
which is useful
for testing.
§Defining a new repository
To define a new repository, you have to:
- Define a new (async) repository trait, with the methods you need
- Write an implementation of this trait for each storage backend you want
(currently only for [
mas-storage-pg
]) - Make it accessible via the
RepositoryAccess
trait
The repository trait definition should look like this:
#[async_trait]
pub trait FakeDataRepository: Send + Sync {
/// The error type returned by the repository
type Error;
/// Lookup a [`FakeData`] by its ID
///
/// Returns `None` if no [`FakeData`] was found
///
/// # Parameters
///
/// * `id`: The ID of the [`FakeData`] to lookup
///
/// # Errors
///
/// Returns [`Self::Error`] if the underlying repository fails
async fn lookup(&mut self, id: Ulid) -> Result<Option<FakeData>, Self::Error>;
/// Create a new [`FakeData`]
///
/// Returns the newly-created [`FakeData`].
///
/// # Parameters
///
/// * `rng`: The random number generator to use
/// * `clock`: The clock used to generate timestamps
///
/// # Errors
///
/// Returns [`Self::Error`] if the underlying repository fails
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
clock: &dyn Clock,
) -> Result<FakeData, Self::Error>;
}
repository_impl!(FakeDataRepository:
async fn lookup(&mut self, id: Ulid) -> Result<Option<FakeData>, Self::Error>;
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
clock: &dyn Clock,
) -> Result<FakeData, Self::Error>;
);
Four things to note with the implementation:
- It defined an assocated error type, and all functions are faillible, and use that error type
- Lookups return an
Result<Option<T>, Self::Error>
, because ‘not found’ errors are usually cases that are handled differently - Operations that need to record the current type use a
Clock
parameter. Operations that need to generate new IDs also use a random number generator. - All the methods use an
&mut self
. This is ensures only one operation is done at a time on a single repository instance.
Then update the RepositoryAccess
trait to make the new repository
available:
/// Access the various repositories the backend implements.
pub trait RepositoryAccess: Send {
/// The backend-specific error type used by each repository.
type Error: std::error::Error + Send + Sync + 'static;
// ...other repositories...
/// Get a [`FakeDataRepository`]
fn fake_data<'c>(&'c mut self) -> Box<dyn FakeDataRepository<Error = Self::Error> + 'c>;
}
Re-exports§
pub use self::clock::Clock;
pub use self::clock::SystemClock;
pub use self::pagination::Page;
pub use self::pagination::Pagination;
Modules§
- Repositories to interact with all kinds of sessions
- A
Clock
is a way to get the current date and time. - Repositories to interact with entities of the compatibility layer
- Repository to schedule persistent jobs.
- Repositories to interact with entities related to the OAuth 2.0 protocol
- Utilities to manage paginated queries.
- Repositories to interact with entities related to the upstream OAuth 2.0 providers
- Repositories to interact with entities related to user accounts
Macros§
Structs§
- A wrapper which is used to map the error type of a repository to another
- An opaque, type-erased error
Traits§
- A
Repository
helps interacting with the underlying storage backend. - Access the various repositories the backend implements.
- A
RepositoryTransaction
can be saved or cancelled, after a series of operations.
Type Aliases§
- A boxed
Clock
- A type-erased
Repository
- A boxed random number generator