From 3e272c8506246d48713c18d9a49189c38a4ecb4b Mon Sep 17 00:00:00 2001 From: Robert Cao Date: Tue, 5 May 2026 19:12:00 -0500 Subject: [PATCH 1/2] expose dns load balancing options through c bridge --- .../include/temporal-sdk-core-c-bridge.h | 6 +++ crates/sdk-core-c-bridge/src/client.rs | 42 +++++++++++++++---- crates/sdk-core-c-bridge/src/tests/context.rs | 12 +++++- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h b/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h index 11178167f..d84993bf5 100644 --- a/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +++ b/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h @@ -145,6 +145,11 @@ typedef struct TemporalCoreClientHttpConnectProxyOptions { typedef void (*TemporalCoreClientGrpcOverrideCallback)(struct TemporalCoreClientGrpcOverrideRequest *request, void *user_data); +typedef struct TemporalCoreClientDnsLoadBalancingOptions { + bool enabled; + uint64_t resolution_interval_millis; +} TemporalCoreClientDnsLoadBalancingOptions; + typedef struct TemporalCoreConnectionOptions { struct TemporalCoreByteArrayRef target_url; struct TemporalCoreByteArrayRef client_name; @@ -172,6 +177,7 @@ typedef struct TemporalCoreConnectionOptions { * Optional user data passed to each callback call. */ void *grpc_override_callback_user_data; + const struct TemporalCoreClientDnsLoadBalancingOptions *dns_load_balancing_options; } TemporalCoreConnectionOptions; typedef struct TemporalCoreByteArray { diff --git a/crates/sdk-core-c-bridge/src/client.rs b/crates/sdk-core-c-bridge/src/client.rs index b1bdfc94a..c7dbc2f9d 100644 --- a/crates/sdk-core-c-bridge/src/client.rs +++ b/crates/sdk-core-c-bridge/src/client.rs @@ -45,6 +45,7 @@ pub struct ConnectionOptions { pub grpc_override_callback: ClientGrpcOverrideCallback, /// Optional user data passed to each callback call. pub grpc_override_callback_user_data: *mut libc::c_void, + pub dns_load_balancing_options: *const ClientDnsLoadBalancingOptions, } #[repr(C)] @@ -78,6 +79,12 @@ pub struct ClientHttpConnectProxyOptions { pub password: ByteArrayRef, } +#[repr(C)] +pub struct ClientDnsLoadBalancingOptions { + pub enabled: bool, + pub resolution_interval_millis: u64, +} + type CoreConnection = temporalio_client::Connection; pub struct Connection { @@ -130,8 +137,8 @@ pub extern "C" fn temporal_core_client_connect( cb, options.grpc_override_callback_user_data, )); - connection_options.dns_load_balancing = None; } + // Spawn async call let user_data = UserDataHandle(user_data); connection_options.metrics_meter = runtime.core.telemetry().get_temporal_metric_meter(); @@ -1362,6 +1369,20 @@ impl TryFrom<&ConnectionOptions> for temporalio_client::ConnectionOptions { let http_connect_proxy = unsafe { opts.http_connect_proxy_options.as_ref() }.map(Into::into); + let dns_load_balancing = if http_connect_proxy.is_some() + || opts.grpc_override_callback.is_some() + { + None + } else { + unsafe { opts.dns_load_balancing_options.as_ref() }.map_or( + // Keep backwards compatibility. + // Before DnsLoadBalancingOptions was exposed through the C bridge, + // this was the default. + Some(temporalio_client::DnsLoadBalancingOptions::default()), + |c| c.into(), + ) + }; + Ok( temporalio_client::ConnectionOptions::new(Url::parse(opts.target_url.to_str())?) .client_name(opts.client_name.to_string()) @@ -1375,12 +1396,8 @@ impl TryFrom<&ConnectionOptions> for temporalio_client::ConnectionOptions { .maybe_headers(headers) .maybe_binary_headers(binary_headers) .maybe_api_key(api_key) - .maybe_http_connect_proxy(http_connect_proxy.clone()) - .dns_load_balancing(if http_connect_proxy.is_some() { - None - } else { - Some(temporalio_client::DnsLoadBalancingOptions::default()) - }) + .maybe_http_connect_proxy(http_connect_proxy) + .dns_load_balancing(dns_load_balancing) .maybe_tls_options(tls_cfg) .build(), ) @@ -1441,6 +1458,17 @@ impl From<&ClientKeepAliveOptions> for temporalio_client::ClientKeepAliveOptions } } +impl From<&ClientDnsLoadBalancingOptions> for Option { + fn from(opts: &ClientDnsLoadBalancingOptions) -> Self { + if !opts.enabled { + return None; + } + let mut out = temporalio_client::DnsLoadBalancingOptions::default(); + out.resolution_interval = Duration::from_millis(opts.resolution_interval_millis); + Some(out) + } +} + impl From<&ClientHttpConnectProxyOptions> for temporalio_client::proxy::HttpConnectProxyOptions { fn from(opts: &ClientHttpConnectProxyOptions) -> Self { temporalio_client::proxy::HttpConnectProxyOptions { diff --git a/crates/sdk-core-c-bridge/src/tests/context.rs b/crates/sdk-core-c-bridge/src/tests/context.rs index 8a9c355f0..a0918d095 100644 --- a/crates/sdk-core-c-bridge/src/tests/context.rs +++ b/crates/sdk-core-c-bridge/src/tests/context.rs @@ -1,7 +1,7 @@ use crate::{ client::{ - ClientHttpConnectProxyOptions, ClientKeepAliveOptions, ClientRetryOptions, - ClientTlsOptions, Connection, GrpcMetadataHolder, RpcCallOptions, + ClientDnsLoadBalancingOptions, ClientHttpConnectProxyOptions, ClientKeepAliveOptions, + ClientRetryOptions, ClientTlsOptions, Connection, GrpcMetadataHolder, RpcCallOptions, temporal_core_client_connect, temporal_core_client_free, temporal_core_client_rpc_call, }, runtime::{ @@ -340,6 +340,13 @@ impl Context { }) }); + let dns_load_balancing_options = options.dns_load_balancing.as_ref().map(|dns| { + Box::new(ClientDnsLoadBalancingOptions { + enabled: true, + resolution_interval_millis: dns.resolution_interval.as_millis() as u64, + }) + }); + let client_options = Box::new(crate::client::ConnectionOptions { target_url: options.target.as_str().into(), client_name: options.get_client_name().into(), @@ -354,6 +361,7 @@ impl Context { http_connect_proxy_options: pointer_or_null(proxy_options.as_deref()), grpc_override_callback, grpc_override_callback_user_data, + dns_load_balancing_options: pointer_or_null(dns_load_balancing_options.as_deref()), }); let client_options_ptr = &*client_options as *const _; From 383de95894d868336ba2341f60fd591affde728c Mon Sep 17 00:00:00 2001 From: Robert Cao Date: Wed, 6 May 2026 13:39:29 -0500 Subject: [PATCH 2/2] cargo fmt --- crates/sdk-core-c-bridge/src/client.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/crates/sdk-core-c-bridge/src/client.rs b/crates/sdk-core-c-bridge/src/client.rs index c7dbc2f9d..895f8a42c 100644 --- a/crates/sdk-core-c-bridge/src/client.rs +++ b/crates/sdk-core-c-bridge/src/client.rs @@ -1369,19 +1369,18 @@ impl TryFrom<&ConnectionOptions> for temporalio_client::ConnectionOptions { let http_connect_proxy = unsafe { opts.http_connect_proxy_options.as_ref() }.map(Into::into); - let dns_load_balancing = if http_connect_proxy.is_some() - || opts.grpc_override_callback.is_some() - { - None - } else { - unsafe { opts.dns_load_balancing_options.as_ref() }.map_or( - // Keep backwards compatibility. - // Before DnsLoadBalancingOptions was exposed through the C bridge, - // this was the default. - Some(temporalio_client::DnsLoadBalancingOptions::default()), - |c| c.into(), - ) - }; + let dns_load_balancing = + if http_connect_proxy.is_some() || opts.grpc_override_callback.is_some() { + None + } else { + unsafe { opts.dns_load_balancing_options.as_ref() }.map_or( + // Keep backwards compatibility. + // Before DnsLoadBalancingOptions was exposed through the C bridge, + // this was the default. + Some(temporalio_client::DnsLoadBalancingOptions::default()), + |c| c.into(), + ) + }; Ok( temporalio_client::ConnectionOptions::new(Url::parse(opts.target_url.to_str())?)