Skip to content

Commit dd91bde

Browse files
committed
envconfig impl
1 parent 6512c02 commit dd91bde

File tree

7 files changed

+1482
-3
lines changed

7 files changed

+1482
-3
lines changed

temporalio/ext/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ prost = "0.13"
1717
rb-sys = "0.9"
1818
temporal-client = { version = "0.1.0", path = "./sdk-core/client" }
1919
temporal-sdk-core = { version = "0.1.0", path = "./sdk-core/core", features = ["ephemeral-server"] }
20-
temporal-sdk-core-api = { version = "0.1.0", path = "./sdk-core/core-api" }
20+
temporal-sdk-core-api = { version = "0.1.0", path = "./sdk-core/core-api", features = ["envconfig"] }
2121
temporal-sdk-core-protos = { version = "0.1.0", path = "./sdk-core/sdk-core-protos" }
2222
tokio = "1.37"
2323
tokio-stream = "0.1"

temporalio/ext/src/envconfig.rs

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
use std::collections::HashMap;
2+
3+
use magnus::{Error, RHash, Ruby, function, prelude::*, scan_args, class};
4+
use temporal_sdk_core_api::envconfig::{
5+
load_client_config as core_load_client_config,
6+
load_client_config_profile as core_load_client_config_profile,
7+
ClientConfig as CoreClientConfig, ClientConfigCodec, ClientConfigProfile as CoreClientConfigProfile,
8+
ClientConfigTLS as CoreClientConfigTLS, DataSource, LoadClientConfigOptions,
9+
LoadClientConfigProfileOptions,
10+
};
11+
12+
use crate::{ROOT_MOD, error};
13+
14+
pub fn init(ruby: &Ruby) -> Result<(), Error> {
15+
let root_mod = ruby.get_inner(&ROOT_MOD);
16+
17+
let class = root_mod.define_class("EnvConfig", class::object())?;
18+
class.define_singleton_method("load_client_config", function!(load_client_config, -1))?;
19+
class.define_singleton_method("load_client_connect_config", function!(load_client_connect_config, -1))?;
20+
21+
Ok(())
22+
}
23+
24+
fn data_source_to_hash(ruby: &Ruby, ds: &DataSource) -> Result<RHash, Error> {
25+
let hash = RHash::new();
26+
match ds {
27+
DataSource::Path(p) => {
28+
hash.aset("path", ruby.str_new(p))?;
29+
}
30+
DataSource::Data(d) => {
31+
hash.aset("data", ruby.str_from_slice(d))?;
32+
}
33+
}
34+
Ok(hash)
35+
}
36+
37+
fn tls_to_hash(ruby: &Ruby, tls: &CoreClientConfigTLS) -> Result<RHash, Error> {
38+
let hash = RHash::new();
39+
hash.aset("disabled", tls.disabled)?;
40+
41+
if let Some(v) = &tls.client_cert {
42+
hash.aset("client_cert", data_source_to_hash(ruby, v)?)?;
43+
}
44+
if let Some(v) = &tls.client_key {
45+
hash.aset("client_key", data_source_to_hash(ruby, v)?)?;
46+
}
47+
if let Some(v) = &tls.server_ca_cert {
48+
hash.aset("server_ca_cert", data_source_to_hash(ruby, v)?)?;
49+
}
50+
if let Some(v) = &tls.server_name {
51+
hash.aset("server_name", ruby.str_new(v))?;
52+
}
53+
hash.aset("disable_host_verification", tls.disable_host_verification)?;
54+
55+
Ok(hash)
56+
}
57+
58+
fn codec_to_hash(ruby: &Ruby, codec: &ClientConfigCodec) -> Result<RHash, Error> {
59+
let hash = RHash::new();
60+
if let Some(v) = &codec.endpoint {
61+
hash.aset("endpoint", ruby.str_new(v))?;
62+
}
63+
if let Some(v) = &codec.auth {
64+
hash.aset("auth", ruby.str_new(v))?;
65+
}
66+
Ok(hash)
67+
}
68+
69+
fn profile_to_hash(ruby: &Ruby, profile: &CoreClientConfigProfile) -> Result<RHash, Error> {
70+
let hash = RHash::new();
71+
72+
if let Some(v) = &profile.address {
73+
hash.aset("address", ruby.str_new(v))?;
74+
}
75+
if let Some(v) = &profile.namespace {
76+
hash.aset("namespace", ruby.str_new(v))?;
77+
}
78+
if let Some(v) = &profile.api_key {
79+
hash.aset("api_key", ruby.str_new(v))?;
80+
}
81+
if let Some(tls) = &profile.tls {
82+
hash.aset("tls", tls_to_hash(ruby, tls)?)?;
83+
}
84+
if let Some(codec) = &profile.codec {
85+
hash.aset("codec", codec_to_hash(ruby, codec)?)?;
86+
}
87+
if !profile.grpc_meta.is_empty() {
88+
let grpc_meta_hash = RHash::new();
89+
for (k, v) in &profile.grpc_meta {
90+
grpc_meta_hash.aset(ruby.str_new(k), ruby.str_new(v))?;
91+
}
92+
hash.aset("grpc_meta", grpc_meta_hash)?;
93+
}
94+
95+
Ok(hash)
96+
}
97+
98+
fn core_config_to_hash(ruby: &Ruby, core_config: &CoreClientConfig) -> Result<RHash, Error> {
99+
let profiles_hash = RHash::new();
100+
for (name, profile) in &core_config.profiles {
101+
let profile_hash = profile_to_hash(ruby, profile)?;
102+
profiles_hash.aset(ruby.str_new(name), profile_hash)?;
103+
}
104+
Ok(profiles_hash)
105+
}
106+
107+
fn load_client_config_inner(
108+
ruby: &Ruby,
109+
config_source: Option<DataSource>,
110+
config_file_strict: bool,
111+
disable_file: bool,
112+
env_vars: Option<HashMap<String, String>>,
113+
) -> Result<RHash, Error> {
114+
let core_config = if disable_file {
115+
CoreClientConfig::default()
116+
} else {
117+
let options = LoadClientConfigOptions {
118+
config_source,
119+
config_file_strict,
120+
};
121+
core_load_client_config(options, env_vars.as_ref())
122+
.map_err(|e| error!("EnvConfig error: {}", e))?
123+
};
124+
125+
core_config_to_hash(ruby, &core_config)
126+
}
127+
128+
fn load_client_connect_config_inner(
129+
ruby: &Ruby,
130+
config_source: Option<DataSource>,
131+
profile: Option<String>,
132+
disable_file: bool,
133+
disable_env: bool,
134+
config_file_strict: bool,
135+
env_vars: Option<HashMap<String, String>>,
136+
) -> Result<RHash, Error> {
137+
let options = LoadClientConfigProfileOptions {
138+
config_source,
139+
config_file_profile: profile,
140+
config_file_strict,
141+
disable_file,
142+
disable_env,
143+
};
144+
145+
let profile = core_load_client_config_profile(options, env_vars.as_ref())
146+
.map_err(|e| error!("EnvConfig error: {}", e))?;
147+
148+
profile_to_hash(ruby, &profile)
149+
}
150+
151+
// load_client_config(path: String|nil, data: String|nil, disable_file: bool, config_file_strict: bool, env_vars: Hash|nil)
152+
fn load_client_config(args: &[magnus::Value]) -> Result<RHash, Error> {
153+
let ruby = Ruby::get().expect("Not in Ruby thread");
154+
let args = scan_args::scan_args::<
155+
(Option<String>, Option<Vec<u8>>, bool, bool),
156+
(Option<HashMap<String, String>>,),
157+
(),
158+
(),
159+
(),
160+
(),
161+
>(args)?;
162+
let (path, data, disable_file, config_file_strict) = args.required;
163+
let (env_vars,) = args.optional;
164+
165+
let config_source = match (path, data) {
166+
(Some(p), None) => Some(DataSource::Path(p)),
167+
(None, Some(d)) => Some(DataSource::Data(d)),
168+
(None, None) => None,
169+
(Some(_), Some(_)) => {
170+
return Err(error!("Cannot specify both path and data for config source"));
171+
}
172+
};
173+
174+
load_client_config_inner(
175+
&ruby,
176+
config_source,
177+
config_file_strict,
178+
disable_file,
179+
env_vars,
180+
)
181+
}
182+
183+
// load_client_connect_config(profile: String|nil, path: String|nil, data: String|nil, disable_file: bool, disable_env: bool, config_file_strict: bool, env_vars: Hash|nil)
184+
fn load_client_connect_config(args: &[magnus::Value]) -> Result<RHash, Error> {
185+
let ruby = Ruby::get().expect("Not in Ruby thread");
186+
let args = scan_args::scan_args::<
187+
(Option<String>, Option<String>, Option<Vec<u8>>, bool, bool, bool),
188+
(Option<HashMap<String, String>>,),
189+
(),
190+
(),
191+
(),
192+
(),
193+
>(args)?;
194+
let (profile, path, data, disable_file, disable_env, config_file_strict) = args.required;
195+
let (env_vars,) = args.optional;
196+
197+
let config_source = match (path, data) {
198+
(Some(p), None) => Some(DataSource::Path(p)),
199+
(None, Some(d)) => Some(DataSource::Data(d)),
200+
(None, None) => None,
201+
(Some(_), Some(_)) => {
202+
return Err(error!("Cannot specify both path and data for config source"));
203+
}
204+
};
205+
206+
load_client_connect_config_inner(
207+
&ruby,
208+
config_source,
209+
profile,
210+
disable_file,
211+
disable_env,
212+
config_file_strict,
213+
env_vars,
214+
)
215+
}

temporalio/ext/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use magnus::{Error, ExceptionClass, RModule, Ruby, prelude::*, value::Lazy};
22

33
mod client;
44
mod client_rpc_generated;
5+
mod envconfig;
56
mod metric;
67
mod runtime;
78
mod testing;
@@ -50,6 +51,7 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
5051
Lazy::force(&ROOT_ERR, ruby);
5152

5253
client::init(ruby)?;
54+
envconfig::init(ruby)?;
5355
metric::init(ruby)?;
5456
runtime::init(ruby)?;
5557
testing::init(ruby)?;

temporalio/lib/temporalio.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require 'temporalio/version'
44
require 'temporalio/versioning_override'
5+
require 'temporalio/envconfig'
56

67
# Temporal Ruby SDK. See the README at https://github.com/temporalio/sdk-ruby.
78
module Temporalio

temporalio/lib/temporalio/cancellation.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ def prepare_cancel(reason:)
167167
to_return.values
168168
end
169169

170-
def canceled_mutex_synchronize(&)
171-
Workflow::Unsafe.illegal_call_tracing_disabled { @canceled_mutex.synchronize(&) }
170+
def canceled_mutex_synchronize(&block)
171+
Workflow::Unsafe.illegal_call_tracing_disabled { @canceled_mutex.synchronize(&block) }
172172
end
173173
end
174174
end

0 commit comments

Comments
 (0)