From 9ac2fa81b7d34908ddbc09d44d80c8293fd6fe02 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 21 Aug 2023 14:04:54 -0700 Subject: [PATCH] pr feedback Signed-off-by: Daniel Gerlag Signed-off-by: Daniel Gerlag --- examples/actors/README.md | 5 +++ src/server/actor/context_client.rs | 36 +++++++++++++++++++ src/server/actor/runtime/mod.rs | 56 ++++++++++++++++++++++++++++++ src/server/http.rs | 27 ++++++++++++++ 4 files changed, 124 insertions(+) diff --git a/examples/actors/README.md b/examples/actors/README.md index 18bcbb1..b167b96 100644 --- a/examples/actors/README.md +++ b/examples/actors/README.md @@ -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, diff --git a/src/server/actor/context_client.rs b/src/server/actor/context_client.rs index 0cb3e9e..11d65e1 100644 --- a/src/server/actor/context_client.rs +++ b/src/server/actor/context_client.rs @@ -45,6 +45,9 @@ impl Into 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, @@ -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(&mut self, key: K) -> Result where K: Into { @@ -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, @@ -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( &mut self, name: I, @@ -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( &mut self, name: I @@ -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( &mut self, name: I, @@ -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( &mut self, name: I diff --git a/src/server/actor/runtime/mod.rs b/src/server/actor/runtime/mod.rs index 029d2fe..6bf54d1 100644 --- a/src/server/actor/runtime/mod.rs +++ b/src/server/actor/runtime/mod.rs @@ -18,6 +18,20 @@ pub struct ActorState { pub runtime: Arc, } +/// 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", 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, @@ -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) -> Json { + /// 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", 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(mut self, method_name: &str, handler: impl Handler + Send + Sync) -> Self where T: 'static { @@ -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; diff --git a/src/server/http.rs b/src/server/http.rs index 34d692c..1504e9f 100644 --- a/src/server/http.rs +++ b/src/server/http.rs @@ -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", 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, } 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 @@ -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) -> Result<(), Box> { let app = self.build_router().await;