Skip to content

Commit

Permalink
Merge pull request #20 from fraktalio/feature/async_fn_in_traits
Browse files Browse the repository at this point in the history
`async fn` in Traits - a new `stable` feature of Rust 1.75
  • Loading branch information
idugalic authored Dec 29, 2023
2 parents 1d7512e + 0a5dd06 commit c06d15c
Show file tree
Hide file tree
Showing 13 changed files with 58 additions and 55 deletions.
12 changes: 11 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@ env:
jobs:
build:

runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macOS-latest ]
rust: [ stable, nightly ]

steps:
- uses: hecrj/setup-rust-action@v2
with:
rust-version: ${{ matrix.rust }}

- uses: actions/checkout@v4

- name: Build
run: cargo build --verbose

- name: Run tests
run: cargo test --verbose
11 changes: 10 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,19 @@ env:
jobs:
build:

runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macOS-latest ]
rust: [ stable, nightly ]

steps:
- uses: hecrj/setup-rust-action@v2
with:
rust-version: ${{ matrix.rust }}

- uses: actions/checkout@v4

- name: Publish
run: cargo publish --token ${CRATES_TOKEN}
env:
Expand Down
14 changes: 1 addition & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
[package]
name = "fmodel-rust"
version = "0.6.1"
version = "0.7.0"
edition = "2021"
description = "Accelerate development of compositional, safe, and ergonomic applications/information systems by effectively implementing Event Sourcing and CQRS patterns in Rust."
license = "Apache-2.0"

[dependencies]
async-trait = "0.1.75"
serde = {version = "1.0.193", features = ["derive"]}


[dev-dependencies]
derive_more = "0.99.17"
tokio = { version = "1.35.1", features = ["rt", "rt-multi-thread", "macros"] }

36 changes: 24 additions & 12 deletions src/aggregate.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::future::Future;
use std::marker::PhantomData;

use async_trait::async_trait;

use crate::decider::{Decider, EventComputation, StateComputation};
use crate::saga::{ActionComputation, Saga};

Expand All @@ -13,16 +12,22 @@ use crate::saga::{ActionComputation, Saga};
/// - `E` - Event
/// - `Version` - Version/Offset/Sequence number
/// - `Error` - Error
#[async_trait]
pub trait EventRepository<C, E, Version, Error> {
/// Fetches current events, based on the command.
async fn fetch_events(&self, command: &C) -> Result<Vec<(E, Version)>, Error>;
/// Desugared `async fn fetch_events(&self, command: &C) -> Result<Vec<(E, Version)>, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`.
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
fn fetch_events(
&self,
command: &C,
) -> impl Future<Output = Result<Vec<(E, Version)>, Error>> + Send;
/// Saves events.
async fn save(
/// Desugared `async fn save(&self, events: &[E], latest_version: &Option<Version>) -> Result<Vec<(E, Version)>, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
fn save(
&self,
events: &[E],
latest_version: &Option<Version>,
) -> Result<Vec<(E, Version)>, Error>;
) -> impl Future<Output = Result<Vec<(E, Version)>, Error>> + Send;
}

/// Event Sourced Aggregate.
Expand Down Expand Up @@ -61,7 +66,6 @@ where
}
}

#[async_trait]
impl<C, S, E, Repository, Decider, Version, Error> EventRepository<C, E, Version, Error>
for EventSourcedAggregate<C, S, E, Repository, Decider, Version, Error>
where
Expand Down Expand Up @@ -129,12 +133,22 @@ where
/// - `S` - State
/// - `Version` - Version
/// - `Error` - Error
#[async_trait]
pub trait StateRepository<C, S, Version, Error> {
/// Fetches current state, based on the command.
async fn fetch_state(&self, command: &C) -> Result<Option<(S, Version)>, Error>;
/// Desugared `async fn fetch_state(&self, command: &C) -> Result<Option<(S, Version)>, Error>;` to a normal `fn` that returns `impl Future` and adds bound `Send`
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
fn fetch_state(
&self,
command: &C,
) -> impl Future<Output = Result<Option<(S, Version)>, Error>> + Send;
/// Saves state.
async fn save(&self, state: &S, version: &Option<Version>) -> Result<(S, Version), Error>;
/// Desugared `async fn save(&self, state: &S, version: &Option<Version>) -> Result<(S, Version), Error>;` to a normal `fn` that returns `impl Future` and adds bound `Send`
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
fn save(
&self,
state: &S,
version: &Option<Version>,
) -> impl Future<Output = Result<(S, Version), Error>> + Send;
}

/// State Stored Aggregate.
Expand Down Expand Up @@ -173,7 +187,6 @@ where
}
}

#[async_trait]
impl<C, S, E, Repository, Decider, Version, Error> StateRepository<C, S, Version, Error>
for StateStoredAggregate<C, S, E, Repository, Decider, Version, Error>
where
Expand Down Expand Up @@ -281,7 +294,6 @@ where
}
}

#[async_trait]
impl<'a, C, S, E, Repository, Version, Error> StateRepository<C, S, Version, Error>
for StateStoredOrchestratingAggregate<'a, C, S, E, Repository, Version, Error>
where
Expand Down
13 changes: 7 additions & 6 deletions src/materialized_view.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::future::Future;
use std::marker::PhantomData;

use async_trait::async_trait;

use crate::view::ViewStateComputation;

/// View State Repository trait
Expand All @@ -11,12 +10,15 @@ use crate::view::ViewStateComputation;
/// - `E` - Event
/// - `S` - State
/// - `Error` - Error
#[async_trait]
pub trait ViewStateRepository<E, S, Error> {
/// Fetches current state, based on the event.
async fn fetch_state(&self, event: &E) -> Result<Option<S>, Error>;
/// Desugared `async fn fetch_state(&self, event: &E) -> Result<Option<S>, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`.
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
fn fetch_state(&self, event: &E) -> impl Future<Output = Result<Option<S>, Error>> + Send;
/// Saves the new state.
async fn save(&self, state: &S) -> Result<S, Error>;
/// Desugared `async fn save(&self, state: &S) -> Result<S, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`.
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
fn save(&self, state: &S) -> impl Future<Output = Result<S, Error>> + Send;
}

/// Materialized View.
Expand Down Expand Up @@ -53,7 +55,6 @@ where
}
}

#[async_trait]
impl<S, E, Repository, View, Error> ViewStateRepository<E, S, Error>
for MaterializedView<S, E, Repository, View, Error>
where
Expand Down
9 changes: 4 additions & 5 deletions src/saga_manager.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::future::Future;
use std::marker::PhantomData;

use async_trait::async_trait;

use crate::saga::ActionComputation;

/// Publishes the action/command to some external system.
Expand All @@ -10,10 +9,11 @@ use crate::saga::ActionComputation;
///
/// - `A`. - action
/// - `Error` - error
#[async_trait]
pub trait ActionPublisher<A, Error> {
/// Publishes the action/command to some external system, returning either the actions that are successfully published or error.
async fn publish(&self, action: &[A]) -> Result<Vec<A>, Error>;
/// Desugared `async fn publish(&self, action: &[A]) -> Result<Vec<A>, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`.
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
fn publish(&self, action: &[A]) -> impl Future<Output = Result<Vec<A>, Error>> + Send;
}

/// Saga Manager.
Expand Down Expand Up @@ -48,7 +48,6 @@ where
}
}

#[async_trait]
impl<A, AR, Publisher, Saga, Error> ActionPublisher<A, Error>
for SagaManager<A, AR, Publisher, Saga, Error>
where
Expand Down
3 changes: 0 additions & 3 deletions tests/aggregate_combined_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::error::Error;
use std::sync::{Arc, Mutex};
use std::thread;

use async_trait::async_trait;
use derive_more::Display;

use fmodel_rust::aggregate::{
Expand Down Expand Up @@ -75,7 +74,6 @@ impl Id for (OrderState, ShipmentState) {
}
}
/// Implementation of [EventRepository] for [InMemoryEventRepository] - infrastructure
#[async_trait]
impl
EventRepository<
Sum<OrderCommand, ShipmentCommand>,
Expand Down Expand Up @@ -133,7 +131,6 @@ impl InMemoryStateRepository {
}

// Implementation of [StateRepository] for [InMemoryOrderStateRepository]
#[async_trait]
impl
StateRepository<
Sum<OrderCommand, ShipmentCommand>,
Expand Down
3 changes: 0 additions & 3 deletions tests/aggregate_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::error::Error;
use std::sync::{Arc, Mutex};
use std::thread;

use async_trait::async_trait;
use derive_more::Display;

use fmodel_rust::aggregate::{
Expand Down Expand Up @@ -44,7 +43,6 @@ impl InMemoryOrderEventRepository {
}

/// Implementation of [EventRepository] for [InMemoryOrderEventRepository] - infrastructure
#[async_trait]
impl EventRepository<OrderCommand, OrderEvent, i32, AggregateError>
for InMemoryOrderEventRepository
{
Expand Down Expand Up @@ -97,7 +95,6 @@ impl InMemoryOrderStateRepository {
}

// Implementation of [StateRepository] for [InMemoryOrderStateRepository]
#[async_trait]
impl StateRepository<OrderCommand, OrderState, i32, AggregateError>
for InMemoryOrderStateRepository
{
Expand Down
2 changes: 0 additions & 2 deletions tests/materialized_view_combined_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::error::Error;
use std::sync::{Arc, Mutex};
use std::thread;

use async_trait::async_trait;
use derive_more::Display;

use fmodel_rust::materialized_view::{MaterializedView, ViewStateRepository};
Expand Down Expand Up @@ -125,7 +124,6 @@ impl Id for (OrderViewState, ShipmentViewState) {
}

// Implementation of [ViewStateRepository] for [InMemoryViewOrderStateRepository]
#[async_trait]
impl
ViewStateRepository<
Sum<OrderEvent, ShipmentEvent>,
Expand Down
2 changes: 0 additions & 2 deletions tests/materialized_view_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::error::Error;
use std::sync::{Arc, Mutex};
use std::thread;

use async_trait::async_trait;
use derive_more::Display;

use fmodel_rust::materialized_view::{MaterializedView, ViewStateRepository};
Expand Down Expand Up @@ -72,7 +71,6 @@ impl InMemoryViewOrderStateRepository {
}

// Implementation of [ViewStateRepository] for [InMemoryViewOrderStateRepository]
#[async_trait]
impl ViewStateRepository<OrderEvent, OrderViewState, MaterializedViewError>
for InMemoryViewOrderStateRepository
{
Expand Down
2 changes: 0 additions & 2 deletions tests/saga_manager_combined_test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use async_trait::async_trait;
use derive_more::Display;
use fmodel_rust::saga::Saga;
use fmodel_rust::saga_manager::{ActionPublisher, SagaManager};
Expand Down Expand Up @@ -65,7 +64,6 @@ impl SimpleActionPublisher {
}
}

#[async_trait]
impl ActionPublisher<Sum<ShipmentCommand, OrderCommand>, SagaManagerError>
for SimpleActionPublisher
{
Expand Down
2 changes: 0 additions & 2 deletions tests/saga_manager_test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use async_trait::async_trait;
use derive_more::Display;
use fmodel_rust::saga::Saga;
use fmodel_rust::saga_manager::{ActionPublisher, SagaManager};
Expand Down Expand Up @@ -48,7 +47,6 @@ impl SimpleActionPublisher {
}
}

#[async_trait]
impl ActionPublisher<ShipmentCommand, SagaManagerError> for SimpleActionPublisher {
async fn publish(
&self,
Expand Down

0 comments on commit c06d15c

Please sign in to comment.