From a0cdb95d01c8057ec74632d096f599871528a272 Mon Sep 17 00:00:00 2001 From: Kai Hudalla Date: Thu, 4 Jul 2024 10:51:25 +0200 Subject: [PATCH] [#122] Make CallOptions immutable Changed CallOptions struct to only support setting fields by means of constructors, effectively making it immutable. This way we will have better control over which fields may or may not be set for the different types of messages to use the CallOptions for. Also removed the traceparent field because it should not be necessary to explicitly set it. Instead, when a UMessage is created, the current span will be looked up in the current thread/future context. --- src/communication.rs | 104 ++++------------------ src/communication/in_memory_rpc_client.rs | 32 +++---- 2 files changed, 29 insertions(+), 107 deletions(-) diff --git a/src/communication.rs b/src/communication.rs index f948c7b..da36c47 100644 --- a/src/communication.rs +++ b/src/communication.rs @@ -60,8 +60,6 @@ impl Display for RegistrationError { impl Error for RegistrationError {} -const DEFAULT_TTL: u32 = 10_000; // 10 seconds - /// General options that clients might want to specify when sending a uProtocol message. #[derive(Debug)] pub struct CallOptions { @@ -69,36 +67,35 @@ pub struct CallOptions { message_id: Option, token: Option, priority: Option, - traceparent: Option, -} - -impl Default for CallOptions { - /// Creates empty options with a TTL of 10s. - fn default() -> Self { - CallOptions { - ttl: DEFAULT_TTL, - message_id: None, - token: None, - priority: None, - traceparent: None, - } - } } impl CallOptions { - /// Creates new call options. + /// Creates new call options for an RPC Request. /// /// # Arguments /// /// * `ttl` - The message's time-to-live in milliseconds. /// * `message_id` - The identifier to use for the message or `None` to use a generated identifier. /// * `token` - The token to use for authenticating to infrastructure and service endpoints. - /// * `priority` - The message's priority or `None` to use the default priority. + /// * `priority` - The message's priority or `None` to use the default priority for RPC Requests. /// /// # Returns /// - /// `CallOption` with specified ttl value, token and priority parameters. - pub fn new( + /// Options suitable for invoking an RPC method. + /// + /// # Examples + /// + /// ```rust + /// use up_rust::{UPriority, UUID, communication::CallOptions}; + /// + /// let uuid = UUID::new(); + /// let options = CallOptions::for_rpc_request(15_000, Some(uuid.clone()), Some("token".to_string()), Some(UPriority::UPRIORITY_CS2)); + /// assert_eq!(options.ttl(), 15_000); + /// assert_eq!(options.message_id(), Some(uuid)); + /// assert_eq!(options.token(), Some("token".to_string())); + /// assert_eq!(options.priority(), Some(UPriority::UPRIORITY_CS2)); + /// ``` + pub fn for_rpc_request( ttl: u32, message_id: Option, token: Option, @@ -109,95 +106,28 @@ impl CallOptions { message_id, token, priority, - traceparent: None, } } - /// Sets the message's time-to-live. - /// - /// # Arguments - /// - /// * `ttl` - The time-to-live in milliseconds. - /// - /// # Returns - /// - /// `CallOption` with specified ttl value. - pub fn with_ttl(&mut self, ttl: u32) -> &mut Self { - self.ttl = ttl; - self - } - /// Gets the message's time-to-live in milliseconds. pub fn ttl(&self) -> u32 { self.ttl } - /// Sets the identifier to use for the message. - /// - /// # Returns - /// - /// `CallOption` with specified reqid value. - pub fn with_message_id(&mut self, message_id: UUID) -> &mut Self { - self.message_id = Some(message_id); - self - } - /// Gets the identifier to use for the message. pub fn message_id(&self) -> Option { self.message_id.clone() } - /// Sets the token to use for authenticating to infrastructure and service endpoints. - /// - /// # Returns - /// - /// `CallOption` with specified token value. - pub fn with_token>(&mut self, token: T) -> &mut Self { - self.token = Some(token.into()); - self - } - /// Gets the token to use for authenticating to infrastructure and service endpoints. pub fn token(&self) -> Option { self.token.clone() } - /// Sets the message's priority. - /// - /// If not set explicitly, the default priority for RPC calls will be used. - /// - /// # Returns - /// - /// `CallOption` with specified priority value. - pub fn with_priority(&mut self, priority: UPriority) -> &mut Self { - self.priority = Some(priority); - self - } - /// Gets the message's priority. pub fn priority(&self) -> Option { self.priority } - - /// Sets the W3C Trace Context that the message is part of. - /// - /// # Arguments - /// - /// * `traceparent` - The [traceparent](https://w3c.github.io/trace-context/#traceparent-header) value identifying the trace context. - /// - /// # Returns - /// - /// `CallOption` with specified priority value. - pub fn with_traceparent>(&mut self, traceparent: T) -> &mut Self { - self.traceparent = Some(traceparent.into()); - self - } - - /// Gets the [traceparent](https://w3c.github.io/trace-context/#traceparent-header) value identifying the trace context that - /// the message is part of. - pub fn traceparent(&self) -> Option { - self.traceparent.clone() - } } /// A wrapper around (raw) message payload data and the corresponding payload format. diff --git a/src/communication/in_memory_rpc_client.rs b/src/communication/in_memory_rpc_client.rs index a505e00..b449ed2 100644 --- a/src/communication/in_memory_rpc_client.rs +++ b/src/communication/in_memory_rpc_client.rs @@ -220,9 +220,6 @@ impl RpcClient for InMemoryRpcClient { if let Some(priority) = call_options.priority() { builder.with_priority(priority); } - if let Some(traceparent) = call_options.traceparent() { - builder.with_traceparent(traceparent); - } let rpc_request_message = if let Some(pl) = payload { let format = pl.payload_format(); builder.build_with_payload(pl.payload(), format) @@ -348,8 +345,8 @@ mod tests { // WHEN invoking a remote service operation let message_id = UUID::build(); - let mut call_options = CallOptions::default(); - call_options.with_message_id(message_id.clone()); + let call_options = + CallOptions::for_rpc_request(5_000, Some(message_id.clone()), None, None); let response = client .invoke_method(service_method_uri(), call_options, None) .await; @@ -362,14 +359,12 @@ mod tests { #[tokio::test] async fn test_invoke_method_succeeds() { let message_id = UUID::build(); - let traceparent = "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"; - let mut call_options = CallOptions::default(); - call_options - .with_message_id(message_id.clone()) - .with_priority(crate::UPriority::UPRIORITY_CS6) - .with_ttl(5_000) - .with_token("my_token") - .with_traceparent(traceparent); + let call_options = CallOptions::for_rpc_request( + 5_000, + Some(message_id.clone()), + Some("my_token".to_string()), + Some(crate::UPriority::UPRIORITY_CS6), + ); // GIVEN an RPC client let listener_ref: Arc>>> = Arc::new(Mutex::new(None)); @@ -395,7 +390,6 @@ mod tests { && attribs.priority.value() == UPriority::UPRIORITY_CS6.value() && attribs.ttl == Some(5_000) && attribs.token == Some("my_token".to_string()) - && attribs.traceparent == Some(traceparent.to_string()) }) }) .returning(move |request_message| { @@ -472,10 +466,10 @@ mod tests { // WHEN invoking the remote service operation let message_id = UUID::build(); - let mut call_options = CallOptions::default(); - call_options.with_message_id(message_id.clone()); + let call_options = + CallOptions::for_rpc_request(5_000, Some(message_id.clone()), None, None); let response = client - .invoke_method(service_method_uri(), CallOptions::default(), None) + .invoke_method(service_method_uri(), call_options, None) .await; // THEN the invocation has failed with the error returned from the service @@ -501,9 +495,7 @@ mod tests { // WHEN invoking the remote service operation let message_id = UUID::build(); - let mut call_options = CallOptions::default(); - call_options.with_ttl(20); - call_options.with_message_id(message_id.clone()); + let call_options = CallOptions::for_rpc_request(20, Some(message_id.clone()), None, None); let response = client .invoke_method(service_method_uri(), call_options, None) .await;