@temporalio/core-bridge 0.23.0 → 1.0.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.
- package/Cargo.lock +118 -15
- package/Cargo.toml +2 -1
- package/LICENSE.md +1 -1
- package/README.md +1 -1
- package/index.d.ts +47 -18
- package/package.json +7 -7
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.buildkite/docker/docker-compose.yaml +4 -2
- package/sdk-core/ARCHITECTURE.md +9 -7
- package/sdk-core/README.md +5 -1
- package/sdk-core/arch_docs/diagrams/workflow_internals.svg +1 -0
- package/sdk-core/bridge-ffi/src/wrappers.rs +0 -3
- package/sdk-core/client/src/lib.rs +26 -8
- package/sdk-core/client/src/raw.rs +166 -54
- package/sdk-core/client/src/retry.rs +9 -4
- package/sdk-core/client/src/workflow_handle/mod.rs +4 -2
- package/sdk-core/core/Cargo.toml +2 -0
- package/sdk-core/core/src/abstractions.rs +137 -16
- package/sdk-core/core/src/core_tests/activity_tasks.rs +258 -63
- package/sdk-core/core/src/core_tests/child_workflows.rs +1 -2
- package/sdk-core/core/src/core_tests/determinism.rs +2 -2
- package/sdk-core/core/src/core_tests/local_activities.rs +8 -7
- package/sdk-core/core/src/core_tests/queries.rs +146 -60
- package/sdk-core/core/src/core_tests/replay_flag.rs +1 -1
- package/sdk-core/core/src/core_tests/workers.rs +39 -23
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +387 -280
- package/sdk-core/core/src/lib.rs +6 -4
- package/sdk-core/core/src/pollers/poll_buffer.rs +16 -10
- package/sdk-core/core/src/protosext/mod.rs +6 -6
- package/sdk-core/core/src/retry_logic.rs +1 -1
- package/sdk-core/core/src/telemetry/metrics.rs +21 -7
- package/sdk-core/core/src/telemetry/mod.rs +18 -4
- package/sdk-core/core/src/test_help/mod.rs +341 -109
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +18 -9
- package/sdk-core/core/src/worker/activities/local_activities.rs +19 -16
- package/sdk-core/core/src/worker/activities.rs +156 -29
- package/sdk-core/core/src/worker/client.rs +1 -0
- package/sdk-core/core/src/worker/mod.rs +132 -659
- package/sdk-core/core/src/{workflow → worker/workflow}/bridge.rs +1 -1
- package/sdk-core/core/src/{workflow → worker/workflow}/driven_workflow.rs +1 -1
- package/sdk-core/core/src/{workflow → worker/workflow}/history_update.rs +16 -2
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/activity_state_machine.rs +39 -4
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/cancel_external_state_machine.rs +5 -2
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/cancel_workflow_state_machine.rs +1 -1
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/child_workflow_state_machine.rs +2 -4
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/complete_workflow_state_machine.rs +0 -0
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/continue_as_new_workflow_state_machine.rs +1 -1
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/fail_workflow_state_machine.rs +0 -0
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/local_activity_state_machine.rs +2 -5
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/mod.rs +1 -1
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/mutable_side_effect_state_machine.rs +0 -0
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/patch_state_machine.rs +1 -1
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/side_effect_state_machine.rs +0 -0
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/signal_external_state_machine.rs +4 -2
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/timer_state_machine.rs +1 -2
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/transition_coverage.rs +1 -1
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/upsert_search_attributes_state_machine.rs +5 -7
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/workflow_machines/local_acts.rs +2 -2
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/workflow_machines.rs +40 -16
- package/sdk-core/core/src/{workflow → worker/workflow}/machines/workflow_task_state_machine.rs +0 -0
- package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +198 -0
- package/sdk-core/core/src/worker/workflow/managed_run.rs +627 -0
- package/sdk-core/core/src/worker/workflow/mod.rs +1115 -0
- package/sdk-core/core/src/worker/workflow/run_cache.rs +143 -0
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +88 -0
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +936 -0
- package/sdk-core/core-api/src/errors.rs +3 -10
- package/sdk-core/core-api/src/lib.rs +2 -1
- package/sdk-core/core-api/src/worker.rs +26 -2
- package/sdk-core/etc/dynamic-config.yaml +2 -0
- package/sdk-core/integ-with-otel.sh +1 -1
- package/sdk-core/protos/api_upstream/Makefile +4 -4
- package/sdk-core/protos/api_upstream/api-linter.yaml +2 -0
- package/sdk-core/protos/api_upstream/buf.yaml +8 -9
- package/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +83 -0
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +7 -1
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/cluster.proto +40 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +3 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +3 -1
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +60 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +3 -0
- package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +32 -4
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +69 -19
- package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +13 -0
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +163 -0
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +97 -0
- package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +300 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +25 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +180 -3
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +53 -3
- package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +2 -2
- package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +6 -5
- package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -1
- package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +2 -1
- package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +0 -64
- package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +2 -1
- package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +11 -8
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +30 -25
- package/sdk-core/sdk/src/activity_context.rs +12 -5
- package/sdk-core/sdk/src/app_data.rs +37 -0
- package/sdk-core/sdk/src/lib.rs +76 -43
- package/sdk-core/sdk/src/workflow_context/options.rs +8 -6
- package/sdk-core/sdk/src/workflow_context.rs +14 -19
- package/sdk-core/sdk/src/workflow_future.rs +11 -6
- package/sdk-core/sdk-core-protos/src/history_builder.rs +19 -5
- package/sdk-core/sdk-core-protos/src/history_info.rs +11 -6
- package/sdk-core/sdk-core-protos/src/lib.rs +74 -176
- package/sdk-core/test-utils/src/lib.rs +85 -72
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +11 -9
- package/sdk-core/tests/integ_tests/polling_tests.rs +12 -0
- package/sdk-core/tests/integ_tests/queries_tests.rs +39 -22
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +49 -4
- package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +61 -0
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +74 -13
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +19 -0
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -3
- package/sdk-core/tests/integ_tests/workflow_tests.rs +10 -23
- package/sdk-core/tests/load_tests.rs +8 -3
- package/sdk-core/tests/main.rs +2 -1
- package/src/conversions.rs +47 -39
- package/src/errors.rs +10 -21
- package/src/lib.rs +342 -325
- package/sdk-core/core/src/pending_activations.rs +0 -173
- package/sdk-core/core/src/worker/wft_delivery.rs +0 -81
- package/sdk-core/core/src/workflow/mod.rs +0 -478
- package/sdk-core/core/src/workflow/workflow_tasks/cache_manager.rs +0 -194
- package/sdk-core/core/src/workflow/workflow_tasks/concurrency_manager.rs +0 -418
- package/sdk-core/core/src/workflow/workflow_tasks/mod.rs +0 -989
package/src/lib.rs
CHANGED
|
@@ -3,12 +3,14 @@ mod errors;
|
|
|
3
3
|
|
|
4
4
|
use crate::conversions::{get_optional, ObjectHandleConversionsExt};
|
|
5
5
|
use errors::*;
|
|
6
|
+
use futures::stream::StreamExt;
|
|
6
7
|
use neon::prelude::*;
|
|
7
|
-
use
|
|
8
|
+
use neon::types::buffer::TypedArray;
|
|
8
9
|
use opentelemetry::trace::{FutureExt, SpanContext, TraceContextExt};
|
|
9
10
|
use parking_lot::RwLock;
|
|
10
11
|
use prost::Message;
|
|
11
12
|
use std::collections::HashMap;
|
|
13
|
+
use std::ops::Deref;
|
|
12
14
|
use std::{
|
|
13
15
|
cell::RefCell,
|
|
14
16
|
fmt::Display,
|
|
@@ -22,7 +24,7 @@ use temporal_client::{
|
|
|
22
24
|
use temporal_sdk_core::{
|
|
23
25
|
api::{
|
|
24
26
|
errors::{CompleteActivityError, CompleteWfError, PollActivityError, PollWfError},
|
|
25
|
-
Worker as
|
|
27
|
+
Worker as CoreWorkerTrait,
|
|
26
28
|
},
|
|
27
29
|
fetch_global_buffered_logs, init_replay_worker, init_worker,
|
|
28
30
|
protos::{
|
|
@@ -32,17 +34,18 @@ use temporal_sdk_core::{
|
|
|
32
34
|
},
|
|
33
35
|
temporal::api::history::v1::History,
|
|
34
36
|
},
|
|
35
|
-
telemetry_init, ClientOptions, RetryClient, WorkerConfig,
|
|
37
|
+
telemetry_init, ClientOptions, RetryClient, Worker as CoreWorker, WorkerConfig,
|
|
36
38
|
};
|
|
37
39
|
use tokio::{
|
|
38
40
|
runtime::Runtime,
|
|
39
41
|
sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
|
40
42
|
};
|
|
43
|
+
use tokio_stream::wrappers::UnboundedReceiverStream;
|
|
41
44
|
|
|
42
45
|
type RawClient = RetryClient<ConfiguredClient<WorkflowServiceClientWithMetrics>>;
|
|
43
46
|
|
|
44
47
|
/// A request from JS to bridge to core
|
|
45
|
-
enum
|
|
48
|
+
enum RuntimeRequest {
|
|
46
49
|
/// A request to shutdown the runtime, breaks from the thread loop.
|
|
47
50
|
Shutdown {
|
|
48
51
|
/// Used to send the result back into JS
|
|
@@ -63,16 +66,8 @@ enum Request {
|
|
|
63
66
|
/// Used to send the result back into JS
|
|
64
67
|
callback: Root<JsFunction>,
|
|
65
68
|
},
|
|
66
|
-
/// A request to shutdown a worker, the worker instance will remain active to
|
|
67
|
-
/// allow draining of pending tasks
|
|
68
|
-
ShutdownWorker {
|
|
69
|
-
worker: Arc<dyn CoreWorker>,
|
|
70
|
-
/// Used to send the result back into JS
|
|
71
|
-
callback: Root<JsFunction>,
|
|
72
|
-
},
|
|
73
69
|
/// A request to create a new Worker using a connected client
|
|
74
70
|
InitWorker {
|
|
75
|
-
runtime: Arc<RuntimeHandle>,
|
|
76
71
|
/// Worker configuration e.g. limits and task queue
|
|
77
72
|
config: WorkerConfig,
|
|
78
73
|
/// A client created with a [CreateClient] request
|
|
@@ -82,7 +77,6 @@ enum Request {
|
|
|
82
77
|
},
|
|
83
78
|
/// A request to register a replay worker
|
|
84
79
|
InitReplayWorker {
|
|
85
|
-
runtime: Arc<RuntimeHandle>,
|
|
86
80
|
/// Worker configuration. Must have unique task queue name.
|
|
87
81
|
config: WorkerConfig,
|
|
88
82
|
/// The history this worker should replay
|
|
@@ -90,16 +84,29 @@ enum Request {
|
|
|
90
84
|
/// Used to send the result back into JS
|
|
91
85
|
callback: Root<JsFunction>,
|
|
92
86
|
},
|
|
87
|
+
/// A request to drain logs from core so they can be emitted in node
|
|
88
|
+
PollLogs {
|
|
89
|
+
/// Logs are sent to this function
|
|
90
|
+
callback: Root<JsFunction>,
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#[derive(Debug)]
|
|
95
|
+
enum WorkerRequest {
|
|
96
|
+
/// A request to shutdown a worker, the worker instance will remain active to
|
|
97
|
+
/// allow draining of pending tasks
|
|
98
|
+
InitiateShutdown {
|
|
99
|
+
/// Used to send the result back into JS
|
|
100
|
+
callback: Root<JsFunction>,
|
|
101
|
+
},
|
|
93
102
|
/// A request to poll for workflow activations
|
|
94
103
|
PollWorkflowActivation {
|
|
95
|
-
worker: Arc<dyn CoreWorker>,
|
|
96
104
|
otel_span: SpanContext,
|
|
97
105
|
/// Used to send the result back into JS
|
|
98
106
|
callback: Root<JsFunction>,
|
|
99
107
|
},
|
|
100
108
|
/// A request to complete a single workflow activation
|
|
101
109
|
CompleteWorkflowActivation {
|
|
102
|
-
worker: Arc<dyn CoreWorker>,
|
|
103
110
|
completion: WorkflowActivationCompletion,
|
|
104
111
|
otel_span: SpanContext,
|
|
105
112
|
/// Used to send the result back into JS
|
|
@@ -107,33 +114,23 @@ enum Request {
|
|
|
107
114
|
},
|
|
108
115
|
/// A request to poll for activity tasks
|
|
109
116
|
PollActivityTask {
|
|
110
|
-
worker: Arc<dyn CoreWorker>,
|
|
111
117
|
otel_span: SpanContext,
|
|
112
118
|
/// Used to report completion or error back into JS
|
|
113
119
|
callback: Root<JsFunction>,
|
|
114
120
|
},
|
|
115
121
|
/// A request to complete a single activity task
|
|
116
122
|
CompleteActivityTask {
|
|
117
|
-
worker: Arc<dyn CoreWorker>,
|
|
118
123
|
completion: ActivityTaskCompletion,
|
|
119
124
|
otel_span: SpanContext,
|
|
120
125
|
/// Used to send the result back into JS
|
|
121
126
|
callback: Root<JsFunction>,
|
|
122
127
|
},
|
|
123
128
|
/// A request to send a heartbeat from a running activity
|
|
124
|
-
RecordActivityHeartbeat {
|
|
125
|
-
worker: Arc<dyn CoreWorker>,
|
|
126
|
-
heartbeat: ActivityHeartbeat,
|
|
127
|
-
},
|
|
128
|
-
/// A request to drain logs from core so they can be emitted in node
|
|
129
|
-
PollLogs {
|
|
130
|
-
/// Logs are sent to this function
|
|
131
|
-
callback: Root<JsFunction>,
|
|
132
|
-
},
|
|
129
|
+
RecordActivityHeartbeat { heartbeat: ActivityHeartbeat },
|
|
133
130
|
}
|
|
134
131
|
|
|
135
132
|
struct RuntimeHandle {
|
|
136
|
-
sender: UnboundedSender<
|
|
133
|
+
sender: UnboundedSender<RuntimeRequest>,
|
|
137
134
|
}
|
|
138
135
|
|
|
139
136
|
/// Box it so we can use the runtime from JS
|
|
@@ -151,34 +148,30 @@ impl Finalize for Client {}
|
|
|
151
148
|
|
|
152
149
|
/// Worker struct, hold a reference for the channel sender responsible for sending requests from
|
|
153
150
|
/// JS to a bridge thread which forwards them to core
|
|
154
|
-
struct
|
|
155
|
-
|
|
156
|
-
core_worker: Arc<dyn CoreWorker>,
|
|
151
|
+
struct WorkerHandle {
|
|
152
|
+
sender: UnboundedSender<WorkerRequest>,
|
|
157
153
|
}
|
|
158
154
|
|
|
159
155
|
/// Box it so we can use Worker from JS
|
|
160
|
-
type BoxedWorker = JsBox<
|
|
161
|
-
impl Finalize for
|
|
162
|
-
|
|
163
|
-
///
|
|
164
|
-
fn tokio_runtime() ->
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
.build()
|
|
171
|
-
.expect("Tokio runtime must construct properly")
|
|
172
|
-
})
|
|
156
|
+
type BoxedWorker = JsBox<RefCell<Option<WorkerHandle>>>;
|
|
157
|
+
impl Finalize for WorkerHandle {}
|
|
158
|
+
|
|
159
|
+
/// Inits a multi-threaded tokio runtime used to interact with sdk-core APIs
|
|
160
|
+
fn tokio_runtime() -> Runtime {
|
|
161
|
+
tokio::runtime::Builder::new_multi_thread()
|
|
162
|
+
.enable_all()
|
|
163
|
+
.thread_name("core")
|
|
164
|
+
.build()
|
|
165
|
+
.expect("Tokio runtime must construct properly")
|
|
173
166
|
}
|
|
174
167
|
|
|
175
|
-
/// Send a result to JS via callback using
|
|
176
|
-
fn send_result<F, T>(
|
|
168
|
+
/// Send a result to JS via callback using a [Channel]
|
|
169
|
+
fn send_result<F, T>(channel: Arc<Channel>, callback: Root<JsFunction>, res_fn: F)
|
|
177
170
|
where
|
|
178
171
|
F: for<'a> FnOnce(&mut TaskContext<'a>) -> NeonResult<Handle<'a, T>> + Send + 'static,
|
|
179
172
|
T: Value,
|
|
180
173
|
{
|
|
181
|
-
|
|
174
|
+
channel.send(move |mut cx| {
|
|
182
175
|
let callback = callback.into_inner(&mut cx);
|
|
183
176
|
let this = cx.undefined();
|
|
184
177
|
let error = cx.undefined();
|
|
@@ -189,13 +182,13 @@ where
|
|
|
189
182
|
});
|
|
190
183
|
}
|
|
191
184
|
|
|
192
|
-
/// Send an error to JS via callback using
|
|
193
|
-
fn send_error<E, F>(
|
|
185
|
+
/// Send an error to JS via callback using a [Channel]
|
|
186
|
+
fn send_error<E, F>(channel: Arc<Channel>, callback: Root<JsFunction>, error_ctor: F)
|
|
194
187
|
where
|
|
195
188
|
E: Object,
|
|
196
189
|
F: for<'a> FnOnce(&mut TaskContext<'a>) -> JsResult<'a, E> + Send + 'static,
|
|
197
190
|
{
|
|
198
|
-
|
|
191
|
+
channel.send(move |mut cx| {
|
|
199
192
|
let callback = callback.into_inner(&mut cx);
|
|
200
193
|
callback_with_error(&mut cx, callback, error_ctor)
|
|
201
194
|
});
|
|
@@ -236,33 +229,33 @@ where
|
|
|
236
229
|
})
|
|
237
230
|
}
|
|
238
231
|
|
|
239
|
-
/// When Future completes, call given JS callback using a neon::
|
|
232
|
+
/// When Future completes, call given JS callback using a neon::Channel with either error or
|
|
240
233
|
/// undefined
|
|
241
234
|
async fn void_future_to_js<E, F, ER, EF>(
|
|
242
|
-
|
|
235
|
+
channel: Arc<Channel>,
|
|
243
236
|
callback: Root<JsFunction>,
|
|
244
237
|
f: F,
|
|
245
238
|
error_function: EF,
|
|
246
239
|
) where
|
|
247
240
|
E: Display + Send + 'static,
|
|
248
|
-
F: Future<Output = Result<(), E>> + Send
|
|
241
|
+
F: Future<Output = Result<(), E>> + Send,
|
|
249
242
|
ER: Object,
|
|
250
243
|
EF: for<'a> FnOnce(&mut TaskContext<'a>, E) -> JsResult<'a, ER> + Send + 'static,
|
|
251
244
|
{
|
|
252
245
|
match f.await {
|
|
253
246
|
Ok(()) => {
|
|
254
|
-
send_result(
|
|
247
|
+
send_result(channel, callback, |cx| Ok(cx.undefined()));
|
|
255
248
|
}
|
|
256
249
|
Err(err) => {
|
|
257
|
-
send_error(
|
|
250
|
+
send_error(channel, callback, |cx| error_function(cx, err));
|
|
258
251
|
}
|
|
259
252
|
}
|
|
260
253
|
}
|
|
261
254
|
|
|
262
|
-
/// Builds a tokio runtime and starts polling on [
|
|
263
|
-
/// Bridges requests from JS to core and sends responses back to JS using a neon::
|
|
255
|
+
/// Builds a tokio runtime and starts polling on [RuntimeRequest]s via an internal channel.
|
|
256
|
+
/// Bridges requests from JS to core and sends responses back to JS using a neon::Channel.
|
|
264
257
|
/// Blocks current thread until a [Shutdown] request is received in channel.
|
|
265
|
-
fn start_bridge_loop(
|
|
258
|
+
fn start_bridge_loop(channel: Arc<Channel>, receiver: &mut UnboundedReceiver<RuntimeRequest>) {
|
|
266
259
|
tokio_runtime().block_on(async {
|
|
267
260
|
loop {
|
|
268
261
|
let request_option = receiver.recv().await;
|
|
@@ -271,14 +264,14 @@ fn start_bridge_loop(event_queue: Arc<EventQueue>, receiver: &mut UnboundedRecei
|
|
|
271
264
|
Some(request) => request,
|
|
272
265
|
};
|
|
273
266
|
|
|
274
|
-
let
|
|
267
|
+
let channel = channel.clone();
|
|
275
268
|
|
|
276
269
|
match request {
|
|
277
|
-
|
|
278
|
-
send_result(
|
|
270
|
+
RuntimeRequest::Shutdown { callback } => {
|
|
271
|
+
send_result(channel, callback, |cx| Ok(cx.undefined()));
|
|
279
272
|
break;
|
|
280
273
|
}
|
|
281
|
-
|
|
274
|
+
RuntimeRequest::CreateClient {
|
|
282
275
|
runtime,
|
|
283
276
|
options,
|
|
284
277
|
headers,
|
|
@@ -288,43 +281,48 @@ fn start_bridge_loop(event_queue: Arc<EventQueue>, receiver: &mut UnboundedRecei
|
|
|
288
281
|
// returned client directly at the moment, when we repurpose the client to be
|
|
289
282
|
// used by a Worker, `init_worker` will attach the correct metrics meter for
|
|
290
283
|
// us.
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
284
|
+
tokio::spawn(async move {
|
|
285
|
+
match options
|
|
286
|
+
.connect_no_namespace(None, headers.map(|h| Arc::new(RwLock::new(h))))
|
|
287
|
+
.await
|
|
288
|
+
{
|
|
289
|
+
Err(err) => {
|
|
290
|
+
send_error(channel.clone(), callback, |cx| match err {
|
|
291
|
+
ClientInitError::SystemInfoCallError(e) => TRANSPORT_ERROR
|
|
292
|
+
.from_string(
|
|
293
|
+
cx,
|
|
294
|
+
format!("Failed to call GetSystemInfo: {}", e),
|
|
295
|
+
),
|
|
296
|
+
ClientInitError::TonicTransportError(e) => {
|
|
297
|
+
TRANSPORT_ERROR.from_error(cx, e)
|
|
298
|
+
}
|
|
299
|
+
ClientInitError::InvalidUri(e) => {
|
|
300
|
+
Ok(JsError::type_error(cx, format!("{}", e))?.upcast())
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
Ok(client) => {
|
|
305
|
+
send_result(channel.clone(), callback, |cx| {
|
|
306
|
+
Ok(cx.boxed(RefCell::new(Some(Client {
|
|
307
|
+
runtime,
|
|
308
|
+
core_client: Arc::new(client),
|
|
309
|
+
}))))
|
|
310
|
+
});
|
|
311
|
+
}
|
|
314
312
|
}
|
|
315
|
-
}
|
|
313
|
+
});
|
|
316
314
|
}
|
|
317
|
-
|
|
315
|
+
RuntimeRequest::UpdateClientHeaders {
|
|
318
316
|
client,
|
|
319
317
|
headers,
|
|
320
318
|
callback,
|
|
321
319
|
} => {
|
|
322
320
|
client.get_client().set_headers(headers);
|
|
323
|
-
send_result(
|
|
321
|
+
send_result(channel.clone(), callback, |cx| Ok(cx.undefined()));
|
|
324
322
|
}
|
|
325
|
-
|
|
323
|
+
RuntimeRequest::PollLogs { callback } => {
|
|
326
324
|
let logs = fetch_global_buffered_logs();
|
|
327
|
-
send_result(
|
|
325
|
+
send_result(channel.clone(), callback, |cx| {
|
|
328
326
|
let logarr = cx.empty_array();
|
|
329
327
|
for (i, cl) in logs.into_iter().enumerate() {
|
|
330
328
|
// Not much to do here except for panic when there's an
|
|
@@ -341,21 +339,7 @@ fn start_bridge_loop(event_queue: Arc<EventQueue>, receiver: &mut UnboundedRecei
|
|
|
341
339
|
Ok(logarr)
|
|
342
340
|
});
|
|
343
341
|
}
|
|
344
|
-
|
|
345
|
-
tokio::spawn(void_future_to_js(
|
|
346
|
-
event_queue,
|
|
347
|
-
callback,
|
|
348
|
-
async move {
|
|
349
|
-
worker.shutdown().await;
|
|
350
|
-
// Wrap the empty result in a valid Result object
|
|
351
|
-
let result: Result<(), String> = Ok(());
|
|
352
|
-
result
|
|
353
|
-
},
|
|
354
|
-
|cx, err| UNEXPECTED_ERROR.from_error(cx, err),
|
|
355
|
-
));
|
|
356
|
-
}
|
|
357
|
-
Request::InitWorker {
|
|
358
|
-
runtime,
|
|
342
|
+
RuntimeRequest::InitWorker {
|
|
359
343
|
config,
|
|
360
344
|
client,
|
|
361
345
|
callback,
|
|
@@ -363,134 +347,139 @@ fn start_bridge_loop(event_queue: Arc<EventQueue>, receiver: &mut UnboundedRecei
|
|
|
363
347
|
let client = (*client).clone();
|
|
364
348
|
let worker =
|
|
365
349
|
init_worker(config, AnyClient::LowLevel(Box::new(client.into_inner())));
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}))
|
|
350
|
+
let (tx, rx) = unbounded_channel();
|
|
351
|
+
tokio::spawn(start_worker_loop(worker, rx, channel.clone()));
|
|
352
|
+
send_result(channel.clone(), callback, |cx| {
|
|
353
|
+
Ok(cx.boxed(RefCell::new(Some(WorkerHandle { sender: tx }))))
|
|
371
354
|
});
|
|
372
355
|
}
|
|
373
|
-
|
|
374
|
-
runtime,
|
|
356
|
+
RuntimeRequest::InitReplayWorker {
|
|
375
357
|
config,
|
|
376
358
|
history,
|
|
377
359
|
callback,
|
|
378
360
|
} => {
|
|
379
361
|
match init_replay_worker(config, &history) {
|
|
380
|
-
Ok(worker) =>
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
362
|
+
Ok(worker) => {
|
|
363
|
+
let (tx, rx) = unbounded_channel();
|
|
364
|
+
tokio::spawn(start_worker_loop(worker, rx, channel.clone()));
|
|
365
|
+
send_result(channel.clone(), callback, |cx| {
|
|
366
|
+
Ok(cx.boxed(RefCell::new(Some(WorkerHandle { sender: tx }))))
|
|
367
|
+
})
|
|
368
|
+
}
|
|
369
|
+
Err(err) => send_error(channel.clone(), callback, move |cx| {
|
|
370
|
+
UNEXPECTED_ERROR.from_error(cx, err.deref())
|
|
388
371
|
}),
|
|
389
372
|
};
|
|
390
373
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
})
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/// Polls on [WorkerRequest]s via given channel.
|
|
380
|
+
/// Bridges requests from JS to core and sends responses back to JS using a neon::Channel.
|
|
381
|
+
/// Returns when the given channel is dropped.
|
|
382
|
+
async fn start_worker_loop(
|
|
383
|
+
worker: CoreWorker,
|
|
384
|
+
rx: UnboundedReceiver<WorkerRequest>,
|
|
385
|
+
channel: Arc<Channel>,
|
|
386
|
+
) {
|
|
387
|
+
UnboundedReceiverStream::new(rx)
|
|
388
|
+
.for_each_concurrent(None, |request| {
|
|
389
|
+
let worker = &worker;
|
|
390
|
+
let channel = channel.clone();
|
|
391
|
+
async move {
|
|
392
|
+
match request {
|
|
393
|
+
WorkerRequest::InitiateShutdown { callback } => {
|
|
394
|
+
worker.initiate_shutdown();
|
|
395
|
+
send_result(channel, callback, |cx| Ok(cx.undefined()));
|
|
396
|
+
}
|
|
397
|
+
WorkerRequest::PollWorkflowActivation {
|
|
398
|
+
otel_span,
|
|
399
|
+
callback,
|
|
400
|
+
} => {
|
|
397
401
|
handle_poll_workflow_activation_request(
|
|
398
|
-
|
|
399
|
-
otel_span,
|
|
400
|
-
event_queue,
|
|
401
|
-
callback,
|
|
402
|
+
&worker, otel_span, channel, callback,
|
|
402
403
|
)
|
|
403
404
|
.await
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
405
|
+
}
|
|
406
|
+
WorkerRequest::PollActivityTask {
|
|
407
|
+
otel_span,
|
|
408
|
+
callback,
|
|
409
|
+
} => {
|
|
410
|
+
handle_poll_activity_task_request(&worker, otel_span, channel, callback)
|
|
411
|
+
.await
|
|
412
|
+
}
|
|
413
|
+
WorkerRequest::CompleteWorkflowActivation {
|
|
414
|
+
completion,
|
|
415
|
+
otel_span,
|
|
416
|
+
callback,
|
|
417
|
+
} => {
|
|
418
|
+
let otel_ctx =
|
|
419
|
+
opentelemetry::Context::new().with_remote_span_context(otel_span);
|
|
420
|
+
void_future_to_js(
|
|
421
|
+
channel,
|
|
416
422
|
callback,
|
|
423
|
+
async move {
|
|
424
|
+
worker
|
|
425
|
+
.complete_workflow_activation(completion)
|
|
426
|
+
.with_context(otel_ctx)
|
|
427
|
+
.await
|
|
428
|
+
},
|
|
429
|
+
|cx, err| match err {
|
|
430
|
+
CompleteWfError::TonicError(_) => {
|
|
431
|
+
TRANSPORT_ERROR.from_error(cx, err)
|
|
432
|
+
}
|
|
433
|
+
CompleteWfError::MalformedWorkflowCompletion { reason, .. } => {
|
|
434
|
+
Ok(JsError::type_error(cx, reason)?.upcast())
|
|
435
|
+
}
|
|
436
|
+
},
|
|
417
437
|
)
|
|
418
|
-
.await
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
completion,
|
|
424
|
-
otel_span,
|
|
425
|
-
callback,
|
|
426
|
-
} => {
|
|
427
|
-
let otel_ctx =
|
|
428
|
-
opentelemetry::Context::new().with_remote_span_context(otel_span);
|
|
429
|
-
tokio::spawn(void_future_to_js(
|
|
430
|
-
event_queue,
|
|
431
|
-
callback,
|
|
432
|
-
async move {
|
|
433
|
-
worker
|
|
434
|
-
.complete_workflow_activation(completion)
|
|
435
|
-
.with_context(otel_ctx)
|
|
436
|
-
.await
|
|
437
|
-
},
|
|
438
|
-
|cx, err| match err {
|
|
439
|
-
CompleteWfError::NoWorkerForQueue(queue_name) => {
|
|
440
|
-
let args = vec![cx.string(queue_name).upcast()];
|
|
441
|
-
NO_WORKER_ERROR.construct(cx, args)
|
|
442
|
-
}
|
|
443
|
-
CompleteWfError::TonicError(_) => TRANSPORT_ERROR.from_error(cx, err),
|
|
444
|
-
CompleteWfError::MalformedWorkflowCompletion { reason, .. } => {
|
|
445
|
-
Ok(JsError::type_error(cx, reason)?.upcast())
|
|
446
|
-
}
|
|
447
|
-
},
|
|
448
|
-
));
|
|
449
|
-
}
|
|
450
|
-
Request::CompleteActivityTask {
|
|
451
|
-
worker,
|
|
452
|
-
completion,
|
|
453
|
-
otel_span,
|
|
454
|
-
callback,
|
|
455
|
-
} => {
|
|
456
|
-
let otel_ctx =
|
|
457
|
-
opentelemetry::Context::new().with_remote_span_context(otel_span);
|
|
458
|
-
tokio::spawn(void_future_to_js(
|
|
459
|
-
event_queue,
|
|
438
|
+
.await;
|
|
439
|
+
}
|
|
440
|
+
WorkerRequest::CompleteActivityTask {
|
|
441
|
+
completion,
|
|
442
|
+
otel_span,
|
|
460
443
|
callback,
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
444
|
+
} => {
|
|
445
|
+
let otel_ctx =
|
|
446
|
+
opentelemetry::Context::new().with_remote_span_context(otel_span);
|
|
447
|
+
void_future_to_js(
|
|
448
|
+
channel,
|
|
449
|
+
callback,
|
|
450
|
+
async move {
|
|
451
|
+
worker
|
|
452
|
+
.complete_activity_task(completion)
|
|
453
|
+
.with_context(otel_ctx)
|
|
454
|
+
.await
|
|
455
|
+
},
|
|
456
|
+
|cx, err| match err {
|
|
457
|
+
CompleteActivityError::MalformedActivityCompletion {
|
|
458
|
+
reason,
|
|
459
|
+
..
|
|
460
|
+
} => Ok(JsError::type_error(cx, reason)?.upcast()),
|
|
461
|
+
CompleteActivityError::TonicError(_) => {
|
|
462
|
+
TRANSPORT_ERROR.from_error(cx, err)
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
)
|
|
466
|
+
.await;
|
|
467
|
+
}
|
|
468
|
+
WorkerRequest::RecordActivityHeartbeat { heartbeat } => {
|
|
469
|
+
worker.record_activity_heartbeat(heartbeat)
|
|
470
|
+
}
|
|
483
471
|
}
|
|
484
472
|
}
|
|
485
|
-
}
|
|
486
|
-
|
|
473
|
+
})
|
|
474
|
+
.await;
|
|
475
|
+
worker.finalize_shutdown().await;
|
|
487
476
|
}
|
|
488
477
|
|
|
489
478
|
/// Called within the poll loop thread, calls core and triggers JS callback with result
|
|
490
479
|
async fn handle_poll_workflow_activation_request(
|
|
491
|
-
worker: &
|
|
480
|
+
worker: &CoreWorker,
|
|
492
481
|
span_context: SpanContext,
|
|
493
|
-
|
|
482
|
+
channel: Arc<Channel>,
|
|
494
483
|
callback: Root<JsFunction>,
|
|
495
484
|
) {
|
|
496
485
|
let otel_ctx = opentelemetry::Context::new().with_remote_span_context(span_context);
|
|
@@ -500,24 +489,19 @@ async fn handle_poll_workflow_activation_request(
|
|
|
500
489
|
.await
|
|
501
490
|
{
|
|
502
491
|
Ok(task) => {
|
|
503
|
-
send_result(
|
|
492
|
+
send_result(channel, callback, move |cx| {
|
|
504
493
|
let len = task.encoded_len();
|
|
505
|
-
let mut result = JsArrayBuffer::new(cx, len
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
};
|
|
511
|
-
});
|
|
494
|
+
let mut result = JsArrayBuffer::new(cx, len)?;
|
|
495
|
+
let mut slice = result.as_mut_slice(cx);
|
|
496
|
+
if task.encode(&mut slice).is_err() {
|
|
497
|
+
panic!("Failed to encode task")
|
|
498
|
+
};
|
|
512
499
|
Ok(result)
|
|
513
500
|
});
|
|
514
501
|
}
|
|
515
502
|
Err(err) => {
|
|
516
|
-
send_error(
|
|
503
|
+
send_error(channel, callback, move |cx| match err {
|
|
517
504
|
PollWfError::ShutDown => SHUTDOWN_ERROR.from_error(cx, err),
|
|
518
|
-
PollWfError::AutocompleteError(CompleteWfError::NoWorkerForQueue(_)) => {
|
|
519
|
-
UNEXPECTED_ERROR.from_error(cx, "TODO this error shouldn't exist")
|
|
520
|
-
}
|
|
521
505
|
PollWfError::TonicError(_)
|
|
522
506
|
| PollWfError::AutocompleteError(CompleteWfError::TonicError(_)) => {
|
|
523
507
|
TRANSPORT_ERROR.from_error(cx, err)
|
|
@@ -533,28 +517,26 @@ async fn handle_poll_workflow_activation_request(
|
|
|
533
517
|
|
|
534
518
|
/// Called within the poll loop thread, calls core and triggers JS callback with result
|
|
535
519
|
async fn handle_poll_activity_task_request(
|
|
536
|
-
worker: &
|
|
520
|
+
worker: &CoreWorker,
|
|
537
521
|
span_context: SpanContext,
|
|
538
|
-
|
|
522
|
+
channel: Arc<Channel>,
|
|
539
523
|
callback: Root<JsFunction>,
|
|
540
524
|
) {
|
|
541
525
|
let otel_ctx = opentelemetry::Context::new().with_remote_span_context(span_context);
|
|
542
526
|
match worker.poll_activity_task().with_context(otel_ctx).await {
|
|
543
527
|
Ok(task) => {
|
|
544
|
-
send_result(
|
|
528
|
+
send_result(channel, callback, move |cx| {
|
|
545
529
|
let len = task.encoded_len();
|
|
546
|
-
let mut result = JsArrayBuffer::new(cx, len
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
};
|
|
552
|
-
});
|
|
530
|
+
let mut result = JsArrayBuffer::new(cx, len)?;
|
|
531
|
+
let mut slice = result.as_mut_slice(cx);
|
|
532
|
+
if task.encode(&mut slice).is_err() {
|
|
533
|
+
panic!("Failed to encode task")
|
|
534
|
+
};
|
|
553
535
|
Ok(result)
|
|
554
536
|
});
|
|
555
537
|
}
|
|
556
538
|
Err(err) => {
|
|
557
|
-
send_error(
|
|
539
|
+
send_error(channel, callback, move |cx| match err {
|
|
558
540
|
PollActivityError::ShutDown => SHUTDOWN_ERROR.from_error(cx, err),
|
|
559
541
|
PollActivityError::TonicError(_) => TRANSPORT_ERROR.from_error(cx, err),
|
|
560
542
|
});
|
|
@@ -576,12 +558,12 @@ fn init_telemetry(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
576
558
|
}
|
|
577
559
|
|
|
578
560
|
/// Create the tokio runtime required to run Core.
|
|
579
|
-
/// Immediately spawns a poller thread that will block on [
|
|
561
|
+
/// Immediately spawns a poller thread that will block on [RuntimeRequest]s
|
|
580
562
|
fn runtime_new(mut cx: FunctionContext) -> JsResult<BoxedRuntime> {
|
|
581
|
-
let
|
|
582
|
-
let (sender, mut receiver) = unbounded_channel::<
|
|
563
|
+
let channel = Arc::new(cx.channel());
|
|
564
|
+
let (sender, mut receiver) = unbounded_channel::<RuntimeRequest>();
|
|
583
565
|
|
|
584
|
-
std::thread::spawn(move || start_bridge_loop(
|
|
566
|
+
std::thread::spawn(move || start_bridge_loop(channel, &mut receiver));
|
|
585
567
|
|
|
586
568
|
Ok(cx.boxed(Arc::new(RuntimeHandle { sender })))
|
|
587
569
|
}
|
|
@@ -594,13 +576,13 @@ fn client_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
594
576
|
let callback = cx.argument::<JsFunction>(2)?;
|
|
595
577
|
|
|
596
578
|
let client_options = opts.as_client_options(&mut cx)?;
|
|
597
|
-
let headers = match js_optional_getter!(&mut cx, &opts, "
|
|
579
|
+
let headers = match js_optional_getter!(&mut cx, &opts, "metadata", JsObject) {
|
|
598
580
|
None => None,
|
|
599
581
|
Some(h) => Some(
|
|
600
582
|
h.as_hash_map_of_string_to_string(&mut cx)
|
|
601
583
|
.map_err(|reason| {
|
|
602
584
|
cx.throw_type_error::<_, HashMap<String, String>>(format!(
|
|
603
|
-
"Invalid
|
|
585
|
+
"Invalid metadata: {}",
|
|
604
586
|
reason
|
|
605
587
|
))
|
|
606
588
|
.unwrap_err()
|
|
@@ -608,7 +590,7 @@ fn client_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
608
590
|
),
|
|
609
591
|
};
|
|
610
592
|
|
|
611
|
-
let request =
|
|
593
|
+
let request = RuntimeRequest::CreateClient {
|
|
612
594
|
runtime: (**runtime).clone(),
|
|
613
595
|
options: client_options,
|
|
614
596
|
headers,
|
|
@@ -634,7 +616,7 @@ fn client_update_headers(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
634
616
|
callback_with_unexpected_error(&mut cx, callback, "Tried to use closed Client")?;
|
|
635
617
|
}
|
|
636
618
|
Some(client) => {
|
|
637
|
-
let request =
|
|
619
|
+
let request = RuntimeRequest::UpdateClientHeaders {
|
|
638
620
|
client: client.core_client.clone(),
|
|
639
621
|
headers,
|
|
640
622
|
callback: callback.root(&mut cx),
|
|
@@ -661,9 +643,8 @@ fn worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
661
643
|
callback_with_unexpected_error(&mut cx, callback, "Tried to use closed Client")?;
|
|
662
644
|
}
|
|
663
645
|
Some(client) => {
|
|
664
|
-
let request =
|
|
646
|
+
let request = RuntimeRequest::InitWorker {
|
|
665
647
|
client: client.core_client.clone(),
|
|
666
|
-
runtime: client.runtime.clone(),
|
|
667
648
|
config,
|
|
668
649
|
callback: callback.root(&mut cx),
|
|
669
650
|
};
|
|
@@ -685,13 +666,10 @@ fn replay_worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
685
666
|
let callback = cx.argument::<JsFunction>(3)?;
|
|
686
667
|
|
|
687
668
|
let config = worker_options.as_worker_config(&mut cx)?;
|
|
688
|
-
|
|
689
|
-
match
|
|
690
|
-
History::decode_length_delimited(data.as_slice::<u8>())
|
|
691
|
-
}) {
|
|
669
|
+
let data = history_binary.as_slice(&mut cx);
|
|
670
|
+
match History::decode_length_delimited(data) {
|
|
692
671
|
Ok(history) => {
|
|
693
|
-
let request =
|
|
694
|
-
runtime: (**runtime).clone(),
|
|
672
|
+
let request = RuntimeRequest::InitReplayWorker {
|
|
695
673
|
config,
|
|
696
674
|
history,
|
|
697
675
|
callback: callback.root(&mut cx),
|
|
@@ -712,7 +690,7 @@ fn replay_worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
712
690
|
fn runtime_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
713
691
|
let runtime = cx.argument::<BoxedRuntime>(0)?;
|
|
714
692
|
let callback = cx.argument::<JsFunction>(1)?;
|
|
715
|
-
let request =
|
|
693
|
+
let request = RuntimeRequest::Shutdown {
|
|
716
694
|
callback: callback.root(&mut cx),
|
|
717
695
|
};
|
|
718
696
|
if let Err(err) = runtime.sender.send(request) {
|
|
@@ -725,7 +703,7 @@ fn runtime_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
725
703
|
fn poll_logs(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
726
704
|
let runtime = cx.argument::<BoxedRuntime>(0)?;
|
|
727
705
|
let callback = cx.argument::<JsFunction>(1)?;
|
|
728
|
-
let request =
|
|
706
|
+
let request = RuntimeRequest::PollLogs {
|
|
729
707
|
callback: callback.root(&mut cx),
|
|
730
708
|
};
|
|
731
709
|
if let Err(err) = runtime.sender.send(request) {
|
|
@@ -740,13 +718,19 @@ fn worker_poll_workflow_activation(mut cx: FunctionContext) -> JsResult<JsUndefi
|
|
|
740
718
|
let worker = cx.argument::<BoxedWorker>(0)?;
|
|
741
719
|
let otel_span = cx.argument::<JsObject>(1)?;
|
|
742
720
|
let callback = cx.argument::<JsFunction>(2)?;
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
721
|
+
match &*worker.borrow() {
|
|
722
|
+
None => {
|
|
723
|
+
callback_with_unexpected_error(&mut cx, callback, "Tried to use closed Worker")?;
|
|
724
|
+
}
|
|
725
|
+
Some(worker) => {
|
|
726
|
+
let request = WorkerRequest::PollWorkflowActivation {
|
|
727
|
+
otel_span: otel_span.as_otel_span_context(&mut cx)?,
|
|
728
|
+
callback: callback.root(&mut cx),
|
|
729
|
+
};
|
|
730
|
+
if let Err(err) = worker.sender.send(request) {
|
|
731
|
+
callback_with_unexpected_error(&mut cx, callback, err)?;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
750
734
|
}
|
|
751
735
|
Ok(cx.undefined())
|
|
752
736
|
}
|
|
@@ -757,13 +741,19 @@ fn worker_poll_activity_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
757
741
|
let worker = cx.argument::<BoxedWorker>(0)?;
|
|
758
742
|
let otel_span = cx.argument::<JsObject>(1)?;
|
|
759
743
|
let callback = cx.argument::<JsFunction>(2)?;
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
744
|
+
match &*worker.borrow() {
|
|
745
|
+
None => {
|
|
746
|
+
callback_with_unexpected_error(&mut cx, callback, "Tried to use closed Worker")?;
|
|
747
|
+
}
|
|
748
|
+
Some(worker) => {
|
|
749
|
+
let request = WorkerRequest::PollActivityTask {
|
|
750
|
+
otel_span: otel_span.as_otel_span_context(&mut cx)?,
|
|
751
|
+
callback: callback.root(&mut cx),
|
|
752
|
+
};
|
|
753
|
+
if let Err(err) = worker.sender.send(request) {
|
|
754
|
+
callback_with_unexpected_error(&mut cx, callback, err)?;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
767
757
|
}
|
|
768
758
|
Ok(cx.undefined())
|
|
769
759
|
}
|
|
@@ -774,24 +764,29 @@ fn worker_complete_workflow_activation(mut cx: FunctionContext) -> JsResult<JsUn
|
|
|
774
764
|
let otel_span = cx.argument::<JsObject>(1)?;
|
|
775
765
|
let completion = cx.argument::<JsArrayBuffer>(2)?;
|
|
776
766
|
let callback = cx.argument::<JsFunction>(3)?;
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
767
|
+
match &*worker.borrow() {
|
|
768
|
+
None => {
|
|
769
|
+
callback_with_unexpected_error(&mut cx, callback, "Tried to use closed Worker")?;
|
|
770
|
+
}
|
|
771
|
+
Some(worker) => {
|
|
772
|
+
match WorkflowActivationCompletion::decode_length_delimited(
|
|
773
|
+
completion.as_slice(&mut cx),
|
|
774
|
+
) {
|
|
775
|
+
Ok(completion) => {
|
|
776
|
+
let request = WorkerRequest::CompleteWorkflowActivation {
|
|
777
|
+
completion,
|
|
778
|
+
otel_span: otel_span.as_otel_span_context(&mut cx)?,
|
|
779
|
+
callback: callback.root(&mut cx),
|
|
780
|
+
};
|
|
781
|
+
if let Err(err) = worker.sender.send(request) {
|
|
782
|
+
callback_with_unexpected_error(&mut cx, callback, err)?;
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
Err(_) => callback_with_error(&mut cx, callback, |cx| {
|
|
786
|
+
JsError::type_error(cx, "Cannot decode Completion from buffer")
|
|
787
|
+
})?,
|
|
788
|
+
}
|
|
791
789
|
}
|
|
792
|
-
Err(_) => callback_with_error(&mut cx, callback, |cx| {
|
|
793
|
-
JsError::type_error(cx, "Cannot decode Completion from buffer")
|
|
794
|
-
})?,
|
|
795
790
|
};
|
|
796
791
|
Ok(cx.undefined())
|
|
797
792
|
}
|
|
@@ -802,24 +797,27 @@ fn worker_complete_activity_task(mut cx: FunctionContext) -> JsResult<JsUndefine
|
|
|
802
797
|
let otel_span = cx.argument::<JsObject>(1)?;
|
|
803
798
|
let result = cx.argument::<JsArrayBuffer>(2)?;
|
|
804
799
|
let callback = cx.argument::<JsFunction>(3)?;
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
800
|
+
match &*worker.borrow() {
|
|
801
|
+
None => {
|
|
802
|
+
callback_with_unexpected_error(&mut cx, callback, "Tried to use closed Worker")?;
|
|
803
|
+
}
|
|
804
|
+
Some(worker) => {
|
|
805
|
+
match ActivityTaskCompletion::decode_length_delimited(result.as_slice(&mut cx)) {
|
|
806
|
+
Ok(completion) => {
|
|
807
|
+
let request = WorkerRequest::CompleteActivityTask {
|
|
808
|
+
completion,
|
|
809
|
+
otel_span: otel_span.as_otel_span_context(&mut cx)?,
|
|
810
|
+
callback: callback.root(&mut cx),
|
|
811
|
+
};
|
|
812
|
+
if let Err(err) = worker.sender.send(request) {
|
|
813
|
+
callback_with_unexpected_error(&mut cx, callback, err)?;
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
Err(_) => callback_with_error(&mut cx, callback, |cx| {
|
|
817
|
+
JsError::type_error(cx, "Cannot decode Completion from buffer")
|
|
818
|
+
})?,
|
|
819
|
+
}
|
|
819
820
|
}
|
|
820
|
-
Err(_) => callback_with_error(&mut cx, callback, |cx| {
|
|
821
|
-
JsError::type_error(cx, "Cannot decode Completion from buffer")
|
|
822
|
-
})?,
|
|
823
821
|
};
|
|
824
822
|
Ok(cx.undefined())
|
|
825
823
|
}
|
|
@@ -828,41 +826,59 @@ fn worker_complete_activity_task(mut cx: FunctionContext) -> JsResult<JsUndefine
|
|
|
828
826
|
fn worker_record_activity_heartbeat(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
829
827
|
let worker = cx.argument::<BoxedWorker>(0)?;
|
|
830
828
|
let heartbeat = cx.argument::<JsArrayBuffer>(1)?;
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
829
|
+
match &*worker.borrow() {
|
|
830
|
+
None => UNEXPECTED_ERROR
|
|
831
|
+
.from_string(&mut cx, "Tried to use closed Worker")
|
|
832
|
+
.and_then(|err| cx.throw(err))?,
|
|
833
|
+
Some(worker) => {
|
|
834
|
+
match ActivityHeartbeat::decode_length_delimited(heartbeat.as_slice(&mut cx)) {
|
|
835
|
+
Ok(heartbeat) => {
|
|
836
|
+
let request = WorkerRequest::RecordActivityHeartbeat { heartbeat };
|
|
837
|
+
if let Err(err) = worker.sender.send(request) {
|
|
838
|
+
UNEXPECTED_ERROR
|
|
839
|
+
.from_error(&mut cx, err)
|
|
840
|
+
.and_then(|err| cx.throw(err))?;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
Err(_) => cx.throw_type_error("Cannot decode ActivityHeartbeat from buffer")?,
|
|
845
844
|
}
|
|
846
845
|
}
|
|
847
|
-
|
|
848
|
-
|
|
846
|
+
};
|
|
847
|
+
Ok(cx.undefined())
|
|
849
848
|
}
|
|
850
849
|
|
|
851
850
|
/// Request shutdown of the worker.
|
|
852
851
|
/// Once complete Core will stop polling on new tasks and activations on worker's task queue.
|
|
853
|
-
/// Caller should drain any pending tasks and activations before breaking from
|
|
852
|
+
/// Caller should drain any pending tasks and activations and call worker_finalize_shutdown before breaking from
|
|
854
853
|
/// the loop to ensure graceful shutdown.
|
|
855
|
-
fn
|
|
854
|
+
fn worker_initiate_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
856
855
|
let worker = cx.argument::<BoxedWorker>(0)?;
|
|
857
856
|
let callback = cx.argument::<JsFunction>(1)?;
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
857
|
+
match &*worker.borrow() {
|
|
858
|
+
None => {
|
|
859
|
+
callback_with_unexpected_error(&mut cx, callback, "Tried to use closed Worker")?;
|
|
860
|
+
}
|
|
861
|
+
Some(worker) => {
|
|
862
|
+
if let Err(err) = worker.sender.send(WorkerRequest::InitiateShutdown {
|
|
863
|
+
callback: callback.root(&mut cx),
|
|
864
|
+
}) {
|
|
865
|
+
UNEXPECTED_ERROR
|
|
866
|
+
.from_error(&mut cx, err)
|
|
867
|
+
.and_then(|err| cx.throw(err))?;
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
Ok(cx.undefined())
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
fn worker_finalize_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
875
|
+
let worker = cx.argument::<BoxedWorker>(0)?;
|
|
876
|
+
if worker.replace(None).is_none() {
|
|
877
|
+
ILLEGAL_STATE_ERROR
|
|
878
|
+
.from_string(&mut cx, "Worker already closed")
|
|
864
879
|
.and_then(|err| cx.throw(err))?;
|
|
865
|
-
}
|
|
880
|
+
}
|
|
881
|
+
|
|
866
882
|
Ok(cx.undefined())
|
|
867
883
|
}
|
|
868
884
|
|
|
@@ -871,7 +887,7 @@ fn client_close(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
871
887
|
let client = cx.argument::<BoxedClient>(0)?;
|
|
872
888
|
if client.replace(None).is_none() {
|
|
873
889
|
ILLEGAL_STATE_ERROR
|
|
874
|
-
.
|
|
890
|
+
.from_string(&mut cx, "Client already closed")
|
|
875
891
|
.and_then(|err| cx.throw(err))?;
|
|
876
892
|
};
|
|
877
893
|
Ok(cx.undefined())
|
|
@@ -909,7 +925,8 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
|
|
909
925
|
cx.export_function("clientUpdateHeaders", client_update_headers)?;
|
|
910
926
|
cx.export_function("newWorker", worker_new)?;
|
|
911
927
|
cx.export_function("newReplayWorker", replay_worker_new)?;
|
|
912
|
-
cx.export_function("
|
|
928
|
+
cx.export_function("workerInitiateShutdown", worker_initiate_shutdown)?;
|
|
929
|
+
cx.export_function("workerFinalizeShutdown", worker_finalize_shutdown)?;
|
|
913
930
|
cx.export_function("clientClose", client_close)?;
|
|
914
931
|
cx.export_function("runtimeShutdown", runtime_shutdown)?;
|
|
915
932
|
cx.export_function("pollLogs", poll_logs)?;
|