#[derive(HandleClient)]
#
#[derive(Handler)]
generates both the server-side handler trait (ShoppingListHandler
) and the client-side trait definition (ShoppingListClient
). However, it does not implement the client trait for any specific type.
This is where #[derive(HandleClient)]
comes in.
What It Adds#
#[derive(HandleClient)]
generates the following implementation:
impl<T> ShoppingListClient for ActorHandle<T>
where
T: ShoppingListHandler + Send + Sync + 'static`
This means you can call methods like .add(...)
or .list(...)
directly on an ActorHandle<T>
without needing to manually implement the ShoppingListClient
trait:
In other words, HandleClient
connects the generated ShoppingListClient
interface (from Handler
) to the concrete type ActorHandle<T>
.
Generated Implementation (simplified)#
use async_trait::async_trait;
use hyperactor::{
ActorHandle,
anyhow::Error,
cap::{CanSend, CanOpenPort},
mailbox::open_once_port,
metrics,
Message,
};
#[async_trait]
impl<T> ShoppingListClient for ActorHandle<T>
where
T: ShoppingListHandler + Send + Sync + 'static,
{
async fn add(&self, caps: &impl CanSend, item: String) -> Result<(), Error> {
self.send(caps, ShoppingList::Add(item)).await
}
async fn remove(&self, caps: &impl CanSend, item: String) -> Result<(), Error> {
self.send(caps, ShoppingList::Remove(item)).await
}
async fn exists(
&self,
caps: &impl CanSend + CanOpenPort,
item: String,
) -> Result<bool, Error> {
let (reply_to, recv) = open_once_port(caps)?;
self.send(caps, ShoppingList::Exists(item, reply_to)).await?;
Ok(recv.await?)
}
async fn list(
&self,
caps: &impl CanSend + CanOpenPort,
) -> Result<Vec<String>, Error> {
let (reply_to, recv) = open_once_port(caps)?;
self.send(caps, ShoppingList::List(reply_to)).await?;
Ok(recv.await?)
}