@temporalio/core-bridge 0.19.2 → 0.20.2

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 (125) hide show
  1. package/Cargo.lock +90 -157
  2. package/Cargo.toml +1 -0
  3. package/index.d.ts +11 -27
  4. package/package.json +3 -3
  5. package/releases/aarch64-apple-darwin/index.node +0 -0
  6. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  7. package/releases/x86_64-apple-darwin/index.node +0 -0
  8. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  9. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  10. package/sdk-core/.buildkite/docker/Dockerfile +1 -1
  11. package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
  12. package/sdk-core/.cargo/config.toml +1 -0
  13. package/sdk-core/CODEOWNERS +1 -1
  14. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +119 -86
  15. package/sdk-core/bridge-ffi/src/lib.rs +311 -315
  16. package/sdk-core/bridge-ffi/src/wrappers.rs +108 -113
  17. package/sdk-core/client/Cargo.toml +13 -9
  18. package/sdk-core/client/LICENSE.txt +23 -0
  19. package/sdk-core/client/src/lib.rs +286 -174
  20. package/sdk-core/client/src/metrics.rs +86 -12
  21. package/sdk-core/client/src/raw.rs +566 -0
  22. package/sdk-core/client/src/retry.rs +137 -99
  23. package/sdk-core/core/Cargo.toml +15 -10
  24. package/sdk-core/core/LICENSE.txt +23 -0
  25. package/sdk-core/core/benches/workflow_replay.rs +79 -0
  26. package/sdk-core/core/src/abstractions.rs +38 -0
  27. package/sdk-core/core/src/core_tests/activity_tasks.rs +108 -182
  28. package/sdk-core/core/src/core_tests/child_workflows.rs +16 -11
  29. package/sdk-core/core/src/core_tests/determinism.rs +24 -12
  30. package/sdk-core/core/src/core_tests/local_activities.rs +53 -27
  31. package/sdk-core/core/src/core_tests/mod.rs +30 -43
  32. package/sdk-core/core/src/core_tests/queries.rs +82 -81
  33. package/sdk-core/core/src/core_tests/workers.rs +111 -296
  34. package/sdk-core/core/src/core_tests/workflow_cancels.rs +4 -4
  35. package/sdk-core/core/src/core_tests/workflow_tasks.rs +257 -242
  36. package/sdk-core/core/src/lib.rs +73 -318
  37. package/sdk-core/core/src/pollers/mod.rs +4 -6
  38. package/sdk-core/core/src/pollers/poll_buffer.rs +20 -14
  39. package/sdk-core/core/src/protosext/mod.rs +7 -10
  40. package/sdk-core/core/src/replay/mod.rs +11 -150
  41. package/sdk-core/core/src/telemetry/metrics.rs +35 -2
  42. package/sdk-core/core/src/telemetry/mod.rs +49 -16
  43. package/sdk-core/core/src/telemetry/prometheus_server.rs +14 -35
  44. package/sdk-core/core/src/test_help/mod.rs +104 -170
  45. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +57 -34
  46. package/sdk-core/core/src/worker/activities/local_activities.rs +95 -23
  47. package/sdk-core/core/src/worker/activities.rs +23 -16
  48. package/sdk-core/core/src/worker/client/mocks.rs +86 -0
  49. package/sdk-core/core/src/worker/client.rs +209 -0
  50. package/sdk-core/core/src/worker/mod.rs +207 -108
  51. package/sdk-core/core/src/workflow/driven_workflow.rs +21 -6
  52. package/sdk-core/core/src/workflow/history_update.rs +107 -24
  53. package/sdk-core/core/src/workflow/machines/activity_state_machine.rs +2 -3
  54. package/sdk-core/core/src/workflow/machines/child_workflow_state_machine.rs +2 -3
  55. package/sdk-core/core/src/workflow/machines/mod.rs +20 -17
  56. package/sdk-core/core/src/workflow/machines/signal_external_state_machine.rs +56 -19
  57. package/sdk-core/core/src/workflow/machines/transition_coverage.rs +5 -0
  58. package/sdk-core/core/src/workflow/machines/upsert_search_attributes_state_machine.rs +230 -22
  59. package/sdk-core/core/src/workflow/machines/workflow_machines.rs +81 -115
  60. package/sdk-core/core/src/workflow/machines/workflow_task_state_machine.rs +4 -4
  61. package/sdk-core/core/src/workflow/mod.rs +13 -1
  62. package/sdk-core/core/src/workflow/workflow_tasks/concurrency_manager.rs +70 -11
  63. package/sdk-core/core/src/workflow/workflow_tasks/mod.rs +65 -41
  64. package/sdk-core/core-api/Cargo.toml +9 -1
  65. package/sdk-core/core-api/LICENSE.txt +23 -0
  66. package/sdk-core/core-api/src/errors.rs +7 -38
  67. package/sdk-core/core-api/src/lib.rs +44 -52
  68. package/sdk-core/core-api/src/worker.rs +10 -2
  69. package/sdk-core/etc/deps.svg +127 -96
  70. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +11 -7
  71. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +10 -0
  72. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +6 -1
  73. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +6 -0
  74. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +6 -0
  75. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +2 -1
  76. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +3 -0
  77. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +12 -0
  78. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +25 -0
  79. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -0
  80. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +19 -35
  81. package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +2 -6
  82. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +53 -11
  83. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +14 -7
  84. package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +3 -5
  85. package/sdk-core/sdk/Cargo.toml +16 -2
  86. package/sdk-core/sdk/LICENSE.txt +23 -0
  87. package/sdk-core/sdk/src/interceptors.rs +11 -0
  88. package/sdk-core/sdk/src/lib.rs +139 -151
  89. package/sdk-core/sdk/src/workflow_context/options.rs +86 -1
  90. package/sdk-core/sdk/src/workflow_context.rs +36 -17
  91. package/sdk-core/sdk/src/workflow_future.rs +19 -25
  92. package/sdk-core/sdk-core-protos/Cargo.toml +1 -1
  93. package/sdk-core/sdk-core-protos/build.rs +1 -0
  94. package/sdk-core/sdk-core-protos/src/history_info.rs +17 -4
  95. package/sdk-core/sdk-core-protos/src/lib.rs +251 -47
  96. package/sdk-core/test-utils/Cargo.toml +3 -1
  97. package/sdk-core/test-utils/src/canned_histories.rs +27 -0
  98. package/sdk-core/test-utils/src/histfetch.rs +3 -3
  99. package/sdk-core/test-utils/src/lib.rs +223 -68
  100. package/sdk-core/tests/integ_tests/client_tests.rs +27 -4
  101. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +93 -14
  102. package/sdk-core/tests/integ_tests/polling_tests.rs +18 -12
  103. package/sdk-core/tests/integ_tests/queries_tests.rs +50 -53
  104. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +117 -103
  105. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +8 -1
  106. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +10 -5
  107. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +7 -1
  108. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +32 -9
  109. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +7 -1
  110. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +76 -15
  111. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +19 -3
  112. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +39 -42
  113. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +84 -0
  114. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +30 -8
  115. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +21 -6
  116. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +26 -16
  117. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +66 -0
  118. package/sdk-core/tests/integ_tests/workflow_tests.rs +78 -74
  119. package/sdk-core/tests/load_tests.rs +9 -6
  120. package/sdk-core/tests/main.rs +43 -10
  121. package/src/conversions.rs +7 -12
  122. package/src/lib.rs +322 -357
  123. package/sdk-core/client/src/mocks.rs +0 -167
  124. package/sdk-core/core/src/worker/dispatcher.rs +0 -171
  125. package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +0 -61
package/src/lib.rs CHANGED
@@ -10,18 +10,18 @@ use prost::Message;
10
10
  use std::{
11
11
  fmt::Display,
12
12
  future::Future,
13
- ops::Deref,
14
13
  sync::Arc,
15
14
  time::{Duration, SystemTime, UNIX_EPOCH},
16
15
  };
16
+ use temporal_client::{
17
+ AnyClient, ClientInitError, ConfiguredClient, WorkflowServiceClientWithMetrics,
18
+ };
17
19
  use temporal_sdk_core::{
18
20
  api::{
19
- errors::{
20
- CompleteActivityError, CompleteWfError, CoreInitError, PollActivityError, PollWfError,
21
- },
22
- Core,
21
+ errors::{CompleteActivityError, CompleteWfError, PollActivityError, PollWfError},
22
+ Worker as CoreWorker,
23
23
  },
24
- init,
24
+ fetch_global_buffered_logs, init_replay_worker, init_worker,
25
25
  protos::{
26
26
  coresdk::{
27
27
  workflow_completion::WorkflowActivationCompletion, ActivityHeartbeat,
@@ -29,39 +29,49 @@ use temporal_sdk_core::{
29
29
  },
30
30
  temporal::api::history::v1::History,
31
31
  },
32
- replay::{init_core_replay, ReplayCore, ReplayCoreImpl},
33
- CoreInitOptionsBuilder, CoreSDK, WorkerConfig,
32
+ telemetry_init, ClientOptions, RetryClient, WorkerConfig,
34
33
  };
35
34
  use tokio::{
36
35
  runtime::Runtime,
37
- sync::mpsc::{unbounded_channel, UnboundedSender},
36
+ sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
38
37
  };
39
38
 
39
+ type RawClient = RetryClient<ConfiguredClient<WorkflowServiceClientWithMetrics>>;
40
+
40
41
  /// A request from JS to bridge to core
41
- #[derive(Debug)]
42
42
  enum Request {
43
- /// A request to shutdown Core, any registered workers will be shutdown as well.
44
- /// Breaks from the thread loop.
43
+ /// A request to shutdown the runtime, breaks from the thread loop.
45
44
  Shutdown {
46
45
  /// Used to send the result back into JS
47
46
  callback: Root<JsFunction>,
48
47
  },
48
+ /// A request to create a client in a runtime
49
+ CreateClient {
50
+ runtime: Arc<RuntimeHandle>,
51
+ options: ClientOptions,
52
+ /// Used to send the result back into JS
53
+ callback: Root<JsFunction>,
54
+ },
49
55
  /// A request to shutdown a worker, the worker instance will remain active to
50
56
  /// allow draining of pending tasks
51
57
  ShutdownWorker {
52
- task_queue: String,
58
+ worker: Arc<dyn CoreWorker>,
53
59
  /// Used to send the result back into JS
54
60
  callback: Root<JsFunction>,
55
61
  },
56
- /// A request to register a new Worker against Core
57
- RegisterWorker {
62
+ /// A request to create a new Worker using a connected client
63
+ InitWorker {
64
+ runtime: Arc<RuntimeHandle>,
58
65
  /// Worker configuration e.g. limits and task queue
59
66
  config: WorkerConfig,
67
+ /// A client created with a [CreateClient] request
68
+ client: Arc<RawClient>,
60
69
  /// Used to send the result back into JS
61
70
  callback: Root<JsFunction>,
62
71
  },
63
- /// A request to register a replay worker. Will only work against a replay core instance.
64
- RegisterReplayWorker {
72
+ /// A request to register a replay worker
73
+ InitReplayWorker {
74
+ runtime: Arc<RuntimeHandle>,
65
75
  /// Worker configuration. Must have unique task queue name.
66
76
  config: WorkerConfig,
67
77
  /// The history this worker should replay
@@ -71,14 +81,14 @@ enum Request {
71
81
  },
72
82
  /// A request to poll for workflow activations
73
83
  PollWorkflowActivation {
74
- /// Name of queue to poll on
75
- queue_name: String,
84
+ worker: Arc<dyn CoreWorker>,
76
85
  otel_span: SpanContext,
77
86
  /// Used to send the result back into JS
78
87
  callback: Root<JsFunction>,
79
88
  },
80
89
  /// A request to complete a single workflow activation
81
90
  CompleteWorkflowActivation {
91
+ worker: Arc<dyn CoreWorker>,
82
92
  completion: WorkflowActivationCompletion,
83
93
  otel_span: SpanContext,
84
94
  /// Used to send the result back into JS
@@ -86,21 +96,24 @@ enum Request {
86
96
  },
87
97
  /// A request to poll for activity tasks
88
98
  PollActivityTask {
89
- /// Name of queue to poll on
90
- queue_name: String,
99
+ worker: Arc<dyn CoreWorker>,
91
100
  otel_span: SpanContext,
92
101
  /// Used to report completion or error back into JS
93
102
  callback: Root<JsFunction>,
94
103
  },
95
104
  /// A request to complete a single activity task
96
105
  CompleteActivityTask {
106
+ worker: Arc<dyn CoreWorker>,
97
107
  completion: ActivityTaskCompletion,
98
108
  otel_span: SpanContext,
99
109
  /// Used to send the result back into JS
100
110
  callback: Root<JsFunction>,
101
111
  },
102
112
  /// A request to send a heartbeat from a running activity
103
- RecordActivityHeartbeat { heartbeat: ActivityHeartbeat },
113
+ RecordActivityHeartbeat {
114
+ worker: Arc<dyn CoreWorker>,
115
+ heartbeat: ActivityHeartbeat,
116
+ },
104
117
  /// A request to drain logs from core so they can be emitted in node
105
118
  PollLogs {
106
119
  /// Logs are sent to this function
@@ -108,40 +121,34 @@ enum Request {
108
121
  },
109
122
  }
110
123
 
111
- #[derive(Clone)]
112
- struct CoreHandle {
124
+ struct RuntimeHandle {
113
125
  sender: UnboundedSender<Request>,
114
126
  }
115
- /// Box it so we can use Core from JS
116
- type BoxedCore = JsBox<CoreHandle>;
117
- impl Finalize for CoreHandle {}
127
+
128
+ /// Box it so we can use the runtime from JS
129
+ type BoxedRuntime = JsBox<Arc<RuntimeHandle>>;
130
+ impl Finalize for RuntimeHandle {}
131
+
132
+ #[derive(Clone)]
133
+ struct Client {
134
+ runtime: Arc<RuntimeHandle>,
135
+ core_client: Arc<RawClient>,
136
+ }
137
+
138
+ type BoxedClient = JsBox<Client>;
139
+ impl Finalize for Client {}
118
140
 
119
141
  /// Worker struct, hold a reference for the channel sender responsible for sending requests from
120
142
  /// JS to a bridge thread which forwards them to core
121
143
  struct Worker {
122
- core: CoreHandle,
123
- queue: String,
144
+ runtime: Arc<RuntimeHandle>,
145
+ core_worker: Arc<dyn CoreWorker>,
124
146
  }
147
+
125
148
  /// Box it so we can use Worker from JS
126
149
  type BoxedWorker = JsBox<Worker>;
127
150
  impl Finalize for Worker {}
128
151
 
129
- enum CoreType {
130
- Real(CoreSDK),
131
- Replay(ReplayCoreImpl),
132
- }
133
-
134
- impl Deref for CoreType {
135
- type Target = dyn Core;
136
-
137
- fn deref(&self) -> &Self::Target {
138
- match self {
139
- CoreType::Real(ref r) => r,
140
- CoreType::Replay(ref r) => r,
141
- }
142
- }
143
- }
144
-
145
152
  /// Lazy-inits or returns a global tokio runtime that we use for interactions with Core(s)
146
153
  fn tokio_runtime() -> &'static Runtime {
147
154
  static INSTANCE: OnceCell<Runtime> = OnceCell::new();
@@ -183,7 +190,7 @@ where
183
190
  });
184
191
  }
185
192
 
186
- /// Call [callback] with given error
193
+ /// Call `callback` with given error
187
194
  fn callback_with_error<'a, C, E, F>(
188
195
  cx: &mut C,
189
196
  callback: Handle<JsFunction>,
@@ -202,6 +209,7 @@ where
202
209
  Ok(())
203
210
  }
204
211
 
212
+ /// Call `callback` with an UnexpectedError created from `err`
205
213
  fn callback_with_unexpected_error<'a, C, E>(
206
214
  cx: &mut C,
207
215
  callback: Handle<JsFunction>,
@@ -242,234 +250,213 @@ async fn void_future_to_js<E, F, ER, EF>(
242
250
 
243
251
  /// Builds a tokio runtime and starts polling on [Request]s via an internal channel.
244
252
  /// Bridges requests from JS to core and sends responses back to JS using a neon::EventQueue.
245
- /// Blocks current thread until a [BreakPoller] request is received in channel.
246
- fn start_bridge_loop(
247
- core_init_fut: impl Future<Output = Result<CoreType, CoreInitError>>,
248
- event_queue: Arc<EventQueue>,
249
- callback: Root<JsFunction>,
250
- ) {
251
- let (sender, mut receiver) = unbounded_channel::<Request>();
252
-
253
+ /// Blocks current thread until a [Shutdown] request is received in channel.
254
+ fn start_bridge_loop(event_queue: Arc<EventQueue>, receiver: &mut UnboundedReceiver<Request>) {
253
255
  tokio_runtime().block_on(async {
254
- match core_init_fut.await {
255
- Err(err) => {
256
- send_error(event_queue.clone(), callback, |cx| match err {
257
- CoreInitError::GatewayInitError(err) => TRANSPORT_ERROR.from_error(cx, err),
258
- e @ CoreInitError::TelemetryInitError(_) => UNEXPECTED_ERROR.from_error(cx, e),
259
- });
260
- }
261
- Ok(result) => {
262
- let core = Arc::new(result);
263
- let core_handle = CoreHandle { sender };
264
- // Clone once to send back to JS via event queue
265
- let cloned_core_handle = core_handle.clone();
266
- send_result(event_queue.clone(), callback, |cx| {
267
- Ok(cx.boxed(cloned_core_handle))
268
- });
256
+ loop {
257
+ let request_option = receiver.recv().await;
258
+ let request = match request_option {
259
+ None => break,
260
+ Some(request) => request,
261
+ };
269
262
 
270
- loop {
271
- let request_option = receiver.recv().await;
272
- let request = match request_option {
273
- None => break,
274
- Some(request) => request,
275
- };
263
+ let event_queue = event_queue.clone();
276
264
 
277
- let core = core.clone();
278
- let event_queue = event_queue.clone();
279
-
280
- match request {
281
- Request::Shutdown { callback } => {
282
- void_future_to_js(
283
- event_queue,
284
- callback,
285
- async move {
286
- core.shutdown().await;
287
- // Wrap the empty result in a valid Result object
288
- let result: Result<(), String> = Ok(());
289
- result
290
- },
291
- |cx, err| UNEXPECTED_ERROR.from_error(cx, err),
292
- )
293
- .await;
294
- break;
295
- }
296
- Request::PollLogs { callback } => {
297
- let logs = core.fetch_buffered_logs();
298
- send_result(event_queue.clone(), callback, |cx| {
299
- let logarr = cx.empty_array();
300
- for (i, cl) in logs.into_iter().enumerate() {
301
- // Not much to do here except for panic when there's an
302
- // error here.
303
- let logobj = cx.empty_object();
304
- let level = cx.string(cl.level.to_string());
305
- logobj.set(cx, "level", level).unwrap();
306
- let ts = system_time_to_js(cx, cl.timestamp).unwrap();
307
- logobj.set(cx, "timestamp", ts).unwrap();
308
- let msg = cx.string(cl.message);
309
- logobj.set(cx, "message", msg).unwrap();
310
- logarr.set(cx, i as u32, logobj).unwrap();
265
+ match request {
266
+ Request::Shutdown { callback } => {
267
+ send_result(event_queue, callback, |cx| Ok(cx.undefined()));
268
+ break;
269
+ }
270
+ Request::CreateClient {
271
+ runtime,
272
+ options,
273
+ callback,
274
+ } => {
275
+ // `metrics_meter` (second arg) can be None here since we don't use the
276
+ // returned client directly at the moment, when we repurpose the client to be
277
+ // used by a Worker, `init_worker` will attach the correct metrics meter for
278
+ // us.
279
+ match options.connect_no_namespace(None).await {
280
+ Err(err) => {
281
+ send_error(event_queue.clone(), callback, |cx| match err {
282
+ ClientInitError::SystemInfoCallError(e) => TRANSPORT_ERROR
283
+ .from_error(cx, format!("Failed to call GetSystemInfo: {}", e)),
284
+ ClientInitError::TonicTransportError(e) => {
285
+ TRANSPORT_ERROR.from_error(cx, e)
286
+ }
287
+ ClientInitError::InvalidUri(e) => {
288
+ Ok(JsError::type_error(cx, format!("{}", e))?.upcast())
311
289
  }
312
- Ok(logarr)
313
290
  });
314
291
  }
315
- Request::ShutdownWorker {
316
- task_queue,
317
- callback,
318
- } => {
319
- tokio::spawn(void_future_to_js(
320
- event_queue,
321
- callback,
322
- async move {
323
- core.shutdown_worker(&task_queue).await;
324
- // Wrap the empty result in a valid Result object
325
- let result: Result<(), String> = Ok(());
326
- result
327
- },
328
- |cx, err| UNEXPECTED_ERROR.from_error(cx, err),
329
- ));
292
+ Ok(client) => {
293
+ send_result(event_queue.clone(), callback, |cx| {
294
+ Ok(cx.boxed(Client {
295
+ runtime,
296
+ core_client: Arc::new(client),
297
+ }))
298
+ });
330
299
  }
331
- Request::RegisterWorker { config, callback } => {
332
- let task_queue = config.task_queue.clone();
333
- match core.register_worker(config) {
334
- Ok(_) => {
335
- let core_handle = core_handle.clone();
336
- send_result(event_queue.clone(), callback, |cx| {
337
- Ok(cx.boxed(Worker {
338
- core: core_handle,
339
- queue: task_queue,
340
- }))
341
- })
342
- }
343
- Err(err) => send_error(event_queue.clone(), callback, |cx| {
344
- UNEXPECTED_ERROR.from_error(cx, err)
345
- }),
346
- };
300
+ }
301
+ }
302
+ Request::PollLogs { callback } => {
303
+ let logs = fetch_global_buffered_logs();
304
+ send_result(event_queue.clone(), callback, |cx| {
305
+ let logarr = cx.empty_array();
306
+ for (i, cl) in logs.into_iter().enumerate() {
307
+ // Not much to do here except for panic when there's an
308
+ // error here.
309
+ let logobj = cx.empty_object();
310
+ let level = cx.string(cl.level.to_string());
311
+ logobj.set(cx, "level", level).unwrap();
312
+ let ts = system_time_to_js(cx, cl.timestamp).unwrap();
313
+ logobj.set(cx, "timestamp", ts).unwrap();
314
+ let msg = cx.string(cl.message);
315
+ logobj.set(cx, "message", msg).unwrap();
316
+ logarr.set(cx, i as u32, logobj).unwrap();
347
317
  }
348
- Request::RegisterReplayWorker {
349
- config,
350
- history,
351
- callback,
352
- } => match *core {
353
- CoreType::Real(_) => {
354
- panic!(
355
- "Attempted to use a real core instance to register a \
356
- replay worker. This is a bug in the TS SDK."
357
- )
358
- }
359
- CoreType::Replay(ref rc) => {
360
- let task_queue = config.task_queue.clone();
361
- match rc.make_replay_worker(config, &history) {
362
- Ok(_) => {
363
- let core_handle = core_handle.clone();
364
- send_result(event_queue.clone(), callback, |cx| {
365
- Ok(cx.boxed(Worker {
366
- core: core_handle,
367
- queue: task_queue,
368
- }))
369
- })
370
- }
371
- Err(err) => send_error(event_queue.clone(), callback, |cx| {
372
- UNEXPECTED_ERROR.from_error(cx, err)
373
- }),
374
- };
375
- }
318
+ Ok(logarr)
319
+ });
320
+ }
321
+ Request::ShutdownWorker { worker, callback } => {
322
+ tokio::spawn(void_future_to_js(
323
+ event_queue,
324
+ callback,
325
+ async move {
326
+ worker.shutdown().await;
327
+ // Wrap the empty result in a valid Result object
328
+ let result: Result<(), String> = Ok(());
329
+ result
376
330
  },
377
- Request::PollWorkflowActivation {
378
- queue_name,
331
+ |cx, err| UNEXPECTED_ERROR.from_error(cx, err),
332
+ ));
333
+ }
334
+ Request::InitWorker {
335
+ runtime,
336
+ config,
337
+ client,
338
+ callback,
339
+ } => {
340
+ let client = (*client).clone();
341
+ let worker =
342
+ init_worker(config, AnyClient::LowLevel(Box::new(client.into_inner())));
343
+ send_result(event_queue.clone(), callback, |cx| {
344
+ Ok(cx.boxed(Worker {
345
+ core_worker: Arc::new(worker),
346
+ runtime,
347
+ }))
348
+ });
349
+ }
350
+ Request::InitReplayWorker {
351
+ runtime,
352
+ config,
353
+ history,
354
+ callback,
355
+ } => {
356
+ match init_replay_worker(config, &history) {
357
+ Ok(worker) => send_result(event_queue.clone(), callback, |cx| {
358
+ Ok(cx.boxed(Worker {
359
+ core_worker: Arc::new(worker),
360
+ runtime,
361
+ }))
362
+ }),
363
+ Err(err) => send_error(event_queue.clone(), callback, |cx| {
364
+ UNEXPECTED_ERROR.from_error(cx, err)
365
+ }),
366
+ };
367
+ }
368
+ Request::PollWorkflowActivation {
369
+ worker,
370
+ otel_span,
371
+ callback,
372
+ } => {
373
+ tokio::spawn(async move {
374
+ handle_poll_workflow_activation_request(
375
+ &*worker,
379
376
  otel_span,
377
+ event_queue,
380
378
  callback,
381
- } => {
382
- // dbg!(&queue_name);
383
- tokio::spawn(async move {
384
- handle_poll_workflow_activation_request(
385
- queue_name,
386
- otel_span,
387
- core.as_ref().deref(),
388
- event_queue,
389
- callback,
390
- )
391
- .await
392
- });
393
- }
394
- Request::PollActivityTask {
395
- queue_name,
379
+ )
380
+ .await
381
+ });
382
+ }
383
+ Request::PollActivityTask {
384
+ worker,
385
+ otel_span,
386
+ callback,
387
+ } => {
388
+ tokio::spawn(async move {
389
+ handle_poll_activity_task_request(
390
+ &*worker,
396
391
  otel_span,
392
+ event_queue,
397
393
  callback,
398
- } => {
399
- tokio::spawn(async move {
400
- handle_poll_activity_task_request(
401
- queue_name,
402
- otel_span,
403
- core.as_ref().deref(),
404
- event_queue,
405
- callback,
406
- )
394
+ )
395
+ .await
396
+ });
397
+ }
398
+ Request::CompleteWorkflowActivation {
399
+ worker,
400
+ completion,
401
+ otel_span,
402
+ callback,
403
+ } => {
404
+ let otel_ctx =
405
+ opentelemetry::Context::new().with_remote_span_context(otel_span);
406
+ tokio::spawn(void_future_to_js(
407
+ event_queue,
408
+ callback,
409
+ async move {
410
+ worker
411
+ .complete_workflow_activation(completion)
412
+ .with_context(otel_ctx)
407
413
  .await
408
- });
409
- }
410
- Request::CompleteWorkflowActivation {
411
- completion,
412
- otel_span,
413
- callback,
414
- } => {
415
- let otel_ctx =
416
- opentelemetry::Context::new().with_remote_span_context(otel_span);
417
- tokio::spawn(void_future_to_js(
418
- event_queue,
419
- callback,
420
- async move {
421
- core.complete_workflow_activation(completion)
422
- .with_context(otel_ctx)
423
- .await
424
- },
425
- |cx, err| match err {
426
- CompleteWfError::NoWorkerForQueue(queue_name) => {
427
- let args = vec![cx.string(queue_name).upcast()];
428
- NO_WORKER_ERROR.construct(cx, args)
429
- }
430
- CompleteWfError::TonicError(_) => {
431
- TRANSPORT_ERROR.from_error(cx, err)
432
- }
433
- CompleteWfError::MalformedWorkflowCompletion {
434
- reason, ..
435
- } => Ok(JsError::type_error(cx, reason)?.upcast()),
436
- },
437
- ));
438
- }
439
- Request::CompleteActivityTask {
440
- completion,
441
- otel_span,
442
- callback,
443
- } => {
444
- let otel_ctx =
445
- opentelemetry::Context::new().with_remote_span_context(otel_span);
446
- tokio::spawn(void_future_to_js(
447
- event_queue,
448
- callback,
449
- async move {
450
- core.complete_activity_task(completion)
451
- .with_context(otel_ctx)
452
- .await
453
- },
454
- |cx, err| match err {
455
- CompleteActivityError::MalformedActivityCompletion {
456
- reason,
457
- ..
458
- } => Ok(JsError::type_error(cx, reason)?.upcast()),
459
- CompleteActivityError::TonicError(_) => {
460
- TRANSPORT_ERROR.from_error(cx, err)
461
- }
462
- CompleteActivityError::NoWorkerForQueue(queue_name) => {
463
- let args = vec![cx.string(queue_name).upcast()];
464
- NO_WORKER_ERROR.construct(cx, args)
465
- }
466
- },
467
- ));
468
- }
469
- Request::RecordActivityHeartbeat { heartbeat } => {
470
- core.record_activity_heartbeat(heartbeat)
471
- }
472
- }
414
+ },
415
+ |cx, err| match err {
416
+ CompleteWfError::NoWorkerForQueue(queue_name) => {
417
+ let args = vec![cx.string(queue_name).upcast()];
418
+ NO_WORKER_ERROR.construct(cx, args)
419
+ }
420
+ CompleteWfError::TonicError(_) => TRANSPORT_ERROR.from_error(cx, err),
421
+ CompleteWfError::MalformedWorkflowCompletion { reason, .. } => {
422
+ Ok(JsError::type_error(cx, reason)?.upcast())
423
+ }
424
+ },
425
+ ));
426
+ }
427
+ Request::CompleteActivityTask {
428
+ worker,
429
+ completion,
430
+ otel_span,
431
+ callback,
432
+ } => {
433
+ let otel_ctx =
434
+ opentelemetry::Context::new().with_remote_span_context(otel_span);
435
+ tokio::spawn(void_future_to_js(
436
+ event_queue,
437
+ callback,
438
+ async move {
439
+ worker
440
+ .complete_activity_task(completion)
441
+ .with_context(otel_ctx)
442
+ .await
443
+ },
444
+ |cx, err| match err {
445
+ CompleteActivityError::MalformedActivityCompletion {
446
+ reason, ..
447
+ } => Ok(JsError::type_error(cx, reason)?.upcast()),
448
+ CompleteActivityError::TonicError(_) => {
449
+ TRANSPORT_ERROR.from_error(cx, err)
450
+ }
451
+ CompleteActivityError::NoWorkerForQueue(queue_name) => {
452
+ let args = vec![cx.string(queue_name).upcast()];
453
+ NO_WORKER_ERROR.construct(cx, args)
454
+ }
455
+ },
456
+ ));
457
+ }
458
+ Request::RecordActivityHeartbeat { worker, heartbeat } => {
459
+ worker.record_activity_heartbeat(heartbeat)
473
460
  }
474
461
  }
475
462
  }
@@ -478,15 +465,14 @@ fn start_bridge_loop(
478
465
 
479
466
  /// Called within the poll loop thread, calls core and triggers JS callback with result
480
467
  async fn handle_poll_workflow_activation_request(
481
- queue_name: String,
468
+ worker: &dyn CoreWorker,
482
469
  span_context: SpanContext,
483
- core: &dyn Core,
484
470
  event_queue: Arc<EventQueue>,
485
471
  callback: Root<JsFunction>,
486
472
  ) {
487
473
  let otel_ctx = opentelemetry::Context::new().with_remote_span_context(span_context);
488
- match core
489
- .poll_workflow_activation(queue_name.as_str())
474
+ match worker
475
+ .poll_workflow_activation()
490
476
  .with_context(otel_ctx)
491
477
  .await
492
478
  {
@@ -507,12 +493,7 @@ async fn handle_poll_workflow_activation_request(
507
493
  send_error(event_queue, callback, move |cx| match err {
508
494
  PollWfError::ShutDown => SHUTDOWN_ERROR.from_error(cx, err),
509
495
  PollWfError::AutocompleteError(CompleteWfError::NoWorkerForQueue(_)) => {
510
- UNEXPECTED_ERROR
511
- .from_error(cx, format!("No worker registered for queue {}", queue_name))
512
- }
513
- PollWfError::NoWorkerForQueue(queue_name) => {
514
- let args = vec![cx.string(queue_name).upcast()];
515
- NO_WORKER_ERROR.construct(cx, args)
496
+ UNEXPECTED_ERROR.from_error(cx, "TODO this error shouldn't exist")
516
497
  }
517
498
  PollWfError::TonicError(_)
518
499
  | PollWfError::AutocompleteError(CompleteWfError::TonicError(_)) => {
@@ -529,18 +510,13 @@ async fn handle_poll_workflow_activation_request(
529
510
 
530
511
  /// Called within the poll loop thread, calls core and triggers JS callback with result
531
512
  async fn handle_poll_activity_task_request(
532
- queue_name: String,
513
+ worker: &dyn CoreWorker,
533
514
  span_context: SpanContext,
534
- core: &dyn Core,
535
515
  event_queue: Arc<EventQueue>,
536
516
  callback: Root<JsFunction>,
537
517
  ) {
538
518
  let otel_ctx = opentelemetry::Context::new().with_remote_span_context(span_context);
539
- match core
540
- .poll_activity_task(queue_name.as_str())
541
- .with_context(otel_ctx)
542
- .await
543
- {
519
+ match worker.poll_activity_task().with_context(otel_ctx).await {
544
520
  Ok(task) => {
545
521
  send_result(event_queue, callback, move |cx| {
546
522
  let len = task.encoded_len();
@@ -557,10 +533,6 @@ async fn handle_poll_activity_task_request(
557
533
  Err(err) => {
558
534
  send_error(event_queue, callback, move |cx| match err {
559
535
  PollActivityError::ShutDown => SHUTDOWN_ERROR.from_error(cx, err),
560
- PollActivityError::NoWorkerForQueue(queue_name) => {
561
- let args = vec![cx.string(queue_name).upcast()];
562
- NO_WORKER_ERROR.construct(cx, args)
563
- }
564
536
  PollActivityError::TonicError(_) => TRANSPORT_ERROR.from_error(cx, err),
565
537
  });
566
538
  }
@@ -569,61 +541,63 @@ async fn handle_poll_activity_task_request(
569
541
 
570
542
  // Below are functions exported to JS
571
543
 
572
- /// Create a new core instance asynchronously.
544
+ /// Initialize Core global telemetry.
545
+ /// This should typically be called once on process startup.
546
+ fn init_telemetry(mut cx: FunctionContext) -> JsResult<JsUndefined> {
547
+ let telemetry_options = cx.argument::<JsObject>(0)?.as_telemetry_options(&mut cx)?;
548
+ telemetry_init(&telemetry_options).map_err(|err| {
549
+ cx.throw_type_error::<String, ()>(format!("{}", err))
550
+ .unwrap_err()
551
+ })?;
552
+ Ok(cx.undefined())
553
+ }
554
+
555
+ /// Create the tokio runtime required to run Core.
573
556
  /// Immediately spawns a poller thread that will block on [Request]s
574
- /// Core is returned to JS using supplied callback
575
- fn core_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
576
- let core_options = cx.argument::<JsObject>(0)?;
577
- let server_options = core_options
578
- .get(&mut cx, "serverOptions")?
579
- .downcast_or_throw::<JsObject, _>(&mut cx)?;
580
- let telem_options = core_options
581
- .get(&mut cx, "telemetryOptions")?
582
- .downcast_or_throw::<JsObject, _>(&mut cx)?;
583
-
584
- let gateway_opts = server_options.as_server_gateway_options(&mut cx)?;
585
- let telemetry_opts = telem_options.as_telemetry_options(&mut cx)?;
586
-
587
- let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
557
+ fn runtime_new(mut cx: FunctionContext) -> JsResult<BoxedRuntime> {
588
558
  let queue = Arc::new(cx.queue());
589
- let core_init_fut = async move {
590
- let opts = CoreInitOptionsBuilder::default()
591
- .gateway_opts(gateway_opts)
592
- .telemetry_opts(telemetry_opts)
593
- .build()
594
- .expect("Core init options must be valid");
595
- Ok(CoreType::Real(init(opts).await?))
596
- };
597
- std::thread::spawn(move || start_bridge_loop(core_init_fut, queue, callback));
559
+ let (sender, mut receiver) = unbounded_channel::<Request>();
598
560
 
599
- Ok(cx.undefined())
561
+ std::thread::spawn(move || start_bridge_loop(queue, &mut receiver));
562
+
563
+ Ok(cx.boxed(Arc::new(RuntimeHandle { sender })))
600
564
  }
601
565
 
602
- /// Create a new "replay" instance of core, which can only be used for replaying static histories.
603
- fn replay_core_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
604
- let telem_options = cx.argument::<JsObject>(0)?;
605
- let telem_options = telem_options.as_telemetry_options(&mut cx)?;
606
- let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
607
- let queue = Arc::new(cx.queue());
608
- let core_init_fut = async { Ok(CoreType::Replay(init_core_replay(telem_options))) };
609
- std::thread::spawn(move || start_bridge_loop(core_init_fut, queue, callback));
566
+ /// Create a connected gRPC client which can be used to initialize workers.
567
+ /// Client will be returned in the supplied `callback`.
568
+ fn client_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
569
+ let runtime = cx.argument::<BoxedRuntime>(0)?;
570
+ let client_options = cx.argument::<JsObject>(1)?.as_client_options(&mut cx)?;
571
+ let callback = cx.argument::<JsFunction>(2)?;
572
+
573
+ let request = Request::CreateClient {
574
+ runtime: (**runtime).clone(),
575
+ options: client_options,
576
+ callback: callback.root(&mut cx),
577
+ };
578
+ if let Err(err) = runtime.sender.send(request) {
579
+ callback_with_unexpected_error(&mut cx, callback, err)?;
580
+ };
581
+
610
582
  Ok(cx.undefined())
611
583
  }
612
584
 
613
585
  /// Create a new worker asynchronously.
614
- /// Worker is registered on supplied core instance and returned to JS using supplied callback.
586
+ /// Worker uses the provided connection and returned to JS using supplied `callback`.
615
587
  fn worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
616
- let core = cx.argument::<BoxedCore>(0)?;
588
+ let client = cx.argument::<BoxedClient>(0)?;
617
589
  let worker_options = cx.argument::<JsObject>(1)?;
618
590
  let callback = cx.argument::<JsFunction>(2)?;
619
591
 
620
592
  let config = worker_options.as_worker_config(&mut cx)?;
621
593
 
622
- let request = Request::RegisterWorker {
594
+ let request = Request::InitWorker {
595
+ client: client.core_client.clone(),
596
+ runtime: client.runtime.clone(),
623
597
  config,
624
598
  callback: callback.root(&mut cx),
625
599
  };
626
- if let Err(err) = core.sender.send(request) {
600
+ if let Err(err) = client.runtime.sender.send(request) {
627
601
  callback_with_unexpected_error(&mut cx, callback, err)?;
628
602
  };
629
603
 
@@ -631,10 +605,9 @@ fn worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
631
605
  }
632
606
 
633
607
  /// Create a new replay worker asynchronously.
634
- /// Worker is registered on supplied core instance and returned to JS using supplied callback.
635
- /// The provided core instance must be a replay core.
608
+ /// Worker is returned to JS using supplied callback.
636
609
  fn replay_worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
637
- let core = cx.argument::<BoxedCore>(0)?;
610
+ let runtime = cx.argument::<BoxedRuntime>(0)?;
638
611
  let worker_options = cx.argument::<JsObject>(1)?;
639
612
  let history_binary = cx.argument::<JsArrayBuffer>(2)?;
640
613
  let callback = cx.argument::<JsFunction>(3)?;
@@ -645,12 +618,13 @@ fn replay_worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
645
618
  History::decode_length_delimited(data.as_slice::<u8>())
646
619
  }) {
647
620
  Ok(history) => {
648
- let request = Request::RegisterReplayWorker {
621
+ let request = Request::InitReplayWorker {
622
+ runtime: (**runtime).clone(),
649
623
  config,
650
624
  history,
651
625
  callback: callback.root(&mut cx),
652
626
  };
653
- if let Err(err) = core.sender.send(request) {
627
+ if let Err(err) = runtime.sender.send(request) {
654
628
  callback_with_unexpected_error(&mut cx, callback, err)?;
655
629
  };
656
630
  }
@@ -663,26 +637,26 @@ fn replay_worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
663
637
  }
664
638
 
665
639
  /// Shutdown the Core instance and break out of the thread loop
666
- fn core_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
667
- let core = cx.argument::<BoxedCore>(0)?;
640
+ fn runtime_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
641
+ let runtime = cx.argument::<BoxedRuntime>(0)?;
668
642
  let callback = cx.argument::<JsFunction>(1)?;
669
643
  let request = Request::Shutdown {
670
644
  callback: callback.root(&mut cx),
671
645
  };
672
- if let Err(err) = core.sender.send(request) {
646
+ if let Err(err) = runtime.sender.send(request) {
673
647
  callback_with_unexpected_error(&mut cx, callback, err)?;
674
648
  };
675
649
  Ok(cx.undefined())
676
650
  }
677
651
 
678
652
  /// Request to drain forwarded logs from core
679
- fn core_poll_logs(mut cx: FunctionContext) -> JsResult<JsUndefined> {
680
- let core = cx.argument::<BoxedCore>(0)?;
653
+ fn poll_logs(mut cx: FunctionContext) -> JsResult<JsUndefined> {
654
+ let runtime = cx.argument::<BoxedRuntime>(0)?;
681
655
  let callback = cx.argument::<JsFunction>(1)?;
682
656
  let request = Request::PollLogs {
683
657
  callback: callback.root(&mut cx),
684
658
  };
685
- if let Err(err) = core.sender.send(request) {
659
+ if let Err(err) = runtime.sender.send(request) {
686
660
  callback_with_unexpected_error(&mut cx, callback, err)?;
687
661
  }
688
662
  Ok(cx.undefined())
@@ -695,11 +669,11 @@ fn worker_poll_workflow_activation(mut cx: FunctionContext) -> JsResult<JsUndefi
695
669
  let otel_span = cx.argument::<JsObject>(1)?;
696
670
  let callback = cx.argument::<JsFunction>(2)?;
697
671
  let request = Request::PollWorkflowActivation {
698
- queue_name: worker.queue.clone(),
672
+ worker: worker.core_worker.clone(),
699
673
  otel_span: otel_span.as_otel_span_context(&mut cx)?,
700
674
  callback: callback.root(&mut cx),
701
675
  };
702
- if let Err(err) = worker.core.sender.send(request) {
676
+ if let Err(err) = worker.runtime.sender.send(request) {
703
677
  callback_with_unexpected_error(&mut cx, callback, err)?;
704
678
  }
705
679
  Ok(cx.undefined())
@@ -712,11 +686,11 @@ fn worker_poll_activity_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {
712
686
  let otel_span = cx.argument::<JsObject>(1)?;
713
687
  let callback = cx.argument::<JsFunction>(2)?;
714
688
  let request = Request::PollActivityTask {
715
- queue_name: worker.queue.clone(),
689
+ worker: worker.core_worker.clone(),
716
690
  otel_span: otel_span.as_otel_span_context(&mut cx)?,
717
691
  callback: callback.root(&mut cx),
718
692
  };
719
- if let Err(err) = worker.core.sender.send(request) {
693
+ if let Err(err) = worker.runtime.sender.send(request) {
720
694
  callback_with_unexpected_error(&mut cx, callback, err)?;
721
695
  }
722
696
  Ok(cx.undefined())
@@ -733,17 +707,13 @@ fn worker_complete_workflow_activation(mut cx: FunctionContext) -> JsResult<JsUn
733
707
  });
734
708
  match result {
735
709
  Ok(completion) => {
736
- // Add the task queue from our Worker
737
- let completion = WorkflowActivationCompletion {
738
- task_queue: worker.queue.clone(),
739
- ..completion
740
- };
741
710
  let request = Request::CompleteWorkflowActivation {
711
+ worker: worker.core_worker.clone(),
742
712
  completion,
743
713
  otel_span: otel_span.as_otel_span_context(&mut cx)?,
744
714
  callback: callback.root(&mut cx),
745
715
  };
746
- if let Err(err) = worker.core.sender.send(request) {
716
+ if let Err(err) = worker.runtime.sender.send(request) {
747
717
  callback_with_unexpected_error(&mut cx, callback, err)?;
748
718
  };
749
719
  }
@@ -765,17 +735,13 @@ fn worker_complete_activity_task(mut cx: FunctionContext) -> JsResult<JsUndefine
765
735
  });
766
736
  match result {
767
737
  Ok(completion) => {
768
- // Add the task queue from our Worker
769
- let completion = ActivityTaskCompletion {
770
- task_queue: worker.queue.clone(),
771
- ..completion
772
- };
773
738
  let request = Request::CompleteActivityTask {
739
+ worker: worker.core_worker.clone(),
774
740
  completion,
775
741
  otel_span: otel_span.as_otel_span_context(&mut cx)?,
776
742
  callback: callback.root(&mut cx),
777
743
  };
778
- if let Err(err) = worker.core.sender.send(request) {
744
+ if let Err(err) = worker.runtime.sender.send(request) {
779
745
  callback_with_unexpected_error(&mut cx, callback, err)?;
780
746
  };
781
747
  }
@@ -795,13 +761,11 @@ fn worker_record_activity_heartbeat(mut cx: FunctionContext) -> JsResult<JsUndef
795
761
  });
796
762
  match heartbeat {
797
763
  Ok(heartbeat) => {
798
- // Add the task queue from our Worker
799
- let heartbeat = ActivityHeartbeat {
800
- task_queue: worker.queue.clone(),
801
- ..heartbeat
764
+ let request = Request::RecordActivityHeartbeat {
765
+ worker: worker.core_worker.clone(),
766
+ heartbeat,
802
767
  };
803
- let request = Request::RecordActivityHeartbeat { heartbeat };
804
- match worker.core.sender.send(request) {
768
+ match worker.runtime.sender.send(request) {
805
769
  Err(err) => UNEXPECTED_ERROR
806
770
  .from_error(&mut cx, err)
807
771
  .and_then(|err| cx.throw(err)),
@@ -819,8 +783,8 @@ fn worker_record_activity_heartbeat(mut cx: FunctionContext) -> JsResult<JsUndef
819
783
  fn worker_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
820
784
  let worker = cx.argument::<BoxedWorker>(0)?;
821
785
  let callback = cx.argument::<JsFunction>(1)?;
822
- match worker.core.sender.send(Request::ShutdownWorker {
823
- task_queue: worker.queue.clone(),
786
+ match worker.runtime.sender.send(Request::ShutdownWorker {
787
+ worker: worker.core_worker.clone(),
824
788
  callback: callback.root(&mut cx),
825
789
  }) {
826
790
  Err(err) => cx.throw_error(format!("{}", err)),
@@ -854,13 +818,14 @@ fn get_time_of_day(mut cx: FunctionContext) -> JsResult<JsArray> {
854
818
  fn main(mut cx: ModuleContext) -> NeonResult<()> {
855
819
  cx.export_function("getTimeOfDay", get_time_of_day)?;
856
820
  cx.export_function("registerErrors", errors::register_errors)?;
857
- cx.export_function("newCore", core_new)?;
858
- cx.export_function("newReplayCore", replay_core_new)?;
821
+ cx.export_function("initTelemetry", init_telemetry)?;
822
+ cx.export_function("newRuntime", runtime_new)?;
823
+ cx.export_function("newClient", client_new)?;
859
824
  cx.export_function("newWorker", worker_new)?;
860
825
  cx.export_function("newReplayWorker", replay_worker_new)?;
861
826
  cx.export_function("workerShutdown", worker_shutdown)?;
862
- cx.export_function("coreShutdown", core_shutdown)?;
863
- cx.export_function("corePollLogs", core_poll_logs)?;
827
+ cx.export_function("runtimeShutdown", runtime_shutdown)?;
828
+ cx.export_function("pollLogs", poll_logs)?;
864
829
  cx.export_function(
865
830
  "workerPollWorkflowActivation",
866
831
  worker_poll_workflow_activation,