Skip to content

Commit c06d15c

Browse files
authored
Merge pull request #20 from fraktalio/feature/async_fn_in_traits
`async fn` in Traits - a new `stable` feature of Rust 1.75
2 parents 1d7512e + 0a5dd06 commit c06d15c

13 files changed

+58
-55
lines changed

.github/workflows/build.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,21 @@ env:
1212
jobs:
1313
build:
1414

15-
runs-on: ubuntu-latest
15+
runs-on: ${{ matrix.os }}
16+
strategy:
17+
matrix:
18+
os: [ ubuntu-latest, windows-latest, macOS-latest ]
19+
rust: [ stable, nightly ]
1620

1721
steps:
22+
- uses: hecrj/setup-rust-action@v2
23+
with:
24+
rust-version: ${{ matrix.rust }}
25+
1826
- uses: actions/checkout@v4
27+
1928
- name: Build
2029
run: cargo build --verbose
30+
2131
- name: Run tests
2232
run: cargo test --verbose

.github/workflows/publish.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,19 @@ env:
1010
jobs:
1111
build:
1212

13-
runs-on: ubuntu-latest
13+
runs-on: ${{ matrix.os }}
14+
strategy:
15+
matrix:
16+
os: [ ubuntu-latest, windows-latest, macOS-latest ]
17+
rust: [ stable, nightly ]
1418

1519
steps:
20+
- uses: hecrj/setup-rust-action@v2
21+
with:
22+
rust-version: ${{ matrix.rust }}
23+
1624
- uses: actions/checkout@v4
25+
1726
- name: Publish
1827
run: cargo publish --token ${CRATES_TOKEN}
1928
env:

Cargo.lock

Lines changed: 1 addition & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
[package]
22
name = "fmodel-rust"
3-
version = "0.6.1"
3+
version = "0.7.0"
44
edition = "2021"
55
description = "Accelerate development of compositional, safe, and ergonomic applications/information systems by effectively implementing Event Sourcing and CQRS patterns in Rust."
66
license = "Apache-2.0"
77

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

1211

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

src/aggregate.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
use std::future::Future;
12
use std::marker::PhantomData;
23

3-
use async_trait::async_trait;
4-
54
use crate::decider::{Decider, EventComputation, StateComputation};
65
use crate::saga::{ActionComputation, Saga};
76

@@ -13,16 +12,22 @@ use crate::saga::{ActionComputation, Saga};
1312
/// - `E` - Event
1413
/// - `Version` - Version/Offset/Sequence number
1514
/// - `Error` - Error
16-
#[async_trait]
1715
pub trait EventRepository<C, E, Version, Error> {
1816
/// Fetches current events, based on the command.
19-
async fn fetch_events(&self, command: &C) -> Result<Vec<(E, Version)>, Error>;
17+
/// 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`.
18+
/// 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.
19+
fn fetch_events(
20+
&self,
21+
command: &C,
22+
) -> impl Future<Output = Result<Vec<(E, Version)>, Error>> + Send;
2023
/// Saves events.
21-
async fn save(
24+
/// 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`
25+
/// 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.
26+
fn save(
2227
&self,
2328
events: &[E],
2429
latest_version: &Option<Version>,
25-
) -> Result<Vec<(E, Version)>, Error>;
30+
) -> impl Future<Output = Result<Vec<(E, Version)>, Error>> + Send;
2631
}
2732

2833
/// Event Sourced Aggregate.
@@ -61,7 +66,6 @@ where
6166
}
6267
}
6368

64-
#[async_trait]
6569
impl<C, S, E, Repository, Decider, Version, Error> EventRepository<C, E, Version, Error>
6670
for EventSourcedAggregate<C, S, E, Repository, Decider, Version, Error>
6771
where
@@ -129,12 +133,22 @@ where
129133
/// - `S` - State
130134
/// - `Version` - Version
131135
/// - `Error` - Error
132-
#[async_trait]
133136
pub trait StateRepository<C, S, Version, Error> {
134137
/// Fetches current state, based on the command.
135-
async fn fetch_state(&self, command: &C) -> Result<Option<(S, Version)>, Error>;
138+
/// 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`
139+
/// 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.
140+
fn fetch_state(
141+
&self,
142+
command: &C,
143+
) -> impl Future<Output = Result<Option<(S, Version)>, Error>> + Send;
136144
/// Saves state.
137-
async fn save(&self, state: &S, version: &Option<Version>) -> Result<(S, Version), Error>;
145+
/// 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`
146+
/// 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.
147+
fn save(
148+
&self,
149+
state: &S,
150+
version: &Option<Version>,
151+
) -> impl Future<Output = Result<(S, Version), Error>> + Send;
138152
}
139153

140154
/// State Stored Aggregate.
@@ -173,7 +187,6 @@ where
173187
}
174188
}
175189

176-
#[async_trait]
177190
impl<C, S, E, Repository, Decider, Version, Error> StateRepository<C, S, Version, Error>
178191
for StateStoredAggregate<C, S, E, Repository, Decider, Version, Error>
179192
where
@@ -281,7 +294,6 @@ where
281294
}
282295
}
283296

284-
#[async_trait]
285297
impl<'a, C, S, E, Repository, Version, Error> StateRepository<C, S, Version, Error>
286298
for StateStoredOrchestratingAggregate<'a, C, S, E, Repository, Version, Error>
287299
where

src/materialized_view.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
use std::future::Future;
12
use std::marker::PhantomData;
23

3-
use async_trait::async_trait;
4-
54
use crate::view::ViewStateComputation;
65

76
/// View State Repository trait
@@ -11,12 +10,15 @@ use crate::view::ViewStateComputation;
1110
/// - `E` - Event
1211
/// - `S` - State
1312
/// - `Error` - Error
14-
#[async_trait]
1513
pub trait ViewStateRepository<E, S, Error> {
1614
/// Fetches current state, based on the event.
17-
async fn fetch_state(&self, event: &E) -> Result<Option<S>, Error>;
15+
/// Desugared `async fn fetch_state(&self, event: &E) -> Result<Option<S>, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`.
16+
/// 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.
17+
fn fetch_state(&self, event: &E) -> impl Future<Output = Result<Option<S>, Error>> + Send;
1818
/// Saves the new state.
19-
async fn save(&self, state: &S) -> Result<S, Error>;
19+
/// Desugared `async fn save(&self, state: &S) -> Result<S, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`.
20+
/// 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.
21+
fn save(&self, state: &S) -> impl Future<Output = Result<S, Error>> + Send;
2022
}
2123

2224
/// Materialized View.
@@ -53,7 +55,6 @@ where
5355
}
5456
}
5557

56-
#[async_trait]
5758
impl<S, E, Repository, View, Error> ViewStateRepository<E, S, Error>
5859
for MaterializedView<S, E, Repository, View, Error>
5960
where

src/saga_manager.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
use std::future::Future;
12
use std::marker::PhantomData;
23

3-
use async_trait::async_trait;
4-
54
use crate::saga::ActionComputation;
65

76
/// Publishes the action/command to some external system.
@@ -10,10 +9,11 @@ use crate::saga::ActionComputation;
109
///
1110
/// - `A`. - action
1211
/// - `Error` - error
13-
#[async_trait]
1412
pub trait ActionPublisher<A, Error> {
1513
/// Publishes the action/command to some external system, returning either the actions that are successfully published or error.
16-
async fn publish(&self, action: &[A]) -> Result<Vec<A>, Error>;
14+
/// Desugared `async fn publish(&self, action: &[A]) -> Result<Vec<A>, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`.
15+
/// 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.
16+
fn publish(&self, action: &[A]) -> impl Future<Output = Result<Vec<A>, Error>> + Send;
1717
}
1818

1919
/// Saga Manager.
@@ -48,7 +48,6 @@ where
4848
}
4949
}
5050

51-
#[async_trait]
5251
impl<A, AR, Publisher, Saga, Error> ActionPublisher<A, Error>
5352
for SagaManager<A, AR, Publisher, Saga, Error>
5453
where

tests/aggregate_combined_test.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::error::Error;
33
use std::sync::{Arc, Mutex};
44
use std::thread;
55

6-
use async_trait::async_trait;
76
use derive_more::Display;
87

98
use fmodel_rust::aggregate::{
@@ -75,7 +74,6 @@ impl Id for (OrderState, ShipmentState) {
7574
}
7675
}
7776
/// Implementation of [EventRepository] for [InMemoryEventRepository] - infrastructure
78-
#[async_trait]
7977
impl
8078
EventRepository<
8179
Sum<OrderCommand, ShipmentCommand>,
@@ -133,7 +131,6 @@ impl InMemoryStateRepository {
133131
}
134132

135133
// Implementation of [StateRepository] for [InMemoryOrderStateRepository]
136-
#[async_trait]
137134
impl
138135
StateRepository<
139136
Sum<OrderCommand, ShipmentCommand>,

tests/aggregate_test.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::error::Error;
33
use std::sync::{Arc, Mutex};
44
use std::thread;
55

6-
use async_trait::async_trait;
76
use derive_more::Display;
87

98
use fmodel_rust::aggregate::{
@@ -44,7 +43,6 @@ impl InMemoryOrderEventRepository {
4443
}
4544

4645
/// Implementation of [EventRepository] for [InMemoryOrderEventRepository] - infrastructure
47-
#[async_trait]
4846
impl EventRepository<OrderCommand, OrderEvent, i32, AggregateError>
4947
for InMemoryOrderEventRepository
5048
{
@@ -97,7 +95,6 @@ impl InMemoryOrderStateRepository {
9795
}
9896

9997
// Implementation of [StateRepository] for [InMemoryOrderStateRepository]
100-
#[async_trait]
10198
impl StateRepository<OrderCommand, OrderState, i32, AggregateError>
10299
for InMemoryOrderStateRepository
103100
{

tests/materialized_view_combined_test.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::error::Error;
33
use std::sync::{Arc, Mutex};
44
use std::thread;
55

6-
use async_trait::async_trait;
76
use derive_more::Display;
87

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

127126
// Implementation of [ViewStateRepository] for [InMemoryViewOrderStateRepository]
128-
#[async_trait]
129127
impl
130128
ViewStateRepository<
131129
Sum<OrderEvent, ShipmentEvent>,

0 commit comments

Comments
 (0)