Skip to content

Commit

Permalink
pr feedback Signed-off-by: Daniel Gerlag <daniel@gerlag.ca>
Browse files Browse the repository at this point in the history
  • Loading branch information
danielgerlag committed Aug 21, 2023
1 parent 29459bc commit aada8b0
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 0 deletions.
5 changes: 5 additions & 0 deletions examples/actors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ This example demonstrates the Dapr actor framework. To author an actor,
1. Create a struct with your custom actor methods that map to [Axum handlers](https://docs.rs/axum/latest/axum/handler/index.html), use [Axum extractors](https://docs.rs/axum/latest/axum/extract/index.html) to access the incoming request and return an [`impl IntoResponse`](https://docs.rs/axum/latest/axum/response/trait.IntoResponse.html).
Use the `DaprJson` extractor to deserialize the request from Json coming from a Dapr sidecar.
```rust
struct MyActor {
id: String,
client: ActorContextClient
}

#[derive(Serialize, Deserialize)]
pub struct MyRequest {
pub name: String,
Expand Down
36 changes: 36 additions & 0 deletions src/server/actor/context_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ impl Into<TransactionalActorStateOperation> for ActorStateOperation {
}
}

/// A client for interacting with the Dapr runtime within the scope of an actor.
///
/// Hosts methods for interacting with the Dapr sidecar specific to the actor instance.
#[derive(Clone)]
pub struct ActorContextClient{
client: TonicClient,
Expand All @@ -62,6 +65,10 @@ impl ActorContextClient {
}
}

/// Retrieves a keyed state value within the scope of this instance of the actor.
///
/// # Arguments
/// * `key` - The key of the state to retrieve.
pub async fn get_actor_state<K>(&mut self, key: K) -> Result<GetActorStateResponse, DaprError>
where K: Into<String>
{
Expand All @@ -72,6 +79,10 @@ impl ActorContextClient {
}).await?.into_inner())
}

/// Saves a state value within the scope of this instance of the actor.
///
/// # Arguments
/// * `operations` - A list of [ActorStateOperation] to perform on the state.
pub async fn execute_actor_state_transaction(
&mut self,
operations: Vec<ActorStateOperation>,
Expand All @@ -85,6 +96,14 @@ impl ActorContextClient {
}).await?.into_inner())
}

/// Registers a reminder with the Dapr runtime.
///
/// # Arguments
/// * `name` - The name of the reminder.
/// * `due_time` - The time at which the reminder should first be invoked.
/// * `period` - The time interval between invocations of the reminder.
/// * `data` - The data to pass to the reminder when it is invoked.
/// * `ttl` - The time to live for the reminder.
pub async fn register_actor_reminder<I>(
&mut self,
name: I,
Expand Down Expand Up @@ -118,6 +137,10 @@ impl ActorContextClient {
}).await?.into_inner())
}

/// Unregisters a reminder with the Dapr runtime.
///
/// # Arguments
/// * `name` - The name of the reminder to unregister.
pub async fn unregister_actor_reminder<I>(
&mut self,
name: I
Expand All @@ -133,6 +156,15 @@ impl ActorContextClient {
}).await?.into_inner())
}

/// Registers a timer with the Dapr runtime.
///
/// # Arguments
/// * `name` - The name of the timer.
/// * `due_time` - The time at which the timer should first be invoked.
/// * `period` - The time interval between invocations of the timer.
/// * `data` - The data to pass to the timer when it is invoked.
/// * `callback` - The callback name to include in the invocation.
/// * `ttl` - The time to live for the timer.
pub async fn register_actor_timer<I>(
&mut self,
name: I,
Expand Down Expand Up @@ -167,6 +199,10 @@ impl ActorContextClient {
}).await?.into_inner())
}

/// Unregisters a timer with the Dapr runtime.
///
/// # Arguments
/// * `name` - The name of the timer to unregister.
pub async fn unregister_actor_timer<I>(
&mut self,
name: I
Expand Down
56 changes: 56 additions & 0 deletions src/server/actor/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ pub struct ActorState {
pub runtime: Arc<ActorRuntime>,
}

/// Describes the registration of an actor type, including the methods that can be invoked on it and the factory to create instances of it.
/// # Example:
/// ```rust
/// let mut dapr_server = dapr::server::DaprHttpServer::new().await;
///
/// dapr_server.register_actor(ActorTypeRegistration::new::<MyActor>("MyActor", Box::new(|_actor_type, actor_id, context| {
/// Arc::new(MyActor {
/// id: actor_id.to_string(),
/// client: context,
/// })}))
/// .register_method("do_stuff", MyActor::do_stuff)
/// .register_method("do_other_stuff", MyActor::do_other_stuff))
/// .await;
/// ```
pub struct ActorTypeRegistration {
name: String,
factory: ActorFactory,
Expand All @@ -33,6 +47,45 @@ impl ActorTypeRegistration {
}
}

/// Registers a method on the actor type to be exposed to actor clients.
///
/// # Arguments:
/// * `method_name` - The name of the method to be registered. This name will be used by actor clients to invoke the method.
/// * `handler` - The handler function to be invoked when the method is called.
/// Can be any valid [Axum handler](https://docs.rs/axum/latest/axum/handler/index.html),
/// use [Axum extractors](https://docs.rs/axum/latest/axum/extract/index.html) to access the incoming request and return an [`impl IntoResponse`](https://docs.rs/axum/latest/axum/response/trait.IntoResponse.html).
/// Use the `DaprJson` extractor to deserialize the request from Json coming from a Dapr sidecar.
/// # Example:
/// ```rust
/// #[derive(Serialize, Deserialize)]
/// pub struct MyRequest {
/// pub name: String,
///}
///
///#[derive(Serialize, Deserialize)]
///pub struct MyResponse {
/// pub available: bool,
///}
///
///impl MyActor {
/// fn do_stuff(&self, DaprJson(data): DaprJson<MyRequest>) -> Json<MyResponse> {
/// println!("doing stuff with {}", data.name);
/// Json(MyResponse {
/// available: true
/// })
/// }
///}
///
/// let mut dapr_server = dapr::server::DaprHttpServer::new().await;
///
/// dapr_server.register_actor(ActorTypeRegistration::new::<MyActor>("MyActor", Box::new(|_actor_type, actor_id, context| {
/// Arc::new(MyActor {
/// id: actor_id.to_string(),
/// client: context,
/// })}))
/// .register_method("do_stuff", MyActor::do_stuff)
/// .await;
/// ```
pub fn register_method<T>(mut self, method_name: &str, handler: impl Handler<T, ActorState> + Send + Sync) -> Self
where T: 'static
{
Expand Down Expand Up @@ -78,6 +131,9 @@ impl ActorRuntime {
}
}

/// Registers an actor type to be exposed to actor clients.
/// # Arguments:
/// * `registration` - The [ActorTypeRegistration] that describes the actor implementation.
pub async fn register_actor(&self, registration: ActorTypeRegistration) {
let name = registration.name.clone();
let mut g = self.registered_actors_types.write().await;
Expand Down
27 changes: 27 additions & 0 deletions src/server/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,30 @@ use super::actor::runtime::{ActorRuntime, ActorTypeRegistration};
use super::super::client::TonicClient;


/// The Dapr HTTP server.
///
/// Supports Http callbacks from the Dapr sidecar.
///
/// # Example:
/// ```rust
/// let mut dapr_server = dapr::server::DaprHttpServer::new().await;
///
/// dapr_server.register_actor(ActorTypeRegistration::new::<MyActor>("MyActor", Box::new(|_actor_type, actor_id, context| {
/// Arc::new(MyActor {
/// id: actor_id.to_string(),
/// client: context,
/// })}))
/// .register_method("do_stuff", MyActor::do_stuff)
/// .await;
///
/// dapr_server.start(None).await?;
/// ```
pub struct DaprHttpServer {
actor_runtime: Arc<ActorRuntime>,
}

impl DaprHttpServer {
/// Creates a new instance of the Dapr HTTP server with default options.
pub async fn new() -> Self {
let dapr_port: u16 = std::env::var("DAPR_GRPC_PORT").unwrap_or("3501".into()).parse().unwrap();
Self::with_dapr_port(dapr_port).await
Expand All @@ -29,10 +48,18 @@ impl DaprHttpServer {
}
}

/// Registers an actor type with the Dapr runtime.
///
/// # Arguments:
/// * `registration` - The [ActorTypeRegistration] struct, carries the methods that can be invoked on it and the factory to create instances of it.
pub async fn register_actor(&self, registration: ActorTypeRegistration) {
self.actor_runtime.register_actor(registration).await;
}

/// Starts the Dapr HTTP server.
///
/// # Arguments:
/// * `port` - The port to listen on. If not specified, the APP_PORT environment variable will be used. If that is not specified, 8080 will be used.
pub async fn start(&mut self, port: Option<u16>) -> Result<(), Box<dyn std::error::Error>> {
let app = self.build_router().await;

Expand Down

0 comments on commit aada8b0

Please sign in to comment.