@temporalio/core-bridge 1.9.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@temporalio/core-bridge",
3
- "version": "1.9.0",
3
+ "version": "1.9.1",
4
4
  "description": "Temporal.io SDK Core<>Node bridge",
5
5
  "main": "index.js",
6
6
  "types": "lib/index.d.ts",
@@ -22,7 +22,7 @@
22
22
  "author": "Temporal Technologies Inc. <sdk@temporal.io>",
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@temporalio/common": "1.9.0",
25
+ "@temporalio/common": "1.9.1",
26
26
  "arg": "^5.0.2",
27
27
  "cargo-cp-artifact": "^0.1.8",
28
28
  "which": "^4.0.0"
@@ -52,5 +52,5 @@
52
52
  "publishConfig": {
53
53
  "access": "public"
54
54
  },
55
- "gitHead": "5096976287616207edcd3e4281a2a5e1f7393e33"
55
+ "gitHead": "05f22004a0d877d8a128768016d5719adbc67de8"
56
56
  }
@@ -44,10 +44,9 @@ impl ArrayHandleConversionsExt for Handle<'_, JsArray> {
44
44
  }
45
45
  }
46
46
 
47
- pub(crate) type TelemOptsRes = (
48
- TelemetryOptions,
49
- Option<Box<dyn FnOnce() -> Arc<dyn CoreMeter> + Send>>,
50
- );
47
+ type BoxedMeterMaker = Box<dyn FnOnce() -> Result<Arc<dyn CoreMeter>, String> + Send + Sync>;
48
+
49
+ pub(crate) type TelemOptsRes = (TelemetryOptions, Option<BoxedMeterMaker>);
51
50
 
52
51
  pub trait ObjectHandleConversionsExt {
53
52
  fn set_default(&self, cx: &mut FunctionContext, key: &str, value: &str) -> NeonResult<()>;
@@ -220,20 +219,24 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
220
219
  .unwrap_err()
221
220
  })?;
222
221
 
223
- meter_maker = Some(Box::new(move || {
224
- let prom_info = start_prometheus_metric_exporter(options)
225
- .expect("Failed creating prometheus exporter");
226
- prom_info.meter as Arc<dyn CoreMeter>
227
- })
228
- as Box<dyn FnOnce() -> Arc<dyn CoreMeter> + Send>);
222
+ meter_maker =
223
+ Some(
224
+ Box::new(move || match start_prometheus_metric_exporter(options) {
225
+ Ok(prom_info) => Ok(prom_info.meter as Arc<dyn CoreMeter>),
226
+ Err(e) => Err(format!("Failed to start prometheus exporter: {}", e)),
227
+ }) as BoxedMeterMaker,
228
+ );
229
229
  } else if let Some(ref otel) = js_optional_getter!(cx, metrics, "otel", JsObject) {
230
230
  let mut options = OtelCollectorOptionsBuilder::default();
231
231
 
232
232
  let url = js_value_getter!(cx, otel, "url", JsString);
233
233
  match Url::parse(&url) {
234
234
  Ok(url) => options.url(url),
235
- Err(_) => {
236
- return cx.throw_type_error("Invalid telemetryOptions.metrics.otel.url");
235
+ Err(e) => {
236
+ return cx.throw_type_error(format!(
237
+ "Invalid telemetryOptions.metrics.otel.url: {}",
238
+ e
239
+ ))?;
237
240
  }
238
241
  };
239
242
 
@@ -269,11 +272,10 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
269
272
  .unwrap_err()
270
273
  })?;
271
274
 
272
- meter_maker = Some(Box::new(move || {
273
- let otlp_exporter =
274
- build_otlp_metric_exporter(options).expect("Failed to build otlp exporter");
275
- Arc::new(otlp_exporter) as Arc<dyn CoreMeter>
276
- }));
275
+ meter_maker = Some(Box::new(move || match build_otlp_metric_exporter(options) {
276
+ Ok(otlp_exporter) => Ok(Arc::new(otlp_exporter) as Arc<dyn CoreMeter>),
277
+ Err(e) => Err(format!("Failed to start otlp exporter: {}", e)),
278
+ }) as BoxedMeterMaker);
277
279
  } else {
278
280
  cx.throw_type_error(
279
281
  "Invalid telemetryOptions.metrics, missing `prometheus` or `otel` option",
package/src/runtime.rs CHANGED
@@ -19,6 +19,7 @@ use temporal_sdk_core::{
19
19
  replay::{HistoryForReplay, ReplayWorkerInput},
20
20
  ClientOptions, RetryClient, WorkerConfig,
21
21
  };
22
+ use tokio::sync::oneshot;
22
23
  use tokio::sync::{
23
24
  mpsc::{channel, unbounded_channel, Sender, UnboundedReceiver, UnboundedSender},
24
25
  Mutex,
@@ -119,6 +120,7 @@ pub fn start_bridge_loop(
119
120
  telemetry_options: TelemOptsRes,
120
121
  channel: Arc<Channel>,
121
122
  receiver: &mut UnboundedReceiver<RuntimeRequest>,
123
+ result_sender: oneshot::Sender<Result<(), String>>,
122
124
  ) {
123
125
  let mut tokio_builder = tokio::runtime::Builder::new_multi_thread();
124
126
  tokio_builder.enable_all().thread_name("core");
@@ -129,10 +131,24 @@ pub fn start_bridge_loop(
129
131
 
130
132
  core_runtime.tokio_handle().block_on(async {
131
133
  if let Some(meter_maker) = meter_maker {
132
- core_runtime
133
- .telemetry_mut()
134
- .attach_late_init_metrics(meter_maker());
134
+ match meter_maker() {
135
+ Ok(meter) => {
136
+ core_runtime.telemetry_mut().attach_late_init_metrics(meter);
137
+ }
138
+ Err(err) => {
139
+ result_sender
140
+ .send(Err(format!("Failed to create meter: {}", err)))
141
+ .unwrap_or_else(|_| {
142
+ panic!("Failed to report runtime start error: {}", err)
143
+ });
144
+ return;
145
+ }
146
+ }
135
147
  }
148
+ result_sender
149
+ .send(Ok(()))
150
+ .expect("Failed to report runtime start success");
151
+
136
152
  loop {
137
153
  let request_option = receiver.recv().await;
138
154
  let request = match request_option {
@@ -386,7 +402,19 @@ pub fn runtime_new(mut cx: FunctionContext) -> JsResult<BoxedRuntime> {
386
402
  let channel = Arc::new(cx.channel());
387
403
  let (sender, mut receiver) = unbounded_channel::<RuntimeRequest>();
388
404
 
389
- std::thread::spawn(move || start_bridge_loop(telemetry_options, channel, &mut receiver));
405
+ // FIXME: This is a temporary fix to get sync notifications of errors while initializing the runtime.
406
+ // The proper fix would be to avoid spawning a new thread here, so that start_bridge_loop
407
+ // can simply yeild back a Result. But early attempts to do just that caused panics
408
+ // on runtime shutdown, so let's use this hack until we can dig deeper.
409
+ let (result_sender, result_receiver) = oneshot::channel::<Result<(), String>>();
410
+
411
+ std::thread::spawn(move || {
412
+ start_bridge_loop(telemetry_options, channel, &mut receiver, result_sender)
413
+ });
414
+
415
+ if let Ok(Err(e)) = result_receiver.blocking_recv() {
416
+ Err(cx.throw_error::<_, String>(e).unwrap_err())?;
417
+ }
390
418
 
391
419
  Ok(cx.boxed(Arc::new(RuntimeHandle { sender })))
392
420
  }