@temporalio/core-bridge 1.11.8 → 1.12.0

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.
Files changed (205) hide show
  1. package/Cargo.lock +219 -193
  2. package/Cargo.toml +27 -8
  3. package/README.md +5 -0
  4. package/index.js +72 -12
  5. package/lib/errors.d.ts +25 -0
  6. package/lib/errors.js +76 -1
  7. package/lib/errors.js.map +1 -1
  8. package/lib/index.d.ts +11 -478
  9. package/lib/index.js +28 -5
  10. package/lib/index.js.map +1 -1
  11. package/lib/native.d.ts +330 -0
  12. package/lib/{worker-tuner.js → native.js} +1 -1
  13. package/lib/native.js.map +1 -0
  14. package/package.json +7 -3
  15. package/releases/aarch64-apple-darwin/index.node +0 -0
  16. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  17. package/releases/x86_64-apple-darwin/index.node +0 -0
  18. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  19. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  20. package/sdk-core/.cargo/config.toml +8 -2
  21. package/sdk-core/.cargo/multi-worker-manual-test +15 -0
  22. package/sdk-core/.github/workflows/per-pr.yml +40 -11
  23. package/sdk-core/AGENTS.md +73 -0
  24. package/sdk-core/ARCHITECTURE.md +71 -23
  25. package/sdk-core/Cargo.toml +1 -1
  26. package/sdk-core/README.md +4 -4
  27. package/sdk-core/arch_docs/workflow_task_chunking.md +51 -0
  28. package/sdk-core/client/Cargo.toml +1 -1
  29. package/sdk-core/client/src/lib.rs +49 -13
  30. package/sdk-core/client/src/metrics.rs +15 -16
  31. package/sdk-core/client/src/proxy.rs +2 -2
  32. package/sdk-core/client/src/raw.rs +54 -8
  33. package/sdk-core/client/src/retry.rs +109 -13
  34. package/sdk-core/client/src/worker_registry/mod.rs +4 -4
  35. package/sdk-core/client/src/workflow_handle/mod.rs +1 -1
  36. package/sdk-core/core/Cargo.toml +28 -8
  37. package/sdk-core/core/src/abstractions.rs +62 -10
  38. package/sdk-core/core/src/core_tests/activity_tasks.rs +180 -8
  39. package/sdk-core/core/src/core_tests/mod.rs +4 -4
  40. package/sdk-core/core/src/core_tests/queries.rs +18 -4
  41. package/sdk-core/core/src/core_tests/workers.rs +3 -3
  42. package/sdk-core/core/src/core_tests/workflow_tasks.rs +191 -25
  43. package/sdk-core/core/src/ephemeral_server/mod.rs +10 -3
  44. package/sdk-core/core/src/internal_flags.rs +14 -14
  45. package/sdk-core/core/src/lib.rs +5 -2
  46. package/sdk-core/core/src/pollers/mod.rs +1 -1
  47. package/sdk-core/core/src/pollers/poll_buffer.rs +495 -164
  48. package/sdk-core/core/src/protosext/mod.rs +3 -3
  49. package/sdk-core/core/src/replay/mod.rs +3 -3
  50. package/sdk-core/core/src/telemetry/metrics.rs +13 -4
  51. package/sdk-core/core/src/telemetry/mod.rs +72 -70
  52. package/sdk-core/core/src/telemetry/otel.rs +51 -54
  53. package/sdk-core/core/src/test_help/mod.rs +9 -3
  54. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +31 -11
  55. package/sdk-core/core/src/worker/activities/local_activities.rs +35 -28
  56. package/sdk-core/core/src/worker/activities.rs +58 -30
  57. package/sdk-core/core/src/worker/client/mocks.rs +3 -3
  58. package/sdk-core/core/src/worker/client.rs +155 -53
  59. package/sdk-core/core/src/worker/mod.rs +103 -95
  60. package/sdk-core/core/src/worker/nexus.rs +100 -73
  61. package/sdk-core/core/src/worker/tuner/resource_based.rs +14 -6
  62. package/sdk-core/core/src/worker/tuner.rs +4 -13
  63. package/sdk-core/core/src/worker/workflow/history_update.rs +47 -51
  64. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -4
  65. package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +127 -32
  66. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +1 -2
  67. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +1 -1
  68. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +55 -42
  69. package/sdk-core/core/src/worker/workflow/managed_run.rs +45 -35
  70. package/sdk-core/core/src/worker/workflow/mod.rs +200 -97
  71. package/sdk-core/core/src/worker/workflow/wft_poller.rs +175 -4
  72. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +38 -36
  73. package/sdk-core/core-api/Cargo.toml +8 -0
  74. package/sdk-core/core-api/src/envconfig.rs +1544 -0
  75. package/sdk-core/core-api/src/lib.rs +2 -0
  76. package/sdk-core/core-api/src/telemetry/metrics.rs +8 -0
  77. package/sdk-core/core-api/src/telemetry.rs +36 -3
  78. package/sdk-core/core-api/src/worker.rs +301 -75
  79. package/sdk-core/docker/docker-compose-telem.yaml +1 -0
  80. package/sdk-core/etc/prometheus.yaml +6 -2
  81. package/sdk-core/histories/long_local_activity_with_update-0_history.bin +0 -0
  82. package/sdk-core/histories/long_local_activity_with_update-1_history.bin +0 -0
  83. package/sdk-core/histories/long_local_activity_with_update-2_history.bin +0 -0
  84. package/sdk-core/histories/long_local_activity_with_update-3_history.bin +0 -0
  85. package/sdk-core/sdk/src/activity_context.rs +5 -0
  86. package/sdk-core/sdk/src/interceptors.rs +73 -3
  87. package/sdk-core/sdk/src/lib.rs +15 -16
  88. package/sdk-core/sdk/src/workflow_context/options.rs +10 -0
  89. package/sdk-core/sdk/src/workflow_context.rs +48 -29
  90. package/sdk-core/sdk/src/workflow_future.rs +5 -6
  91. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/.github/workflows/push-to-buf.yml +20 -0
  92. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/CODEOWNERS +6 -0
  93. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/README.md +17 -6
  94. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -1
  95. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.lock +7 -2
  96. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.yaml +2 -0
  97. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +78 -0
  98. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +29 -0
  99. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +74 -32
  100. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +45 -15
  101. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/nexus/v1/message.proto +7 -1
  102. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +3 -3
  103. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +3 -3
  104. package/sdk-core/sdk-core-protos/protos/api_upstream/LICENSE +1 -1
  105. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +2 -0
  106. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +1103 -88
  107. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +1233 -151
  108. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/activity/v1/message.proto +0 -22
  109. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +19 -24
  110. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +0 -22
  111. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +12 -22
  112. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +45 -45
  113. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -22
  114. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/command_type.proto +0 -22
  115. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/common.proto +15 -22
  116. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/deployment.proto +0 -22
  117. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +4 -22
  118. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +0 -22
  119. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/namespace.proto +0 -22
  120. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/nexus.proto +0 -20
  121. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/query.proto +0 -22
  122. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/reset.proto +0 -22
  123. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/schedule.proto +0 -22
  124. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -22
  125. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/update.proto +0 -22
  126. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/workflow.proto +4 -22
  127. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/errordetails/v1/message.proto +0 -22
  128. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/export/v1/message.proto +0 -22
  129. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -22
  130. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/filter/v1/message.proto +0 -22
  131. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +75 -49
  132. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +0 -22
  133. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +0 -20
  134. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +0 -22
  135. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -22
  136. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/protocol/v1/message.proto +0 -22
  137. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/query/v1/message.proto +0 -22
  138. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/replication/v1/message.proto +0 -22
  139. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/rules/v1/message.proto +90 -0
  140. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/schedule/v1/message.proto +0 -22
  141. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/enhanced_stack_trace.proto +0 -22
  142. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +0 -22
  143. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/user_metadata.proto +0 -22
  144. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +0 -22
  145. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +17 -38
  146. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/update/v1/message.proto +0 -22
  147. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/version/v1/message.proto +0 -22
  148. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +151 -44
  149. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +172 -65
  150. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +69 -28
  151. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/activity_task/activity_task.proto +18 -0
  152. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/common/common.proto +5 -0
  153. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/nexus/nexus.proto +16 -1
  154. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +21 -15
  155. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +3 -0
  156. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +3 -0
  157. package/sdk-core/sdk-core-protos/src/lib.rs +60 -16
  158. package/sdk-core/test-utils/src/lib.rs +157 -39
  159. package/sdk-core/tests/cloud_tests.rs +86 -0
  160. package/sdk-core/tests/fuzzy_workflow.rs +23 -26
  161. package/sdk-core/tests/global_metric_tests.rs +116 -0
  162. package/sdk-core/tests/heavy_tests.rs +127 -7
  163. package/sdk-core/tests/integ_tests/client_tests.rs +2 -8
  164. package/sdk-core/tests/integ_tests/metrics_tests.rs +100 -106
  165. package/sdk-core/tests/integ_tests/polling_tests.rs +94 -8
  166. package/sdk-core/tests/integ_tests/update_tests.rs +75 -6
  167. package/sdk-core/tests/integ_tests/worker_tests.rs +54 -5
  168. package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +240 -0
  169. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +41 -3
  170. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +168 -8
  171. package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +285 -15
  172. package/sdk-core/tests/integ_tests/workflow_tests/priority.rs +12 -4
  173. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +3 -2
  174. package/sdk-core/tests/integ_tests/workflow_tests.rs +124 -74
  175. package/sdk-core/tests/main.rs +3 -51
  176. package/sdk-core/tests/manual_tests.rs +430 -0
  177. package/sdk-core/tests/runner.rs +28 -2
  178. package/src/client.rs +565 -0
  179. package/src/helpers/abort_controller.rs +204 -0
  180. package/src/helpers/callbacks.rs +299 -0
  181. package/src/helpers/errors.rs +302 -0
  182. package/src/helpers/future.rs +44 -0
  183. package/src/helpers/handles.rs +191 -0
  184. package/src/helpers/inspect.rs +18 -0
  185. package/src/helpers/json_string.rs +58 -0
  186. package/src/helpers/mod.rs +20 -0
  187. package/src/helpers/properties.rs +71 -0
  188. package/src/helpers/try_from_js.rs +213 -0
  189. package/src/helpers/try_into_js.rs +129 -0
  190. package/src/lib.rs +28 -40
  191. package/src/logs.rs +111 -0
  192. package/src/metrics.rs +325 -0
  193. package/src/runtime.rs +409 -498
  194. package/src/testing.rs +315 -57
  195. package/src/worker.rs +907 -378
  196. package/ts/errors.ts +57 -0
  197. package/ts/index.ts +10 -596
  198. package/ts/native.ts +496 -0
  199. package/lib/worker-tuner.d.ts +0 -167
  200. package/lib/worker-tuner.js.map +0 -1
  201. package/src/conversions/slot_supplier_bridge.rs +0 -291
  202. package/src/conversions.rs +0 -618
  203. package/src/errors.rs +0 -38
  204. package/src/helpers.rs +0 -297
  205. package/ts/worker-tuner.ts +0 -193
package/src/testing.rs CHANGED
@@ -1,70 +1,328 @@
1
- use crate::conversions::*;
2
- use crate::errors::*;
3
- use crate::helpers::*;
4
- use crate::runtime::{BoxedEphemeralServer, BoxedRuntime, RuntimeRequest};
1
+ use std::io::{Read as _, Write as _};
2
+ use std::{process::Stdio, sync::Arc};
3
+
4
+ use anyhow::Context as _;
5
5
  use neon::prelude::*;
6
6
 
7
- // Below are functions exported to JS
7
+ use temporal_sdk_core::ephemeral_server::{
8
+ EphemeralServer as CoreEphemeralServer, TemporalDevServerConfig as CoreTemporalDevServerConfig,
9
+ TestServerConfig as CoreTestServerConfig,
10
+ };
11
+
12
+ use bridge_macros::js_function;
13
+ use temporal_sdk_core::CoreRuntime;
14
+
15
+ use crate::helpers::*;
16
+ use crate::runtime::{Runtime, RuntimeExt as _};
17
+
18
+ pub fn init(cx: &mut neon::prelude::ModuleContext) -> neon::prelude::NeonResult<()> {
19
+ cx.export_function("newEphemeralServer", ephemeral_server_new)?;
20
+ cx.export_function("ephemeralServerGetTarget", ephemeral_server_get_target)?;
21
+ cx.export_function("ephemeralServerShutdown", ephemeral_server_shutdown)?;
22
+
23
+ Ok(())
24
+ }
25
+
26
+ pub struct EphemeralServer {
27
+ core_runtime: Arc<CoreRuntime>,
28
+ core_server: CoreEphemeralServer,
29
+ stdout_thread: Option<std::thread::JoinHandle<()>>,
30
+ stderr_thread: Option<std::thread::JoinHandle<()>>,
31
+ }
8
32
 
9
33
  /// Start an ephemeral Temporal server
10
- pub fn start_ephemeral_server(mut cx: FunctionContext) -> JsResult<JsUndefined> {
11
- let runtime = cx.argument::<BoxedRuntime>(0)?;
12
- let config = cx.argument::<JsObject>(1)?;
13
- let sdk_version = cx.argument::<JsString>(2)?.value(&mut cx);
14
- let callback = cx.argument::<JsFunction>(3)?;
15
-
16
- let config = config.as_ephemeral_server_config(&mut cx, sdk_version)?;
17
- let request = RuntimeRequest::StartEphemeralServer {
18
- runtime: (**runtime).clone(),
19
- config,
20
- callback: callback.root(&mut cx),
21
- };
22
- if let Err(err) = runtime.sender.send(request) {
23
- callback_with_unexpected_error(&mut cx, callback, err)?;
24
- };
34
+ #[js_function]
35
+ pub fn ephemeral_server_new(
36
+ runtime: OpaqueInboundHandle<Runtime>,
37
+ config: config::EphemeralServerConfig,
38
+ ) -> BridgeResult<BridgeFuture<OpaqueOutboundHandle<EphemeralServer>>> {
39
+ let runtime = runtime.borrow()?.core_runtime.clone();
40
+ let config: CoreEphemeralServerConfig = config.try_into()?;
41
+
42
+ runtime.clone().future_to_promise(async move {
43
+ let (stdout, stderr, stdout_thread, stderr_thread) = get_stdout_stderr()?;
25
44
 
26
- Ok(cx.undefined())
45
+ let core_server = config
46
+ .start_server(stdout, stderr)
47
+ .await
48
+ .context("Failed to start ephemeral server")?;
49
+
50
+ Ok(OpaqueOutboundHandle::new(EphemeralServer {
51
+ core_runtime: runtime,
52
+ core_server,
53
+ stdout_thread,
54
+ stderr_thread,
55
+ }))
56
+ })
27
57
  }
28
58
 
29
- /// Get the ephemeral server "target" (address:port string)
30
- pub fn get_ephemeral_server_target(mut cx: FunctionContext) -> JsResult<JsString> {
31
- let server = cx.argument::<BoxedEphemeralServer>(0)?;
32
- let target = server
33
- .borrow()
34
- .as_ref()
35
- .map(|s| cx.string(s.core_server.blocking_lock().target.as_str()));
36
- if target.is_none() {
37
- make_named_error_from_string(
38
- &mut cx,
39
- ILLEGAL_STATE_ERROR,
40
- "Tried to use closed test server",
41
- )
42
- .and_then(|err| cx.throw(err))?;
43
- };
44
- Ok(target.unwrap())
59
+ // Node intentionally drops stdout/stderr on process fork for security reasons, which
60
+ // is causing various issues with ephemeral servers. To work around that behavior, we
61
+ // explicitly force stdout/stderr on the child process. Unfortunately, simply propagating
62
+ // our stdout and stderr also cause issues, as some test engines (e.g. ava) run tests in
63
+ // worker threads or child processes, with pipes as stdout/stderr. When tests complete,
64
+ // the engine stops draining the pipe, preventing remaining ephemeral servers from exiting.
65
+ //
66
+ // Solution is to make our own pipes that forward the the ephemeral server's stdout/stderr
67
+ // to our own, with some simple logic to drop any output generated after the parent process
68
+ // has closed its handles to the pipes. For now, that logic is implemented using a thread
69
+ // per pipe. Replacing with async is definitely possible, but may require some work on the
70
+ // Core side. For now, we'll just live with the extra threads.
71
+ // FIXME: Investigate use of async io for stdout/stderr forwarding.
72
+ #[allow(clippy::type_complexity)] // Acceptable until this is revisited
73
+ fn get_stdout_stderr() -> BridgeResult<(
74
+ Stdio,
75
+ Stdio,
76
+ Option<std::thread::JoinHandle<()>>,
77
+ Option<std::thread::JoinHandle<()>>,
78
+ )> {
79
+ let (mut stdout_read, stdout_write) = os_pipe::pipe().context("Failed to create pipe")?;
80
+ let (mut stderr_read, stderr_write) = os_pipe::pipe().context("Failed to create pipe")?;
81
+
82
+ let stdout = Stdio::from(stdout_write);
83
+ let stderr = Stdio::from(stderr_write);
84
+
85
+ // Start threads to forward the output
86
+ let stdout_thread = std::thread::spawn(move || {
87
+ let mut buffer = [0; 1024];
88
+ loop {
89
+ match stdout_read.read(&mut buffer) {
90
+ Ok(0) | Err(_) => break,
91
+ Ok(n) => {
92
+ std::io::stdout().write_all(&buffer[0..n]).ok();
93
+ std::io::stdout().flush().ok();
94
+ }
95
+ }
96
+ }
97
+ });
98
+
99
+ let stderr_thread = std::thread::spawn(move || {
100
+ let mut buffer = [0; 1024];
101
+ loop {
102
+ match stderr_read.read(&mut buffer) {
103
+ Ok(0) | Err(_) => break,
104
+ Ok(n) => {
105
+ std::io::stderr().write_all(&buffer[0..n]).ok();
106
+ std::io::stderr().flush().ok();
107
+ }
108
+ }
109
+ }
110
+ });
111
+
112
+ Ok((stdout, stderr, Some(stdout_thread), Some(stderr_thread)))
113
+ }
114
+
115
+ /// Get the "target address" (address:port string) of a running ephemeral server.
116
+ #[js_function]
117
+ pub fn ephemeral_server_get_target(
118
+ server: OpaqueInboundHandle<EphemeralServer>,
119
+ ) -> BridgeResult<String> {
120
+ Ok(server.borrow()?.core_server.target.clone())
121
+ }
122
+
123
+ /// Shutdown an ephemeral server.
124
+ #[js_function]
125
+ pub fn ephemeral_server_shutdown(
126
+ server: OpaqueInboundHandle<EphemeralServer>,
127
+ ) -> BridgeResult<BridgeFuture<()>> {
128
+ let mut server = server.take()?;
129
+
130
+ let runtime = server.core_runtime.clone();
131
+ runtime.future_to_promise(async move {
132
+ server
133
+ .core_server
134
+ .shutdown()
135
+ .await
136
+ .context("Failed to shutdown ephemeral server")?;
137
+
138
+ let _ = server
139
+ .stdout_thread
140
+ .take()
141
+ .map(std::thread::JoinHandle::join);
142
+
143
+ let _ = server
144
+ .stderr_thread
145
+ .take()
146
+ .map(std::thread::JoinHandle::join);
147
+
148
+ Ok(())
149
+ })
45
150
  }
46
151
 
47
- /// Shutdown an ephemeral server - consumes the server
48
- pub fn shutdown_ephemeral_server(mut cx: FunctionContext) -> JsResult<JsUndefined> {
49
- let server = cx.argument::<BoxedEphemeralServer>(0)?;
50
- let callback = cx.argument::<JsFunction>(1)?;
51
- // Drop the ref
52
- match server.replace(None) {
53
- None => {
54
- callback_with_unexpected_error(&mut cx, callback, "Tried to use closed test server")?;
152
+ impl MutableFinalize for EphemeralServer {
153
+ fn finalize_mut(mut self) {
154
+ self.core_runtime.clone().tokio_handle().spawn(async move {
155
+ // We can't really do anything about errors here, so we just ignore them
156
+ let _ = self.core_server.shutdown().await;
157
+ self.stdout_thread.take().map(std::thread::JoinHandle::join);
158
+ self.stderr_thread.take().map(std::thread::JoinHandle::join);
159
+ });
160
+ }
161
+ }
162
+
163
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
164
+
165
+ // Contrarily to other SDKs and to the APIs that Core SDK exposes, we use a common code path for
166
+ // both kind of ephemeral servers, so we need an extra abstraction layer to make both adhere
167
+ // to a common interface. Hopefully, these should be defined in the core-bridge crate.
168
+
169
+ enum CoreEphemeralServerConfig {
170
+ TimeSkipping(CoreTestServerConfig),
171
+ DevServer(CoreTemporalDevServerConfig),
172
+ }
173
+
174
+ impl CoreEphemeralServerConfig {
175
+ async fn start_server(
176
+ self,
177
+ stdout: Stdio,
178
+ stderr: Stdio,
179
+ ) -> anyhow::Result<CoreEphemeralServer> {
180
+ match self {
181
+ Self::TimeSkipping(config) => config.start_server_with_output(stdout, stderr).await,
182
+ Self::DevServer(config) => config.start_server_with_output(stdout, stderr).await,
55
183
  }
56
- Some(server) => {
57
- if let Err(err) = server
58
- .runtime
59
- .sender
60
- .send(RuntimeRequest::ShutdownEphemeralServer {
61
- server: server.core_server.clone(),
62
- callback: callback.root(&mut cx),
63
- })
64
- {
65
- callback_with_unexpected_error(&mut cx, callback, err)?;
66
- };
184
+ }
185
+ }
186
+
187
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
188
+
189
+ mod config {
190
+ use std::time::Duration;
191
+
192
+ use anyhow::Context as _;
193
+
194
+ use temporal_sdk_core::ephemeral_server::{
195
+ EphemeralExe, EphemeralExeVersion, TemporalDevServerConfig as CoreTemporalDevServerConfig,
196
+ TemporalDevServerConfigBuilder, TestServerConfig as CoreTestServerConfig,
197
+ TestServerConfigBuilder,
198
+ };
199
+
200
+ use bridge_macros::TryFromJs;
201
+
202
+ use crate::helpers::BridgeError;
203
+
204
+ #[derive(Debug, Clone, TryFromJs)]
205
+ pub(super) enum EphemeralServerConfig {
206
+ TimeSkipping(TimeSkippingServerConfig),
207
+ DevServer(DevServerConfig),
208
+ }
209
+
210
+ #[derive(Debug, Clone, TryFromJs)]
211
+ pub(super) struct TimeSkippingServerConfig {
212
+ exe: EphemeralServerExecutableConfig,
213
+ port: Option<u16>,
214
+ extra_args: Vec<String>,
215
+ }
216
+
217
+ #[derive(Debug, Clone, TryFromJs)]
218
+ pub(super) struct DevServerConfig {
219
+ exe: EphemeralServerExecutableConfig,
220
+ namespace: String,
221
+ ip: String,
222
+ port: Option<u16>,
223
+ ui_port: Option<u16>,
224
+ db_filename: Option<String>,
225
+ ui: bool,
226
+ log: DevServerLogConfig,
227
+ extra_args: Vec<String>,
228
+ }
229
+
230
+ #[derive(Debug, Clone, TryFromJs)]
231
+ pub(super) struct DevServerLogConfig {
232
+ format: String,
233
+ level: String,
234
+ }
235
+
236
+ #[derive(Debug, Clone, TryFromJs)]
237
+ enum EphemeralServerExecutableConfig {
238
+ CachedDownload(CachedDownloadConfig),
239
+ ExistingPath(ExistingPathConfig),
240
+ }
241
+
242
+ #[derive(Debug, Clone, TryFromJs)]
243
+ struct CachedDownloadConfig {
244
+ download_dir: Option<String>,
245
+ version: String,
246
+ ttl: Duration,
247
+ sdk_name: String,
248
+ sdk_version: String,
249
+ }
250
+
251
+ #[derive(Debug, Clone, TryFromJs)]
252
+ struct ExistingPathConfig {
253
+ path: String,
254
+ }
255
+
256
+ impl TryInto<super::CoreEphemeralServerConfig> for EphemeralServerConfig {
257
+ type Error = BridgeError;
258
+ fn try_into(self) -> Result<super::CoreEphemeralServerConfig, Self::Error> {
259
+ match self {
260
+ Self::TimeSkipping(config) => Ok(super::CoreEphemeralServerConfig::TimeSkipping(
261
+ config.try_into()?,
262
+ )),
263
+ Self::DevServer(config) => Ok(super::CoreEphemeralServerConfig::DevServer(
264
+ config.try_into()?,
265
+ )),
266
+ }
267
+ }
268
+ }
269
+
270
+ impl TryInto<CoreTestServerConfig> for TimeSkippingServerConfig {
271
+ type Error = BridgeError;
272
+
273
+ fn try_into(self) -> Result<CoreTestServerConfig, Self::Error> {
274
+ let mut config = TestServerConfigBuilder::default();
275
+ let config = config
276
+ .exe(self.exe.into())
277
+ .port(self.port)
278
+ .extra_args(self.extra_args)
279
+ .build()
280
+ .context("Invalid Test Server config")?;
281
+
282
+ Ok(config)
283
+ }
284
+ }
285
+
286
+ impl TryInto<CoreTemporalDevServerConfig> for DevServerConfig {
287
+ type Error = BridgeError;
288
+
289
+ fn try_into(self) -> Result<CoreTemporalDevServerConfig, Self::Error> {
290
+ let mut config = TemporalDevServerConfigBuilder::default();
291
+ let config = config
292
+ .exe(self.exe.into())
293
+ .namespace(self.namespace)
294
+ .ip(self.ip)
295
+ .port(self.port)
296
+ .ui_port(self.ui_port)
297
+ .db_filename(self.db_filename)
298
+ .ui(self.ui)
299
+ .log((self.log.format, self.log.level))
300
+ .extra_args(self.extra_args)
301
+ .build()
302
+ .context("Invalid Dev Server config")?;
303
+
304
+ Ok(config)
305
+ }
306
+ }
307
+
308
+ impl From<EphemeralServerExecutableConfig> for EphemeralExe {
309
+ fn from(val: EphemeralServerExecutableConfig) -> Self {
310
+ match val {
311
+ EphemeralServerExecutableConfig::CachedDownload(config) => Self::CachedDownload {
312
+ version: match config.version.as_str() {
313
+ "default" => EphemeralExeVersion::SDKDefault {
314
+ sdk_name: config.sdk_name,
315
+ sdk_version: config.sdk_version,
316
+ },
317
+ _ => EphemeralExeVersion::Fixed(config.version),
318
+ },
319
+ dest_dir: config.download_dir,
320
+ ttl: Some(config.ttl),
321
+ },
322
+ EphemeralServerExecutableConfig::ExistingPath(config) => {
323
+ Self::ExistingPath(config.path)
324
+ }
325
+ }
67
326
  }
68
327
  }
69
- Ok(cx.undefined())
70
328
  }