Compare commits

...

21 Commits

Author SHA1 Message Date
Marc Duiker 407447816c
Update markdown files to be compatible with latest Hugo (#287)
Signed-off-by: Marc Duiker <marcduiker@users.noreply.github.com>
2025-07-10 09:15:57 +01:00
Mike Nguyen 06ea44e8d3
fix: refactor log formatting (#285)
* fix: refactor log formatting

Signed-off-by: mikeee <hey@mike.ee>

* fix: refactor all print formatting

Signed-off-by: mikeee <hey@mike.ee>

---------

Signed-off-by: mikeee <hey@mike.ee>
2025-06-27 14:56:05 +01:00
Mike Nguyen 942263938a
fix(chore): allow large size difference between variants in generated enums (#283)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-06-03 16:16:31 +01:00
Mike Nguyen 9537a3b826
chore: limit the visibility of the cargo token (#280)
Addresses #218

Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-05-14 15:49:35 +01:00
Mike Nguyen 35930ebc5f
docs: fix typo (#279)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-05-14 13:56:31 +01:00
Mike Nguyen acb829cdb5
chore: pin idna_adapter (#278)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-05-14 13:04:17 +01:00
Mike Nguyen 26f4ee6d32
fix(docs): over indented docs (#274)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-04-09 11:04:09 +01:00
Mike Nguyen 4fb85abcea fix(deps): pin reserve-port to 2.1.0
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-04-01 19:19:07 +01:00
Mike Nguyen f1e469cf57 fix(deps): pin axum-test crate to 16.4.0
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-04-01 19:19:07 +01:00
Mike Nguyen 1cdcc272ce chore: remove pinned release versions validation (#270)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-03-10 15:53:52 +00:00
Mike Nguyen 185dc72889
release: v0.16.0 (#266)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-02-27 19:00:39 +00:00
Mike Nguyen 1508ea24cb
chore: bump protos to rc18 (#265)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-02-27 13:47:18 +00:00
Mike Nguyen 99d099f15e
release: rc.7 (#264)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-02-27 13:17:39 +00:00
Mike Nguyen c0b7155093
fix(deps): pin indirect dependencies (#263)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-02-27 13:05:28 +00:00
Mike Nguyen ab219049a4
refactor(conversations): rename message to content (#261)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-02-24 17:40:04 +00:00
Mike Nguyen 57347e70c3
feat(client): add a client port override method (#259)
* feat(client): add a client port override method

Signed-off-by: Mike Nguyen <hey@mike.ee>

* chore(lint): cargo fmt

Signed-off-by: Mike Nguyen <hey@mike.ee>

* doc(client): add port method

Signed-off-by: mikeee <hey@mike.ee>

* release: rc6

Signed-off-by: mikeee <hey@mike.ee>

---------

Signed-off-by: Mike Nguyen <hey@mike.ee>
Signed-off-by: mikeee <hey@mike.ee>
2025-02-09 21:01:22 +00:00
Mike Nguyen 93322c0e86
release: bump (#256)
* release: bump

Signed-off-by: Mike Nguyen <hey@mike.ee>

* bump to cli rc3 & runtime rc6

Signed-off-by: Mike Nguyen <hey@mike.ee>

* bump runtime to rc7

Signed-off-by: Mike Nguyen <hey@mike.ee>

* chore: bump validation to latest rcs

Signed-off-by: mikeee <hey@mike.ee>

* chore(release): bump deps and rc version

Signed-off-by: mikeee <hey@mike.ee>

* chore(release): regen protos

Signed-off-by: mikeee <hey@mike.ee>

* chore: regen protos from rc.9

Signed-off-by: mikeee <hey@mike.ee>

---------

Signed-off-by: Mike Nguyen <hey@mike.ee>
Signed-off-by: mikeee <hey@mike.ee>
2025-02-03 15:49:18 +00:00
Leon Matthes 52f095f8e7
Add fallback handler to axum Router (#258)
By default the fallback handler now logs the path that could not be
found.
This can be vital for debugging, as otherwise there is no feedback on
the server if a method is called that isn't registered.

Signed-off-by: Leon Matthes <leon.matthes@kdab.com>
2025-01-28 20:21:14 +00:00
Mike Nguyen a532ee1a50
chore: bump runtime to 1.15.0-rc.2 (#255)
Signed-off-by: mikeee <hey@mike.ee>
2025-01-15 16:12:31 +00:00
Mike Nguyen 8bf6013eee
Cleanup (#254)
* Return Result when creating DaprHttpServer

Especially when running custom docker setups, the container that
contains the sidecar may not be running exactly when the Rust code
starts running.

To fix this, before we needed to sleep(2s) to avoid a panic in the Rust
program.
With this patch, this can be handled on the user side (e.g. the
connection can be retried multiple times with timeouts in-between).

Signed-off-by: Leon Matthes <leon.matthes@kdab.com>

* release: v0.16.0-rc.4

Signed-off-by: Mike Nguyen <hey@mike.ee>

* chore(deps): remove unused crates

Signed-off-by: Mike Nguyen <hey@mike.ee>

* doc: missing expression closure

Signed-off-by: Mike Nguyen <hey@mike.ee>

* refactor: lint issues and correctness improvements

Signed-off-by: Mike Nguyen <hey@mike.ee>

---------

Signed-off-by: Leon Matthes <leon.matthes@kdab.com>
Signed-off-by: Mike Nguyen <hey@mike.ee>
Co-authored-by: Leon Matthes <leon.matthes@kdab.com>
2025-01-15 10:52:01 +00:00
Leon Matthes 6973b7d9be
Return Result when creating DaprHttpServer (#253)
Especially when running custom docker setups, the container that
contains the sidecar may not be running exactly when the Rust code
starts running.

With this patch, this can be handled on the user side (e.g. the
connection can be retried multiple times with timeouts in between).

Signed-off-by: Leon Matthes <leon.matthes@kdab.com>
Co-authored-by: Mike Nguyen <hey@mike.ee>
2024-12-10 20:16:13 +00:00
42 changed files with 217 additions and 157 deletions

View File

@ -16,7 +16,6 @@ on:
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
CARGO_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
PROTOC_VERSION: 24.4 PROTOC_VERSION: 24.4
RUSTFLAGS: "-D warnings" RUSTFLAGS: "-D warnings"
@ -145,4 +144,6 @@ jobs:
version: ${{ env.PROTOC_VERSION }} version: ${{ env.PROTOC_VERSION }}
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: cargo publish - ${{ matrix.crate }} - name: cargo publish - ${{ matrix.crate }}
env:
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
run: cargo publish --manifest-path ${{ matrix.crate }}/Cargo.toml --token ${{ env.CARGO_TOKEN }} run: cargo publish --manifest-path ${{ matrix.crate }}/Cargo.toml --token ${{ env.CARGO_TOKEN }}

View File

@ -11,6 +11,6 @@ rust-version = "1.70.0"
[dependencies] [dependencies]
exitcode = "1.1.2" exitcode = "1.1.2"
octocrab = "0.34.1" octocrab = "0.42.1"
serde_json = "1.0.114" serde_json = "1.0.114"
tokio = { version = "1.36.0", features = ["full"] } tokio = { version = "1.36.0", features = ["full"] }

View File

@ -46,7 +46,7 @@ jobs:
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/master/install/install.sh DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/master/install/install.sh
DAPR_CLI_REF: ${{ github.event.inputs_daprcli_commit }} DAPR_CLI_REF: ${{ github.event.inputs_daprcli_commit }}
DAPR_CLI_VERSION: ${{ github.event.inputs_daprcli_version }} DAPR_CLI_VERSION: ${{ github.event.inputs_daprcli_version }}
DAPR_REF: 334ae9eea43d487a7b29a0e4aef904e3eba57a10 DAPR_REF: ${{ github.event.inputs.dapr_commit }}
DAPR_RUNTIME_VERSION: ${{ github.event.inputs.dapr_version }} DAPR_RUNTIME_VERSION: ${{ github.event.inputs.dapr_version }}
CHECKOUT_REPO: ${{ github.repository }} CHECKOUT_REPO: ${{ github.repository }}
CHECKOUT_REF: ${{ github.ref }} CHECKOUT_REF: ${{ github.ref }}

View File

@ -12,23 +12,21 @@ resolver = "2"
[workspace.dependencies] [workspace.dependencies]
async-trait = "0.1" async-trait = "0.1"
prost = "0.13.1" prost = "0.13.4"
prost-build = "0.13.1" prost-types = "0.13.4"
prost-types = "0.13.1"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
tokio = "1.39" tokio = "1.39"
tokio-stream = "0.1" tokio-stream = "0.1"
tokio-test = "0.4"
tokio-util = "0.7" tokio-util = "0.7"
tonic = "0.12.1" tonic = "0.12.3"
tonic-build = "0.12.1" tonic-build = "0.12.3"
[workspace.package] [workspace.package]
version = "0.16.0-rc.3" version = "0.16.0"
authors = [ authors = [
"Mike Nguyen <hey@mike.ee>", "Mike Nguyen <hey@mike.ee>",
"The Dapr Authors <dapr@dapr.io>" "The Dapr Authors <dapr@dapr.io>"

View File

@ -53,7 +53,7 @@ Add the following to your `Cargo.toml` file:
```toml ```toml
[dependencies] [dependencies]
dapr = "0.16.0-rc.3" dapr = "0.16.0"
``` ```
Here's a basic example to create a client: Here's a basic example to create a client:

View File

@ -12,9 +12,6 @@ rust-version.workspace = true
proc-macro = true proc-macro = true
[dependencies] [dependencies]
async-trait = { workspace = true }
axum = "0.7"
log = "0.4"
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "2.0", features = ["full"] } syn = { version = "2.0", features = ["full"] }

View File

@ -81,7 +81,7 @@ pub fn actor(_attr: TokenStream, item: TokenStream) -> TokenStream {
Ok(actor_struct) => actor_struct.ident.clone(), Ok(actor_struct) => actor_struct.ident.clone(),
Err(_) => match syn::parse::<syn::ItemType>(item.clone()) { Err(_) => match syn::parse::<syn::ItemType>(item.clone()) {
Ok(ty) => ty.ident.clone(), Ok(ty) => ty.ident.clone(),
Err(e) => panic!("Error parsing actor struct: {}", e), Err(e) => panic!("Error parsing actor struct: {e}"),
}, },
}; };

View File

@ -13,7 +13,6 @@ rust-version.workspace = true
[dependencies] [dependencies]
async-trait = { workspace = true } async-trait = { workspace = true }
axum = "0.7" axum = "0.7"
bytes = "1.7"
chrono = "0.4" chrono = "0.4"
futures = "0.3" futures = "0.3"
log = "0.4" log = "0.4"
@ -27,11 +26,15 @@ tokio-util = { workspace = true, features = ["io"] }
[dev-dependencies] [dev-dependencies]
axum-test = "16.4.0" axum-test = "=16.4.0" # TODO: Remove problematic dep
litemap = "=0.7.4" # TODO: Remove pinned - linked to axum_test
zerofrom = "=0.1.5" # TODO: Remove pinned - linked to axum_test
reserve-port = "=2.1.0" # TODO: Remove pinned - linked to axum_test
idna_adapter = "=1.2.0"
once_cell = "1.19" once_cell = "1.19"
dapr = { path = "./" } dapr = { path = "./" }
dapr-macros = { path = "../dapr-macros" } dapr-macros = { path = "../dapr-macros" }
tokio = { workspace = true, features = ["full"] } tokio = { workspace = true, features = ["full"] }
uuid = { version = "1.10", features = ["v4"] } uuid = { version = "1.10", features = ["v4"] }
tokio-test = { workspace = true }
tokio-stream = { workspace = true } tokio-stream = { workspace = true }

View File

@ -1,37 +1,36 @@
use crate::dapr;
use crate::dapr::proto::runtime::v1::app_callback_server::AppCallback; use crate::dapr::proto::runtime::v1::app_callback_server::AppCallback;
use crate::dapr::proto::{common, runtime}; use crate::dapr::proto::{common, runtime};
use std::collections::HashMap; use std::collections::HashMap;
use tonic::{Code, Request, Response, Status}; use tonic::{Code, Request, Response, Status};
/// InvokeRequest is the message to invoke a method with the data. /// InvokeRequest is the message to invoke a method with the data.
pub type InvokeRequest = dapr::proto::common::v1::InvokeRequest; pub type InvokeRequest = common::v1::InvokeRequest;
/// InvokeResponse is the response message inclduing data and its content type /// InvokeResponse is the response message inclduing data and its content type
/// from app callback. /// from app callback.
pub type InvokeResponse = dapr::proto::common::v1::InvokeResponse; pub type InvokeResponse = common::v1::InvokeResponse;
/// ListTopicSubscriptionsResponse is the message including the list of the subscribing topics. /// ListTopicSubscriptionsResponse is the message including the list of the subscribing topics.
pub type ListTopicSubscriptionsResponse = dapr::proto::runtime::v1::ListTopicSubscriptionsResponse; pub type ListTopicSubscriptionsResponse = runtime::v1::ListTopicSubscriptionsResponse;
/// TopicSubscription represents a topic and it's metadata (session id etc.) /// TopicSubscription represents a topic and it's metadata (session id etc.)
pub type TopicSubscription = dapr::proto::runtime::v1::TopicSubscription; pub type TopicSubscription = runtime::v1::TopicSubscription;
/// TopicEventRequest message is compatiable with CloudEvent spec v1.0. /// TopicEventRequest message is compatiable with CloudEvent spec v1.0.
pub type TopicEventRequest = dapr::proto::runtime::v1::TopicEventRequest; pub type TopicEventRequest = runtime::v1::TopicEventRequest;
/// TopicEventResponse is response from app on published message /// TopicEventResponse is response from app on published message
pub type TopicEventResponse = dapr::proto::runtime::v1::TopicEventResponse; pub type TopicEventResponse = runtime::v1::TopicEventResponse;
/// ListInputBindingsResponse is the message including the list of input bindings. /// ListInputBindingsResponse is the message including the list of input bindings.
pub type ListInputBindingsResponse = dapr::proto::runtime::v1::ListInputBindingsResponse; pub type ListInputBindingsResponse = runtime::v1::ListInputBindingsResponse;
/// BindingEventRequest represents input bindings event. /// BindingEventRequest represents input bindings event.
pub type BindingEventRequest = dapr::proto::runtime::v1::BindingEventRequest; pub type BindingEventRequest = runtime::v1::BindingEventRequest;
/// BindingEventResponse includes operations to save state or /// BindingEventResponse includes operations to save state or
/// send data to output bindings optionally. /// send data to output bindings optionally.
pub type BindingEventResponse = dapr::proto::runtime::v1::BindingEventResponse; pub type BindingEventResponse = runtime::v1::BindingEventResponse;
impl ListTopicSubscriptionsResponse { impl ListTopicSubscriptionsResponse {
/// Create `ListTopicSubscriptionsResponse` with a topic. /// Create `ListTopicSubscriptionsResponse` with a topic.

View File

@ -25,7 +25,27 @@ impl<T: DaprInterface> Client<T> {
pub async fn connect(addr: String) -> Result<Self, Error> { pub async fn connect(addr: String) -> Result<Self, Error> {
// Get the Dapr port to create a connection // Get the Dapr port to create a connection
let port: u16 = std::env::var("DAPR_GRPC_PORT")?.parse()?; let port: u16 = std::env::var("DAPR_GRPC_PORT")?.parse()?;
let address = format!("{}:{}", addr, port); let address = format!("{addr}:{port}");
Ok(Client(T::connect(address).await?))
}
/// Connect to the Dapr sidecar with a specific port.
///
/// # Arguments
///
/// * `addr` - Address of gRPC server to connect to.
/// * `port` - Port of the gRPC server to connect to.
pub async fn connect_with_port(addr: String, port: String) -> Result<Self, Error> {
// assert that port is between 1 and 65535
let port: u16 = match port.parse::<u16>() {
Ok(p) => p,
Err(_) => {
panic!("Port must be a number between 1 and 65535");
}
};
let address = format!("{addr}:{port}");
Ok(Client(T::connect(address).await?)) Ok(Client(T::connect(address).await?))
} }
@ -656,6 +676,13 @@ impl DaprInterface for dapr_v1::dapr_client::DaprClient<TonicChannel> {
Ok(dapr_v1::dapr_client::DaprClient::connect(addr).await?) Ok(dapr_v1::dapr_client::DaprClient::connect(addr).await?)
} }
async fn publish_event(&mut self, request: PublishEventRequest) -> Result<(), Error> {
self.publish_event(Request::new(request))
.await?
.into_inner();
Ok(())
}
async fn invoke_service( async fn invoke_service(
&mut self, &mut self,
request: InvokeServiceRequest, request: InvokeServiceRequest,
@ -676,13 +703,6 @@ impl DaprInterface for dapr_v1::dapr_client::DaprClient<TonicChannel> {
.into_inner()) .into_inner())
} }
async fn publish_event(&mut self, request: PublishEventRequest) -> Result<(), Error> {
self.publish_event(Request::new(request))
.await?
.into_inner();
Ok(())
}
async fn get_secret(&mut self, request: GetSecretRequest) -> Result<GetSecretResponse, Error> { async fn get_secret(&mut self, request: GetSecretRequest) -> Result<GetSecretResponse, Error> {
Ok(self.get_secret(Request::new(request)).await?.into_inner()) Ok(self.get_secret(Request::new(request)).await?.into_inner())
} }
@ -701,6 +721,11 @@ impl DaprInterface for dapr_v1::dapr_client::DaprClient<TonicChannel> {
Ok(self.get_state(Request::new(request)).await?.into_inner()) Ok(self.get_state(Request::new(request)).await?.into_inner())
} }
async fn save_state(&mut self, request: SaveStateRequest) -> Result<(), Error> {
self.save_state(Request::new(request)).await?.into_inner();
Ok(())
}
async fn query_state_alpha1( async fn query_state_alpha1(
&mut self, &mut self,
request: QueryStateRequest, request: QueryStateRequest,
@ -711,11 +736,6 @@ impl DaprInterface for dapr_v1::dapr_client::DaprClient<TonicChannel> {
.into_inner()) .into_inner())
} }
async fn save_state(&mut self, request: SaveStateRequest) -> Result<(), Error> {
self.save_state(Request::new(request)).await?.into_inner();
Ok(())
}
async fn delete_state(&mut self, request: DeleteStateRequest) -> Result<(), Error> { async fn delete_state(&mut self, request: DeleteStateRequest) -> Result<(), Error> {
self.delete_state(Request::new(request)).await?.into_inner(); self.delete_state(Request::new(request)).await?.into_inner();
Ok(()) Ok(())
@ -1073,7 +1093,7 @@ impl JobBuilder {
} }
pub struct ConversationInputBuilder { pub struct ConversationInputBuilder {
message: String, content: String,
role: Option<String>, role: Option<String>,
scrub_pii: Option<bool>, scrub_pii: Option<bool>,
} }
@ -1081,7 +1101,7 @@ pub struct ConversationInputBuilder {
impl ConversationInputBuilder { impl ConversationInputBuilder {
pub fn new(message: &str) -> Self { pub fn new(message: &str) -> Self {
ConversationInputBuilder { ConversationInputBuilder {
message: message.to_string(), content: message.to_string(),
role: None, role: None,
scrub_pii: None, scrub_pii: None,
} }
@ -1089,7 +1109,7 @@ impl ConversationInputBuilder {
pub fn build(self) -> ConversationInput { pub fn build(self) -> ConversationInput {
ConversationInput { ConversationInput {
message: self.message, content: self.content,
role: self.role, role: self.role,
scrub_pii: self.scrub_pii, scrub_pii: self.scrub_pii,
} }

View File

@ -2373,9 +2373,18 @@ pub struct GetMetadataResponse {
pub runtime_version: ::prost::alloc::string::String, pub runtime_version: ::prost::alloc::string::String,
#[prost(string, repeated, tag = "9")] #[prost(string, repeated, tag = "9")]
pub enabled_features: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, pub enabled_features: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// TODO: Cassie: probably add scheduler runtime status
#[prost(message, optional, tag = "10")] #[prost(message, optional, tag = "10")]
pub actor_runtime: ::core::option::Option<ActorRuntime>, pub actor_runtime: ::core::option::Option<ActorRuntime>,
#[prost(message, optional, tag = "11")]
pub scheduler: ::core::option::Option<MetadataScheduler>,
}
/// MetadataScheduler is a message that contains the list of addresses of the
/// scheduler connections.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct MetadataScheduler {
/// connected_addresses the list of addresses of the scheduler connections.
#[prost(string, repeated, tag = "1")]
pub connected_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
} }
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ActorRuntime { pub struct ActorRuntime {
@ -3261,9 +3270,9 @@ pub struct ConversationRequest {
} }
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ConversationInput { pub struct ConversationInput {
/// The message to send to the llm /// The content to send to the llm
#[prost(string, tag = "1")] #[prost(string, tag = "1")]
pub message: ::prost::alloc::string::String, pub content: ::prost::alloc::string::String,
/// The role to set for the message /// The role to set for the message
#[prost(string, optional, tag = "2")] #[prost(string, optional, tag = "2")]
pub role: ::core::option::Option<::prost::alloc::string::String>, pub role: ::core::option::Option<::prost::alloc::string::String>,

Binary file not shown.

View File

@ -13,7 +13,7 @@ pub enum Error {
impl Display for Error { impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self) write!(f, "{self:?}")
} }
} }
@ -50,6 +50,6 @@ pub struct GrpcError {
impl Display for GrpcError { impl Display for GrpcError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self) write!(f, "{self:?}")
} }
} }

View File

@ -9,8 +9,10 @@ pub use client::Client;
pub mod appcallback; pub mod appcallback;
/// Module containing the 'Client' implementation. /// Module containing the 'Client' implementation.
pub mod client; pub mod client;
/// Module importing the Dapr runtime implementation. /// Module importing the Dapr runtime implementation.
pub mod dapr { pub mod dapr {
#![allow(clippy::large_enum_variant)]
pub mod proto { pub mod proto {
pub mod common { pub mod common {
pub mod v1 { pub mod v1 {

View File

@ -37,7 +37,7 @@ impl Display for ActorError {
ActorError::CorruptedState => write!(f, "Actor state corrupted"), ActorError::CorruptedState => write!(f, "Actor state corrupted"),
ActorError::MethodNotFound => write!(f, "Method not found"), ActorError::MethodNotFound => write!(f, "Method not found"),
ActorError::ActorNotFound => write!(f, "Actor not found"), ActorError::ActorNotFound => write!(f, "Actor not found"),
ActorError::MethodError(e) => write!(f, "Method error: {}", e), ActorError::MethodError(e) => write!(f, "Method error: {e}"),
ActorError::SerializationError() => write!(f, "Serialization error"), ActorError::SerializationError() => write!(f, "Serialization error"),
} }
} }

View File

@ -102,9 +102,9 @@ impl ActorTypeRegistration {
/// # Arguments: /// # Arguments:
/// * `method_name` - The name of the method to be registered. This name will be used by actor clients to invoke the method. /// * `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. /// * `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), /// 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 [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. /// Use the `DaprJson` extractor to deserialize the request from Json coming from a Dapr sidecar.
/// # Example: /// # Example:
/// ```ignore /// ```ignore
/// # use std::sync::Arc; /// # use std::sync::Arc;
@ -174,7 +174,7 @@ impl ActorTypeRegistration {
T: 'static, T: 'static,
{ {
let actor_type = self.name.clone(); let actor_type = self.name.clone();
let method_path = format!("/actors/{}/:actor_id/method/{}", actor_type, method_name); let method_path = format!("/actors/{actor_type}/:actor_id/method/{method_name}");
let reg_func = move |router: Router, runtime: Arc<ActorRuntime>| { let reg_func = move |router: Router, runtime: Arc<ActorRuntime>| {
router.route( router.route(
@ -224,7 +224,7 @@ impl ActorRuntime {
let name = registration.name.clone(); let name = registration.name.clone();
let mut g = self.registered_actors_types.write().await; let mut g = self.registered_actors_types.write().await;
g.insert(name.clone(), registration); g.insert(name.clone(), registration);
log::info!("registered actor {}", name); log::info!("registered actor {name}");
} }
pub async fn configure_method_routes( pub async fn configure_method_routes(

View File

@ -97,7 +97,7 @@ async fn test_actor_invoke() {
let server = TestServer::new(app.into_make_service()).unwrap(); let server = TestServer::new(app.into_make_service()).unwrap();
let invoke_resp = server let invoke_resp = server
.put(&format!("/actors/MyActor/{}/method/do_stuff", actor_id)) .put(&format!("/actors/MyActor/{actor_id}/method/do_stuff"))
.json(&json!({ "name": "foo" })) .json(&json!({ "name": "foo" }))
.await; .await;
invoke_resp.assert_status_ok(); invoke_resp.assert_status_ok();
@ -118,7 +118,7 @@ async fn test_actor_invoke() {
); );
let invoke_resp2 = server let invoke_resp2 = server
.put(&format!("/actors/MyActor/{}/method/do_stuff", actor_id)) .put(&format!("/actors/MyActor/{actor_id}/method/do_stuff"))
.json(&json!({ "name": "foo" })) .json(&json!({ "name": "foo" }))
.await; .await;
invoke_resp2.assert_status_ok(); invoke_resp2.assert_status_ok();
@ -169,19 +169,15 @@ async fn test_actor_deactivate() {
let actor_id = Uuid::new_v4().to_string(); let actor_id = Uuid::new_v4().to_string();
let invoke_resp = server let invoke_resp = server
.put(&format!("/actors/MyActor/{}/method/do_stuff", actor_id)) .put(&format!("/actors/MyActor/{actor_id}/method/do_stuff"))
.json(&json!({ "name": "foo" })) .json(&json!({ "name": "foo" }))
.await; .await;
invoke_resp.assert_status_ok(); invoke_resp.assert_status_ok();
let deactivate_resp1 = server let deactivate_resp1 = server.delete(&format!("/actors/MyActor/{actor_id}")).await;
.delete(&format!("/actors/MyActor/{}", actor_id))
.await;
deactivate_resp1.assert_status_ok(); deactivate_resp1.assert_status_ok();
let deactivate_resp2 = server let deactivate_resp2 = server.delete(&format!("/actors/MyActor/{actor_id}")).await;
.delete(&format!("/actors/MyActor/{}", actor_id))
.await;
deactivate_resp2.assert_status_not_found(); deactivate_resp2.assert_status_not_found();
assert_eq!( assert_eq!(

View File

@ -1,5 +1,5 @@
use axum::{ use axum::{
extract::{Path, State}, extract::{OriginalUri, Path, State},
http::StatusCode, http::StatusCode,
response::IntoResponse, response::IntoResponse,
routing::{delete, get, put}, routing::{delete, get, put},
@ -84,6 +84,12 @@ pub struct DaprHttpServer {
impl DaprHttpServer { impl DaprHttpServer {
/// Creates a new instance of the Dapr HTTP server with default options. /// Creates a new instance of the Dapr HTTP server with default options.
///
/// # Panics
///
/// This function panics if the Dapr Sidecar cannot be reached!
/// For a non-panicking version that allows you to handle any errors yourself, see:
/// [DaprHttpServer::try_new_with_dapr_port]
pub async fn new() -> Self { pub async fn new() -> Self {
let dapr_port: u16 = std::env::var("DAPR_GRPC_PORT") let dapr_port: u16 = std::env::var("DAPR_GRPC_PORT")
.unwrap_or("3501".into()) .unwrap_or("3501".into())
@ -92,19 +98,38 @@ impl DaprHttpServer {
Self::with_dapr_port(dapr_port).await Self::with_dapr_port(dapr_port).await
} }
/// Creates a new instance of the Dapr HTTP server that connects to the Dapr sidecar on the
/// given dapr_port.
///
/// # Panics
///
/// This function panics if the Dapr Sidecar cannot be reached!
/// For a non-panicking version that allows you to handle any errors yourself, see:
/// [DaprHttpServer::try_new_with_dapr_port]
pub async fn with_dapr_port(dapr_port: u16) -> Self { pub async fn with_dapr_port(dapr_port: u16) -> Self {
let dapr_addr = format!("https://127.0.0.1:{}", dapr_port); match Self::try_new_with_dapr_port(dapr_port).await {
let cc = match TonicClient::connect(dapr_addr).await {
Ok(c) => c, Ok(c) => c,
Err(err) => panic!("failed to connect to dapr: {}", err), Err(err) => panic!("failed to connect to dapr: {err}"),
}; }
}
/// Creates a new instance of the Dapr HTTP server that connects to the Dapr sidecar on the
/// given dapr_port.
///
/// In contrast to the other functions that create a DaprHttpServer, this function does
/// not panic, but instead returns a Result.
pub async fn try_new_with_dapr_port(
dapr_port: u16,
) -> Result<Self, Box<dyn std::error::Error>> {
let dapr_addr = format!("https://127.0.0.1:{dapr_port}");
let cc = TonicClient::connect(dapr_addr).await?;
let rt = ActorRuntime::new(cc); let rt = ActorRuntime::new(cc);
DaprHttpServer { Ok(DaprHttpServer {
actor_runtime: Arc::new(rt), actor_runtime: Arc::new(rt),
shutdown_signal: None, shutdown_signal: None,
} })
} }
pub fn with_graceful_shutdown<F>(self, signal: F) -> Self pub fn with_graceful_shutdown<F>(self, signal: F) -> Self
@ -138,7 +163,7 @@ impl DaprHttpServer {
.unwrap_or(8080); .unwrap_or(8080);
let address = format!("127.0.0.1:{}", port.unwrap_or(default_port)); let address = format!("127.0.0.1:{}", port.unwrap_or(default_port));
let listener = TcpListener::bind(address).await.unwrap(); let listener = TcpListener::bind(address).await?;
let server = axum::serve(listener, app.into_make_service()); let server = axum::serve(listener, app.into_make_service());
@ -182,7 +207,8 @@ impl DaprHttpServer {
.route( .route(
"/actors/:actor_type/:actor_id/method/timer/:timer_name", "/actors/:actor_type/:actor_id/method/timer/:timer_name",
put(invoke_timer).with_state(rt.clone()), put(invoke_timer).with_state(rt.clone()),
); )
.fallback(fallback_handler);
self.actor_runtime self.actor_runtime
.configure_method_routes(app, rt.clone()) .configure_method_routes(app, rt.clone())
@ -190,6 +216,14 @@ impl DaprHttpServer {
} }
} }
async fn fallback_handler(OriginalUri(uri): OriginalUri) -> impl IntoResponse {
log::warn!("Returning 404 for request: {uri}");
(
StatusCode::NOT_FOUND,
format!("The URI '{uri}' could not be found!"),
)
}
async fn health_check() -> impl IntoResponse { async fn health_check() -> impl IntoResponse {
log::debug!("recieved health check request"); log::debug!("recieved health check request");
StatusCode::OK StatusCode::OK
@ -210,11 +244,11 @@ async fn deactivate_actor(
match runtime.deactivate_actor(&actor_type, &actor_id).await { match runtime.deactivate_actor(&actor_type, &actor_id).await {
Ok(_) => StatusCode::OK, Ok(_) => StatusCode::OK,
Err(err) => { Err(err) => {
log::error!("invoke_actor: {:?}", err); log::error!("invoke_actor: {err:?}");
match err { match err {
super::actor::ActorError::ActorNotFound => StatusCode::NOT_FOUND, super::actor::ActorError::ActorNotFound => StatusCode::NOT_FOUND,
_ => { _ => {
log::error!("deactivate_actor: {:?}", err); log::error!("deactivate_actor: {err:?}");
StatusCode::INTERNAL_SERVER_ERROR StatusCode::INTERNAL_SERVER_ERROR
} }
} }
@ -227,13 +261,7 @@ async fn invoke_reminder(
Path((actor_type, actor_id, reminder_name)): Path<(String, String, String)>, Path((actor_type, actor_id, reminder_name)): Path<(String, String, String)>,
Json(payload): Json<ReminderPayload>, Json(payload): Json<ReminderPayload>,
) -> impl IntoResponse { ) -> impl IntoResponse {
log::debug!( log::debug!("invoke_reminder: {actor_type} {actor_id} {reminder_name} {payload:?}");
"invoke_reminder: {} {} {} {:?}",
actor_type,
actor_id,
reminder_name,
payload
);
match runtime match runtime
.invoke_reminder( .invoke_reminder(
@ -246,11 +274,11 @@ async fn invoke_reminder(
{ {
Ok(_output) => StatusCode::OK, Ok(_output) => StatusCode::OK,
Err(err) => { Err(err) => {
log::error!("invoke_actor: {:?}", err); log::error!("invoke_actor: {err:?}");
match err { match err {
super::actor::ActorError::ActorNotFound => StatusCode::NOT_FOUND, super::actor::ActorError::ActorNotFound => StatusCode::NOT_FOUND,
_ => { _ => {
log::error!("invoke_reminder: {:?}", err); log::error!("invoke_reminder: {err:?}");
StatusCode::INTERNAL_SERVER_ERROR StatusCode::INTERNAL_SERVER_ERROR
} }
} }
@ -263,13 +291,7 @@ async fn invoke_timer(
Path((actor_type, actor_id, timer_name)): Path<(String, String, String)>, Path((actor_type, actor_id, timer_name)): Path<(String, String, String)>,
Json(payload): Json<TimerPayload>, Json(payload): Json<TimerPayload>,
) -> impl IntoResponse { ) -> impl IntoResponse {
log::debug!( log::debug!("invoke_timer: {actor_type} {actor_id} {timer_name}, {payload:?}");
"invoke_timer: {} {} {}, {:?}",
actor_type,
actor_id,
timer_name,
payload
);
match runtime match runtime
.invoke_timer( .invoke_timer(
@ -282,11 +304,11 @@ async fn invoke_timer(
{ {
Ok(_output) => StatusCode::OK, Ok(_output) => StatusCode::OK,
Err(err) => { Err(err) => {
log::error!("invoke_actor: {:?}", err); log::error!("invoke_actor: {err:?}");
match err { match err {
super::actor::ActorError::ActorNotFound => StatusCode::NOT_FOUND, super::actor::ActorError::ActorNotFound => StatusCode::NOT_FOUND,
_ => { _ => {
log::error!("invoke_timer: {:?}", err); log::error!("invoke_timer: {err:?}");
StatusCode::INTERNAL_SERVER_ERROR StatusCode::INTERNAL_SERVER_ERROR
} }
} }

View File

@ -28,14 +28,14 @@ where
let bytes = match axum::body::Bytes::from_request(req, state).await { let bytes = match axum::body::Bytes::from_request(req, state).await {
Ok(bytes) => bytes, Ok(bytes) => bytes,
Err(e) => { Err(e) => {
log::error!("Error getting bytes: {}", e); log::error!("Error getting bytes: {e}");
return Err(JsonRejection::JsonError(e.to_string())); return Err(JsonRejection::JsonError(e.to_string()));
} }
}; };
let value = match serde_json::from_slice::<T>(&bytes) { let value = match serde_json::from_slice::<T>(&bytes) {
Ok(value) => value, Ok(value) => value,
Err(e) => { Err(e) => {
log::error!("Error deserializing JSON: {}", e); log::error!("Error deserializing JSON: {e}");
return Err(JsonRejection::JsonError(e.to_string())); return Err(JsonRejection::JsonError(e.to_string()));
} }
}; };

View File

@ -14,7 +14,8 @@ This allows separation of roles and expertise between maintainers, and makes it
## Writing Rust SDK docs ## Writing Rust SDK docs
To get up and running to write Go SDK docs, visit the [docs repo](https://github.com/dapr/docs) to initialize your environment. It will clone both the docs repo and this repo, so you can make changes and see it rendered within the site instantly, as well as commit and PR into this repo. To get up and running to write Rust SDK docs, visit the [docs repo](https://github.com/dapr/docs) to initialize your
environment. It will clone both the docs repo and this repo, so you can make changes and see it rendered within the site instantly, as well as commit and PR into this repo.
Make sure to read the [docs contributing guide](https://docs.dapr.io/contributing/contributing-docs/) for information on style/semantics/etc. Make sure to read the [docs contributing guide](https://docs.dapr.io/contributing/contributing-docs/) for information on style/semantics/etc.

View File

@ -12,7 +12,7 @@ When contributing to the [Rust SDK](https://github.com/dapr/rust-sdk) the follow
The `examples` directory contains code samples for users to run to try out specific functionality of the various Rust SDK packages and extensions. It also hosts component examples used for validation. When writing new and updated samples keep in mind: The `examples` directory contains code samples for users to run to try out specific functionality of the various Rust SDK packages and extensions. It also hosts component examples used for validation. When writing new and updated samples keep in mind:
- All examples should be runnable on Windows, Linux, and MacOS. While Rust code is consistent among operating systems aside from minor OS-feature gating, any pre/post example commands should provide options through [codetabs]({{< ref "contributing-docs.md#tabbed-content" >}}) - All examples should be runnable on Windows, Linux, and MacOS. While Rust code is consistent among operating systems aside from minor OS-feature gating, any pre/post example commands should provide options through [tabpane]({{% ref "contributing-docs.md#tabbed-content" %}})
- Contain steps to download/install any required pre-requisites. Someone coming in with a fresh OS install should be able to start on the example and complete it without an error. Links to external download pages are fine. - Contain steps to download/install any required pre-requisites. Someone coming in with a fresh OS install should be able to start on the example and complete it without an error. Links to external download pages are fine.
- Examples should be pass validation and include mechanical markdown steps and be added to the validation workflow [TBA](#) - Examples should be pass validation and include mechanical markdown steps and be added to the validation workflow [TBA](#)
@ -20,7 +20,7 @@ The `examples` directory contains code samples for users to run to try out speci
The `daprdocs` directory contains the markdown files that are rendered into the [Dapr Docs](https://docs.dapr.io) website. When the documentation website is built this repo is cloned and configured so that its contents are rendered with the docs content. When writing docs keep in mind: The `daprdocs` directory contains the markdown files that are rendered into the [Dapr Docs](https://docs.dapr.io) website. When the documentation website is built this repo is cloned and configured so that its contents are rendered with the docs content. When writing docs keep in mind:
- All rules in the [docs guide]({{< ref contributing-docs.md >}}) should be followed in addition to these. - All rules in the [docs guide]({{% ref contributing-docs.md %}}) should be followed in addition to these.
- All files and directories should be prefixed with `rust-` to ensure all file/directory names are globally unique across all Dapr documentation. - All files and directories should be prefixed with `rust-` to ensure all file/directory names are globally unique across all Dapr documentation.
## Update Protobufs ## Update Protobufs

View File

@ -22,6 +22,6 @@ A client library to help build Dapr applications using Rust. This client is targ
{{< card title="**Client**">}} {{< card title="**Client**">}}
Use the Rust Client SDK for invoking public Dapr APIs Use the Rust Client SDK for invoking public Dapr APIs
[**Learn more about the Rust Client SDK**]({{< ref rust-client >}}) [**Learn more about the Rust Client SDK**]({{% ref rust-client %}})
{{< /card >}} {{< /card >}}
{{< /cardpane >}} {{< /cardpane >}}

View File

@ -17,8 +17,8 @@ stable release and will likely involve breaking changes.
## Prerequisites ## Prerequisites
- [Dapr CLI]({{< ref install-dapr-cli.md >}}) installed - [Dapr CLI]({{% ref install-dapr-cli.md %}}) installed
- Initialized [Dapr environment]({{< ref install-dapr-selfhost.md >}}) - Initialized [Dapr environment]({{% ref install-dapr-selfhost.md %}})
- [Rust installed](https://www.rust-lang.org/tools/install) - [Rust installed](https://www.rust-lang.org/tools/install)
## Import the client package ## Import the client package
@ -34,7 +34,7 @@ dapr = "0.16.0"
You can either reference `dapr::Client` or bind the full path to a new name as follows: You can either reference `dapr::Client` or bind the full path to a new name as follows:
```rust ```rust
use dapr::Client as DaprClient use dapr::Client as DaprClient;
``` ```
## Instantiating the Dapr client ## Instantiating the Dapr client
@ -43,13 +43,19 @@ use dapr::Client as DaprClient
let addr = "https://127.0.0.1".to_string(); let addr = "https://127.0.0.1".to_string();
let mut client = dapr::Client::<dapr::client::TonicClient>::connect(addr, let mut client = dapr::Client::<dapr::client::TonicClient>::connect(addr,
port).await?; port).await?;
```
Alternatively if you would like to specify a custom port, this can be done by using this connect method:
```rust
let mut client = dapr::Client::<dapr::client::TonicClient>::connect_with_port(addr, "3500".to_string()).await?;
``` ```
## Building blocks ## Building blocks
The Rust SDK allows you to interface with the The Rust SDK allows you to interface with the
[Dapr building blocks]({{< ref building-blocks >}}). [Dapr building blocks]({{% ref building-blocks %}}).
### Service Invocation (gRPC) ### Service Invocation (gRPC)
@ -66,7 +72,7 @@ let response = client
``` ```
For a full guide on service invocation, visit For a full guide on service invocation, visit
[How-To: Invoke a service]({{< ref howto-invoke-discover-services.md >}}). [How-To: Invoke a service]({{% ref howto-invoke-discover-services.md %}}).
### State Management ### State Management
@ -97,7 +103,7 @@ client
Multiple states can be sent with the `save_bulk_states` method. Multiple states can be sent with the `save_bulk_states` method.
For a full guide on state management, visit For a full guide on state management, visit
[How-To: Save & get state]({{< ref howto-get-save-state.md >}}). [How-To: Save & get state]({{% ref howto-get-save-state.md %}}).
### Publish Messages ### Publish Messages
@ -115,7 +121,7 @@ client
``` ```
For a full guide on pub/sub, visit For a full guide on pub/sub, visit
[How-To: Publish & subscribe]({{< ref howto-publish-subscribe.md >}}). [How-To: Publish & subscribe]({{% ref howto-publish-subscribe.md %}}).
## Related links ## Related links

View File

@ -10,7 +10,6 @@ rust-version.workspace = true
[dependencies] [dependencies]
async-trait = { workspace = true } async-trait = { workspace = true }
base64 = "0.22"
dapr = { path = "../dapr" } dapr = { path = "../dapr" }
dapr-macros = { path = "../dapr-macros" } dapr-macros = { path = "../dapr-macros" }
env_logger = "0.11" env_logger = "0.11"

View File

@ -14,7 +14,7 @@ pub struct MyRequest {
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// TODO: Handle this issue in the sdk // TODO: Handle this issue in the sdk
// Introduce delay so that dapr grpc port is assigned before app tries to connect // Introduce delay so that dapr grpc port is assigned before app tries to connect
std::thread::sleep(std::time::Duration::new(2, 0)); tokio::time::sleep(std::time::Duration::new(2, 0)).await;
// Define the Dapr address // Define the Dapr address
let addr = "https://127.0.0.1".to_string(); let addr = "https://127.0.0.1".to_string();
@ -30,7 +30,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.invoke_actor("MyActor", "a1", "do_stuff", data, None) .invoke_actor("MyActor", "a1", "do_stuff", data, None)
.await; .await;
println!("Response: {:#?}", resp); println!("Response: {resp:#?}");
Ok(()) Ok(())
} }

View File

@ -31,7 +31,7 @@ impl MyActor {
println!("doing stuff with {}", req.name); println!("doing stuff with {}", req.name);
let mut dapr = self.client.clone(); let mut dapr = self.client.clone();
let r = dapr.get_actor_state("key1").await.unwrap(); let r = dapr.get_actor_state("key1").await.unwrap();
println!("get_actor_state {:?}", r); println!("get_actor_state {r:?}");
Json(MyResponse { available: true }) Json(MyResponse { available: true })
} }
} }

View File

@ -61,7 +61,7 @@ impl AppCallback for AppCallbackService {
let name = &r.name; let name = &r.name;
let data = &r.data; let data = &r.data;
let message = String::from_utf8_lossy(&data); let message = String::from_utf8_lossy(data);
println!("Binding Name: {}", &name); println!("Binding Name: {}", &name);
println!("Message: {}", &message); println!("Message: {}", &message);
@ -75,7 +75,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let callback_service = AppCallbackService::default(); let callback_service = AppCallbackService::default();
println!("AppCallback server listening on: {}", addr); println!("AppCallback server listening on: {addr}");
// Create a gRPC server with the callback_service. // Create a gRPC server with the callback_service.
Server::builder() Server::builder()

View File

@ -1,10 +1,10 @@
use std::{collections::HashMap, thread, time::Duration}; use std::{collections::HashMap, time::Duration};
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// TODO: Handle this issue in the sdk // TODO: Handle this issue in the sdk
// Introduce delay so that dapr grpc port is assigned before app tries to connect // Introduce delay so that dapr grpc port is assigned before app tries to connect
thread::sleep(Duration::from_secs(2)); tokio::time::sleep(Duration::from_secs(2)).await;
// Get the Dapr port and create a connection // Get the Dapr port and create a connection
let addr = "https://127.0.0.1".to_string(); let addr = "https://127.0.0.1".to_string();

View File

@ -2,7 +2,7 @@
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// TODO: Handle this issue in the sdk // TODO: Handle this issue in the sdk
// Introduce delay so that dapr grpc port is assigned before app tries to connect // Introduce delay so that dapr grpc port is assigned before app tries to connect
std::thread::sleep(std::time::Duration::new(2, 0)); tokio::time::sleep(std::time::Duration::new(2, 0)).await;
// Set the Dapr address // Set the Dapr address
let addr = "https://127.0.0.1".to_string(); let addr = "https://127.0.0.1".to_string();

View File

@ -7,7 +7,7 @@ type DaprClient = dapr::Client<dapr::client::TonicClient>;
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// TODO: Handle this issue in the sdk // TODO: Handle this issue in the sdk
// Introduce delay so that dapr grpc port is assigned before app tries to connect // Introduce delay so that dapr grpc port is assigned before app tries to connect
std::thread::sleep(std::time::Duration::new(2, 0)); tokio::time::sleep(std::time::Duration::new(2, 0)).await;
// Set the Dapr address // Set the Dapr address
let addr = "https://127.0.0.1".to_string(); let addr = "https://127.0.0.1".to_string();
@ -19,14 +19,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// get key-value pair in the state store // get key-value pair in the state store
let response = client let response = client
.get_configuration(CONFIGSTORE_NAME, vec![(&key)], None) .get_configuration(CONFIGSTORE_NAME, vec![&key], None)
.await?; .await?;
let val = response.items.get("hello").unwrap(); let val = response.items.get("hello").unwrap();
println!("Configuration value: {val:?}"); println!("Configuration value: {val:?}");
// Subscribe for configuration changes // Subscribe for configuration changes
let mut stream = client let mut stream = client
.subscribe_configuration(CONFIGSTORE_NAME, vec![(&key)], None) .subscribe_configuration(CONFIGSTORE_NAME, vec![&key], None)
.await?; .await?;
let mut subscription_id = String::new(); let mut subscription_id = String::new();
@ -52,7 +52,7 @@ async fn unsubscribe(client: &mut DaprClient, subscription_id: &str) {
.await .await
{ {
Ok(_) => println!("App unsubscribed from config changes"), Ok(_) => println!("App unsubscribed from config changes"),
Err(e) => println!("Error unsubscribing from config updates: {}", e), Err(e) => println!("Error unsubscribing from config updates: {e}"),
} }
std::process::exit(0); std::process::exit(0);
} }

View File

@ -1,5 +1,4 @@
use dapr::client::{ConversationInputBuilder, ConversationRequestBuilder}; use dapr::client::{ConversationInputBuilder, ConversationRequestBuilder};
use std::thread;
use std::time::Duration; use std::time::Duration;
type DaprClient = dapr::Client<dapr::client::TonicClient>; type DaprClient = dapr::Client<dapr::client::TonicClient>;
@ -7,12 +6,13 @@ type DaprClient = dapr::Client<dapr::client::TonicClient>;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Sleep to allow for the server to become available // Sleep to allow for the server to become available
thread::sleep(Duration::from_secs(5)); tokio::time::sleep(Duration::from_secs(5)).await;
// Set the Dapr address // Set the Dapr address
let address = "https://127.0.0.1".to_string(); let address = "https://127.0.0.1".to_string();
let port = "3500".to_string();
let mut client = DaprClient::connect(address).await?; let mut client = DaprClient::connect_with_port(address, port).await?;
let input = ConversationInputBuilder::new("hello world").build(); let input = ConversationInputBuilder::new("hello world").build();
@ -21,7 +21,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let request = let request =
ConversationRequestBuilder::new(conversation_component, vec![input.clone()]).build(); ConversationRequestBuilder::new(conversation_component, vec![input.clone()]).build();
println!("conversation input: {:?}", input.message); println!("conversation input: {:?}", input.content);
let response = client.converse_alpha1(request).await?; let response = client.converse_alpha1(request).await?;

View File

@ -1,4 +1,4 @@
use std::{thread, time::Duration}; use std::time::Duration;
use hello_world::{greeter_client::GreeterClient, HelloRequest}; use hello_world::{greeter_client::GreeterClient, HelloRequest};
@ -11,11 +11,11 @@ pub mod hello_world {
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Sleep to allow for the server to become available // Sleep to allow for the server to become available
thread::sleep(Duration::from_secs(5)); tokio::time::sleep(Duration::from_secs(5)).await;
// Get the Dapr port and create a connection // Get the Dapr port and create a connection
let port: u16 = std::env::var("DAPR_GRPC_PORT").unwrap().parse().unwrap(); let port: u16 = std::env::var("DAPR_GRPC_PORT").unwrap().parse().unwrap();
let address = format!("https://127.0.0.1:{}", port); let address = format!("https://127.0.0.1:{port}");
let mut client = GreeterClient::connect(address).await?; let mut client = GreeterClient::connect(address).await?;
@ -31,7 +31,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let response = client.say_hello(request).await.unwrap(); let response = client.say_hello(request).await.unwrap();
let hello_reply = response.into_inner(); let hello_reply = response.into_inner();
println!("Response: {:#?}", hello_reply); println!("Response: {hello_reply:#?}");
Ok(()) Ok(())
} }

View File

@ -33,7 +33,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let greeter_service = GreeterService::default(); let greeter_service = GreeterService::default();
println!("AppCallback server listening on: {}", server_address); println!("AppCallback server listening on: {server_address}");
// Create a gRPC server with the callback_service. // Create a gRPC server with the callback_service.
Server::builder() Server::builder()
.add_service(GreeterServer::new(greeter_service)) .add_service(GreeterServer::new(greeter_service))

View File

@ -1,5 +1,5 @@
use crate::hello_world::HelloReply; use crate::hello_world::HelloReply;
use std::{thread, time::Duration}; use std::time::Duration;
use prost::Message; use prost::Message;
@ -12,7 +12,7 @@ type DaprClient = dapr::Client<dapr::client::TonicClient>;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Sleep to allow for the server to become available // Sleep to allow for the server to become available
thread::sleep(Duration::from_secs(5)); tokio::time::sleep(Duration::from_secs(5)).await;
// Set the Dapr address // Set the Dapr address
let address = "https://127.0.0.1".to_string(); let address = "https://127.0.0.1".to_string();
@ -39,7 +39,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Message: {:#?}", &resp.message); println!("Message: {:#?}", &resp.message);
}; };
println!("Response: {:#?}", response); println!("Response: {response:#?}");
Ok(()) Ok(())
} }

View File

@ -97,7 +97,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let callback_service = AppCallbackService {}; let callback_service = AppCallbackService {};
println!("AppCallback server listening on: {}", server_address); println!("AppCallback server listening on: {server_address}");
// Create a gRPC server with the callback_service. // Create a gRPC server with the callback_service.
Server::builder() Server::builder()
.add_service(AppCallbackServer::new(callback_service)) .add_service(AppCallbackServer::new(callback_service))

View File

@ -44,7 +44,7 @@ async fn backup_job_handler(request: JobEventRequest) -> Result<JobEventResponse
// Deserialize the decoded value into a Backup struct // Deserialize the decoded value into a Backup struct
let backup_val: Backup = serde_json::from_slice(&request.data.unwrap().value).unwrap(); let backup_val: Backup = serde_json::from_slice(&request.data.unwrap().value).unwrap();
println!("job received: {:?}", backup_val); println!("job received: {backup_val:?}");
} }
Ok(JobEventResponse::default()) Ok(JobEventResponse::default())
@ -88,9 +88,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client_addr = "https://127.0.0.1".to_string(); let client_addr = "https://127.0.0.1".to_string();
let port: u16 = std::env::var("DAPR_GRPC_PORT")?.parse()?; let port: u16 = std::env::var("DAPR_GRPC_PORT")?.parse()?;
let address = format!("{}:{}", client_addr, port); let address = format!("{client_addr}:{port}");
println!("attempting to create a dapr client: {}", address); println!("attempting to create a dapr client: {address}");
// Create the client // Create the client
let mut client = DaprClient::connect(client_addr).await?; let mut client = DaprClient::connect(client_addr).await?;
@ -127,7 +127,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let get_resp_backup: Backup = let get_resp_backup: Backup =
serde_json::from_slice(&get_resp.clone().job.unwrap().data.unwrap().value).unwrap(); serde_json::from_slice(&get_resp.clone().job.unwrap().data.unwrap().value).unwrap();
println!("job retrieved: {:?}", get_resp_backup); println!("job retrieved: {get_resp_backup:?}");
let _delete_resp = client.delete_job_alpha1("prod-db-backup").await?; let _delete_resp = client.delete_job_alpha1("prod-db-backup").await?;

View File

@ -1,4 +1,4 @@
use std::{collections::HashMap, thread, time::Duration}; use std::{collections::HashMap, time::Duration};
use tokio::time; use tokio::time;
@ -21,7 +21,7 @@ struct Refund {
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// TODO: Handle this issue in the sdk // TODO: Handle this issue in the sdk
// Introduce delay so that dapr grpc port is assigned before app tries to connect // Introduce delay so that dapr grpc port is assigned before app tries to connect
thread::sleep(Duration::from_secs(2)); tokio::time::sleep(Duration::from_secs(2)).await;
// Set address for Dapr connection // Set address for Dapr connection
let addr = "https://127.0.0.1".to_string(); let addr = "https://127.0.0.1".to_string();
@ -45,7 +45,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
for count in 0..10 { for count in 0..10 {
let order = Order { let order = Order {
order_number: count, order_number: count,
order_details: format!("Count is {}", count), order_details: format!("Count is {count}"),
}; };
// message metadata // message metadata
let mut metadata = HashMap::<String, String>::new(); let mut metadata = HashMap::<String, String>::new();

View File

@ -18,12 +18,12 @@ struct Refund {
#[topic(pub_sub_name = "pubsub", topic = "A")] #[topic(pub_sub_name = "pubsub", topic = "A")]
async fn handle_a_event(order: Order) { async fn handle_a_event(order: Order) {
println!("Topic A - {:#?}", order) println!("Topic A - {order:#?}")
} }
#[topic(pub_sub_name = "pubsub", topic = "B")] #[topic(pub_sub_name = "pubsub", topic = "B")]
async fn handle_b_event(refund: Refund) { async fn handle_b_event(refund: Refund) {
println!("Topic B - {:#?}", refund) println!("Topic B - {refund:#?}")
} }
#[tokio::main] #[tokio::main]
@ -36,7 +36,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
callback_service.add_handler(HandleBEvent.get_handler()); callback_service.add_handler(HandleBEvent.get_handler());
println!("AppCallback server listening on: {}", addr); println!("AppCallback server listening on: {addr}");
// Create a gRPC server with the callback_service. // Create a gRPC server with the callback_service.
Server::builder() Server::builder()

View File

@ -3,7 +3,7 @@ use serde_json::json;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Introduce delay so that dapr grpc port is assigned before app tries to connect // Introduce delay so that dapr grpc port is assigned before app tries to connect
std::thread::sleep(std::time::Duration::new(5, 0)); tokio::time::sleep(std::time::Duration::new(5, 0)).await;
// Set the Dapr address and create a connection // Set the Dapr address and create a connection
let addr = "https://127.0.0.1".to_string(); let addr = "https://127.0.0.1".to_string();
@ -29,7 +29,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
{ {
Ok(response) => response.results, Ok(response) => response.results,
Err(e) => { Err(e) => {
println!("Error: {:?}", e); println!("Error: {e:?}");
return Ok(()); return Ok(());
} }
}; };
@ -43,7 +43,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
"value": value "value": value
})); }));
} }
println!("Query results: {:?}", results); println!("Query results: {results:?}");
Ok(()) Ok(())
} }

View File

@ -3,7 +3,7 @@ use serde_json::json;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Introduce delay so that dapr grpc port is assigned before app tries to connect // Introduce delay so that dapr grpc port is assigned before app tries to connect
std::thread::sleep(std::time::Duration::new(5, 0)); tokio::time::sleep(std::time::Duration::new(5, 0)).await;
// Set the Dapr address and create a connection // Set the Dapr address and create a connection
let addr = "https://127.0.0.1".to_string(); let addr = "https://127.0.0.1".to_string();
@ -23,7 +23,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
{ {
Ok(response) => response.results, Ok(response) => response.results,
Err(e) => { Err(e) => {
println!("Error: {:?}", e); println!("Error: {e:?}");
return Ok(()); return Ok(());
} }
}; };
@ -37,7 +37,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
"value": value "value": value
})); }));
} }
println!("Query results: {:?}", results); println!("Query results: {results:?}");
Ok(()) Ok(())
} }

View File

@ -51,16 +51,16 @@ fn proto_gen(
.map(|path| format!("{}/{}", root_dir.to_str().unwrap(), path)) .map(|path| format!("{}/{}", root_dir.to_str().unwrap(), path))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
println!("included {:?}", include_dirs); println!("included {include_dirs:?}");
let interface = interface let interface = interface
.iter() .iter()
.map(|path| format!("{}/{}", root_dir.to_str().unwrap(), path)) .map(|path| format!("{}/{}", root_dir.to_str().unwrap(), path))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
println!("interface {:?}", interface); println!("interface {interface:?}");
let out_dir = root_dir.join(out_dir); let out_dir = root_dir.join(out_dir);
println!("outdir {:?}", out_dir); println!("outdir {out_dir:?}");
tonic_build::configure() tonic_build::configure()
.build_client(build_client) .build_client(build_client)

View File

@ -694,7 +694,14 @@ message GetMetadataResponse {
string runtime_version = 8 [json_name = "runtimeVersion"]; string runtime_version = 8 [json_name = "runtimeVersion"];
repeated string enabled_features = 9 [json_name = "enabledFeatures"]; repeated string enabled_features = 9 [json_name = "enabledFeatures"];
ActorRuntime actor_runtime = 10 [json_name = "actorRuntime"]; ActorRuntime actor_runtime = 10 [json_name = "actorRuntime"];
//TODO: Cassie: probably add scheduler runtime status optional MetadataScheduler scheduler = 11 [json_name = "scheduler"];
}
// MetadataScheduler is a message that contains the list of addresses of the
// scheduler connections.
message MetadataScheduler {
// connected_addresses the list of addresses of the scheduler connections.
repeated string connected_addresses = 1;
} }
message ActorRuntime { message ActorRuntime {
@ -1319,8 +1326,8 @@ message ConversationRequest {
} }
message ConversationInput { message ConversationInput {
// The message to send to the llm // The content to send to the llm
string message = 1; string content = 1;
// The role to set for the message // The role to set for the message
optional string role = 2; optional string role = 2;
@ -1344,4 +1351,4 @@ message ConversationResponse {
// An array of results. // An array of results.
repeated ConversationResult outputs = 2; repeated ConversationResult outputs = 2;
} }