use crate::aggregate::{Aggregate, AggregateRepository};
use crate::command_ledger::{
CausalGetStream, CausalRepositoryIdentity, CausalTransactionalCommit, CommandLedgerStore,
};
use crate::outbox::OutboxPublisherConfig;
use crate::projection_protocol::ProjectionProtocolStore;
use crate::repository::{ReadModelWritePlanStore, RelationalReadModelQueryStore, Repository};
pub trait HasRepo {
type Repo;
fn repo(&self) -> &Self::Repo;
}
#[doc(hidden)]
#[allow(private_bounds)]
pub trait CausalRepositoryBackend:
CausalGetStream
+ CommandLedgerStore
+ CausalTransactionalCommit
+ CausalRepositoryIdentity
+ ProjectionProtocolStore
+ Send
+ Sync
+ 'static
{
}
impl<T> CausalRepositoryBackend for T where
T: CausalGetStream
+ CommandLedgerStore
+ CausalTransactionalCommit
+ CausalRepositoryIdentity
+ ProjectionProtocolStore
+ Send
+ Sync
+ 'static
{
}
#[doc(hidden)]
pub trait CausalRouteDependencies {
type Backend: CausalRepositoryBackend;
type Aggregate: Aggregate;
#[doc(hidden)]
fn __causal_aggregate_repository(&self)
-> &AggregateRepository<Self::Backend, Self::Aggregate>;
}
pub trait HasReadModelStore {
type ReadModelStore;
fn read_model_store(&self) -> &Self::ReadModelStore;
}
#[doc(hidden)]
#[allow(private_bounds)]
pub trait CausalProjectionStore: ProjectionProtocolStore + Clone + Send + Sync + 'static {}
impl<T> CausalProjectionStore for T where T: ProjectionProtocolStore + Clone + Send + Sync + 'static {}
#[doc(hidden)]
pub trait CausalProjectionRouteDependencies {
type Store: CausalProjectionStore;
#[doc(hidden)]
fn __causal_projection_store(&self) -> &Self::Store;
}
impl<D> CausalProjectionRouteDependencies for D
where
D: HasReadModelStore,
D::ReadModelStore: CausalProjectionStore,
{
type Store = D::ReadModelStore;
fn __causal_projection_store(&self) -> &Self::Store {
self.read_model_store()
}
}
pub trait ConfigurableOutboxPublisher {
fn configure_outbox_publisher(&mut self, config: OutboxPublisherConfig);
}
impl<R, A> ConfigurableOutboxPublisher for AggregateRepository<R, A> {
fn configure_outbox_publisher(&mut self, config: OutboxPublisherConfig) {
self.set_outbox_publisher(config);
}
}
impl<R: ConfigurableOutboxPublisher, S> ConfigurableOutboxPublisher
for RepoReadModelDependencies<R, S>
{
fn configure_outbox_publisher(&mut self, config: OutboxPublisherConfig) {
self.repo.configure_outbox_publisher(config);
}
}
impl<R: HasOutboxStore, S> HasOutboxStore for RepoReadModelDependencies<R, S> {
type OutboxStore = R::OutboxStore;
fn outbox_store(&self) -> Self::OutboxStore {
self.repo().outbox_store()
}
}
pub trait HasOutboxStore {
type OutboxStore: crate::outbox_worker::OutboxStore;
fn outbox_store(&self) -> Self::OutboxStore;
}
impl HasOutboxStore for crate::InMemoryRepository {
type OutboxStore = crate::InMemoryOutboxStore;
fn outbox_store(&self) -> Self::OutboxStore {
crate::InMemoryRepository::outbox_store(self)
}
}
#[cfg(feature = "sqlite")]
impl HasOutboxStore for crate::SqliteRepository {
type OutboxStore = crate::SqliteOutboxStore;
fn outbox_store(&self) -> Self::OutboxStore {
crate::SqliteRepository::outbox_store(self)
}
}
#[cfg(feature = "postgres")]
impl HasOutboxStore for crate::PostgresRepository {
type OutboxStore = crate::PostgresOutboxStore;
fn outbox_store(&self) -> Self::OutboxStore {
crate::PostgresRepository::outbox_store(self)
}
}
impl<R, A> HasOutboxStore for AggregateRepository<R, A>
where
R: HasOutboxStore,
{
type OutboxStore = R::OutboxStore;
fn outbox_store(&self) -> Self::OutboxStore {
self.repo().outbox_store()
}
}
impl<R, L> HasOutboxStore for crate::QueuedRepository<R, L>
where
R: HasOutboxStore,
{
type OutboxStore = R::OutboxStore;
fn outbox_store(&self) -> Self::OutboxStore {
self.inner().outbox_store()
}
}
impl<R> HasRepo for R
where
R: Repository,
{
type Repo = R;
fn repo(&self) -> &Self::Repo {
self
}
}
impl<R, A> HasRepo for AggregateRepository<R, A> {
type Repo = Self;
fn repo(&self) -> &Self::Repo {
self
}
}
impl<R, A> CausalRouteDependencies for AggregateRepository<R, A>
where
R: CausalRepositoryBackend,
A: Aggregate,
{
type Backend = R;
type Aggregate = A;
fn __causal_aggregate_repository(&self) -> &AggregateRepository<R, A> {
self
}
}
impl<S> HasReadModelStore for S
where
S: ReadModelWritePlanStore + RelationalReadModelQueryStore,
{
type ReadModelStore = S;
fn read_model_store(&self) -> &Self::ReadModelStore {
self
}
}
#[derive(Clone)]
pub struct RepoDependencies<R> {
repo: R,
}
impl<R> RepoDependencies<R> {
pub fn new(repo: R) -> Self {
Self { repo }
}
}
impl<R> HasRepo for RepoDependencies<R> {
type Repo = R;
fn repo(&self) -> &Self::Repo {
&self.repo
}
}
impl<R, A> CausalRouteDependencies for RepoDependencies<AggregateRepository<R, A>>
where
R: CausalRepositoryBackend,
A: Aggregate,
{
type Backend = R;
type Aggregate = A;
fn __causal_aggregate_repository(&self) -> &AggregateRepository<R, A> {
&self.repo
}
}
#[derive(Clone)]
pub struct ReadModelStoreDependencies<S> {
read_model_store: S,
}
impl<S> ReadModelStoreDependencies<S> {
pub fn new(read_model_store: S) -> Self {
Self { read_model_store }
}
}
impl<S> HasReadModelStore for ReadModelStoreDependencies<S> {
type ReadModelStore = S;
fn read_model_store(&self) -> &Self::ReadModelStore {
&self.read_model_store
}
}
#[derive(Clone)]
pub struct RepoReadModelDependencies<R, S> {
repo: R,
read_model_store: S,
}
impl<R, S> RepoReadModelDependencies<R, S> {
pub fn new(repo: R, read_model_store: S) -> Self {
Self {
repo,
read_model_store,
}
}
}
impl<R, S> HasRepo for RepoReadModelDependencies<R, S> {
type Repo = R;
fn repo(&self) -> &Self::Repo {
&self.repo
}
}
impl<R, A, S> CausalRouteDependencies for RepoReadModelDependencies<AggregateRepository<R, A>, S>
where
R: CausalRepositoryBackend,
A: Aggregate,
{
type Backend = R;
type Aggregate = A;
fn __causal_aggregate_repository(&self) -> &AggregateRepository<R, A> {
&self.repo
}
}
impl<R, S> HasReadModelStore for RepoReadModelDependencies<R, S> {
type ReadModelStore = S;
fn read_model_store(&self) -> &Self::ReadModelStore {
&self.read_model_store
}
}
#[cfg(test)]
mod tests {
use super::*;
fn assert_has_outbox_store<T: HasOutboxStore>() {}
#[test]
fn has_outbox_store_resolves_through_repo_wrappers() {
assert_has_outbox_store::<crate::InMemoryRepository>();
assert_has_outbox_store::<AggregateRepository<crate::InMemoryRepository, ()>>();
assert_has_outbox_store::<
AggregateRepository<crate::QueuedRepository<crate::InMemoryRepository>, ()>,
>();
}
}