Hello peeps,
I'm working on my personal project and I recently stumbled upon the real force of why async fn
is hard.
I have this nice trait with an async function in it.
The result type of the function, however, is expressed as an associated type, since we don't have GAT yet and impl Trait
can't be used.
pub trait Handler {
type Command;
type Aggregate: Aggregate;
type Error;
type Result: Future<Output = Result<Vec<EventOf<Self::Aggregate>>, Self::Error>>;
fn handle(&self, state: &StateOf<Self::Aggregate>, command: Self::Command) -> Self::Result;
}
Now, my intention is to write a decorator over this trait.
I already have some code in place, check it out here:
impl<H: Handler> Handler for AsHandler<H> {
type Command = H::Command;
// Decorated Aggregate type
type Aggregate = AsAggregate<H::Aggregate>;
type Error = H::Error;
type Result = H::Result;
fn handle(&self, state: &StateOf<Self::Aggregate>, command: Self::Command) -> Self::Result {
self.0.handle(state, command)
}
}
As you can see, the type Result
is basically taken as-is from the generic Handler
implementation we're decorating.
However, I'd like to return a different result here.
Since we have no GAT, I need to box and pin the async block to await the decorated Handler.handle
method execution and then mapping the result, so it would be something like this:
type Result =
Pin<Box<dyn Future<Output = Result<Vec<EventOf<Self::Aggregate>>, Self::Error>>>>;
fn handle(
&self,
state: &StateOf<Self::Aggregate>,
command: Self::Command,
) -> Self::Result {
Box::pin(async move {
let version = state.version();
self.0.handle(state, command).await.map(|events| {
events
.into_iter()
.map(|event| Versioned::with_version(event, version + 1))
.collect::<Vec<EventOf<Self::Aggregate>>>()
})
})
}
However, this is not going to work due to type Result
assuming 'static
lifetime for dyn Future
.
Is there any way I can do this?
For complete reference, this is the link to the actual source code if you want to take a look: eventually-rs/versioned.rs at 5beeb2f94260a40bfccf8a28eea9d32b8e3ea796 · get-eventually/eventually-rs · GitHub
Many many thanks to whoever puts some time into this!