@temporalio/core-bridge 0.22.0 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +120 -15
- package/Cargo.toml +3 -1
- package/README.md +1 -1
- package/index.d.ts +137 -33
- package/package.json +6 -6
- 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/lib.rs +1 -1
- package/sdk-core/bridge-ffi/src/wrappers.rs +60 -37
- package/sdk-core/client/Cargo.toml +1 -0
- package/sdk-core/client/src/lib.rs +50 -15
- package/sdk-core/client/src/raw.rs +167 -55
- 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/benches/workflow_replay.rs +1 -7
- 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 +8 -5
- package/sdk-core/core/src/pollers/poll_buffer.rs +16 -10
- package/sdk-core/core/src/protosext/mod.rs +7 -9
- package/sdk-core/core/src/retry_logic.rs +73 -16
- package/sdk-core/core/src/telemetry/metrics.rs +21 -7
- package/sdk-core/core/src/telemetry/mod.rs +182 -110
- 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 +22 -25
- 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 +27 -6
- 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 +87 -176
- package/sdk-core/test-utils/src/histfetch.rs +1 -1
- package/sdk-core/test-utils/src/lib.rs +93 -77
- package/sdk-core/tests/integ_tests/client_tests.rs +2 -2
- 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 +7 -3
- package/src/conversions.rs +149 -70
- package/src/errors.rs +10 -21
- package/src/lib.rs +400 -319
- 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
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
mod conversions;
|
|
2
2
|
mod errors;
|
|
3
3
|
|
|
4
|
-
use crate::conversions::ObjectHandleConversionsExt;
|
|
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};
|
|
10
|
+
use parking_lot::RwLock;
|
|
9
11
|
use prost::Message;
|
|
12
|
+
use std::collections::HashMap;
|
|
13
|
+
use std::ops::Deref;
|
|
10
14
|
use std::{
|
|
11
15
|
cell::RefCell,
|
|
12
16
|
fmt::Display,
|
|
@@ -20,7 +24,7 @@ use temporal_client::{
|
|
|
20
24
|
use temporal_sdk_core::{
|
|
21
25
|
api::{
|
|
22
26
|
errors::{CompleteActivityError, CompleteWfError, PollActivityError, PollWfError},
|
|
23
|
-
Worker as
|
|
27
|
+
Worker as CoreWorkerTrait,
|
|
24
28
|
},
|
|
25
29
|
fetch_global_buffered_logs, init_replay_worker, init_worker,
|
|
26
30
|
protos::{
|
|
@@ -30,17 +34,18 @@ use temporal_sdk_core::{
|
|
|
30
34
|
},
|
|
31
35
|
temporal::api::history::v1::History,
|
|
32
36
|
},
|
|
33
|
-
telemetry_init, ClientOptions, RetryClient, WorkerConfig,
|
|
37
|
+
telemetry_init, ClientOptions, RetryClient, Worker as CoreWorker, WorkerConfig,
|
|
34
38
|
};
|
|
35
39
|
use tokio::{
|
|
36
40
|
runtime::Runtime,
|
|
37
41
|
sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
|
38
42
|
};
|
|
43
|
+
use tokio_stream::wrappers::UnboundedReceiverStream;
|
|
39
44
|
|
|
40
45
|
type RawClient = RetryClient<ConfiguredClient<WorkflowServiceClientWithMetrics>>;
|
|
41
46
|
|
|
42
47
|
/// A request from JS to bridge to core
|
|
43
|
-
enum
|
|
48
|
+
enum RuntimeRequest {
|
|
44
49
|
/// A request to shutdown the runtime, breaks from the thread loop.
|
|
45
50
|
Shutdown {
|
|
46
51
|
/// Used to send the result back into JS
|
|
@@ -50,19 +55,19 @@ enum Request {
|
|
|
50
55
|
CreateClient {
|
|
51
56
|
runtime: Arc<RuntimeHandle>,
|
|
52
57
|
options: ClientOptions,
|
|
58
|
+
headers: Option<HashMap<String, String>>,
|
|
53
59
|
/// Used to send the result back into JS
|
|
54
60
|
callback: Root<JsFunction>,
|
|
55
61
|
},
|
|
56
|
-
/// A request to
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
/// A request to update a client's HTTP request headers
|
|
63
|
+
UpdateClientHeaders {
|
|
64
|
+
client: Arc<RawClient>,
|
|
65
|
+
headers: HashMap<String, String>,
|
|
60
66
|
/// Used to send the result back into JS
|
|
61
67
|
callback: Root<JsFunction>,
|
|
62
68
|
},
|
|
63
69
|
/// A request to create a new Worker using a connected client
|
|
64
70
|
InitWorker {
|
|
65
|
-
runtime: Arc<RuntimeHandle>,
|
|
66
71
|
/// Worker configuration e.g. limits and task queue
|
|
67
72
|
config: WorkerConfig,
|
|
68
73
|
/// A client created with a [CreateClient] request
|
|
@@ -72,7 +77,6 @@ enum Request {
|
|
|
72
77
|
},
|
|
73
78
|
/// A request to register a replay worker
|
|
74
79
|
InitReplayWorker {
|
|
75
|
-
runtime: Arc<RuntimeHandle>,
|
|
76
80
|
/// Worker configuration. Must have unique task queue name.
|
|
77
81
|
config: WorkerConfig,
|
|
78
82
|
/// The history this worker should replay
|
|
@@ -80,16 +84,29 @@ enum Request {
|
|
|
80
84
|
/// Used to send the result back into JS
|
|
81
85
|
callback: Root<JsFunction>,
|
|
82
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
|
+
},
|
|
83
102
|
/// A request to poll for workflow activations
|
|
84
103
|
PollWorkflowActivation {
|
|
85
|
-
worker: Arc<dyn CoreWorker>,
|
|
86
104
|
otel_span: SpanContext,
|
|
87
105
|
/// Used to send the result back into JS
|
|
88
106
|
callback: Root<JsFunction>,
|
|
89
107
|
},
|
|
90
108
|
/// A request to complete a single workflow activation
|
|
91
109
|
CompleteWorkflowActivation {
|
|
92
|
-
worker: Arc<dyn CoreWorker>,
|
|
93
110
|
completion: WorkflowActivationCompletion,
|
|
94
111
|
otel_span: SpanContext,
|
|
95
112
|
/// Used to send the result back into JS
|
|
@@ -97,33 +114,23 @@ enum Request {
|
|
|
97
114
|
},
|
|
98
115
|
/// A request to poll for activity tasks
|
|
99
116
|
PollActivityTask {
|
|
100
|
-
worker: Arc<dyn CoreWorker>,
|
|
101
117
|
otel_span: SpanContext,
|
|
102
118
|
/// Used to report completion or error back into JS
|
|
103
119
|
callback: Root<JsFunction>,
|
|
104
120
|
},
|
|
105
121
|
/// A request to complete a single activity task
|
|
106
122
|
CompleteActivityTask {
|
|
107
|
-
worker: Arc<dyn CoreWorker>,
|
|
108
123
|
completion: ActivityTaskCompletion,
|
|
109
124
|
otel_span: SpanContext,
|
|
110
125
|
/// Used to send the result back into JS
|
|
111
126
|
callback: Root<JsFunction>,
|
|
112
127
|
},
|
|
113
128
|
/// A request to send a heartbeat from a running activity
|
|
114
|
-
RecordActivityHeartbeat {
|
|
115
|
-
worker: Arc<dyn CoreWorker>,
|
|
116
|
-
heartbeat: ActivityHeartbeat,
|
|
117
|
-
},
|
|
118
|
-
/// A request to drain logs from core so they can be emitted in node
|
|
119
|
-
PollLogs {
|
|
120
|
-
/// Logs are sent to this function
|
|
121
|
-
callback: Root<JsFunction>,
|
|
122
|
-
},
|
|
129
|
+
RecordActivityHeartbeat { heartbeat: ActivityHeartbeat },
|
|
123
130
|
}
|
|
124
131
|
|
|
125
132
|
struct RuntimeHandle {
|
|
126
|
-
sender: UnboundedSender<
|
|
133
|
+
sender: UnboundedSender<RuntimeRequest>,
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
/// Box it so we can use the runtime from JS
|
|
@@ -141,34 +148,30 @@ impl Finalize for Client {}
|
|
|
141
148
|
|
|
142
149
|
/// Worker struct, hold a reference for the channel sender responsible for sending requests from
|
|
143
150
|
/// JS to a bridge thread which forwards them to core
|
|
144
|
-
struct
|
|
145
|
-
|
|
146
|
-
core_worker: Arc<dyn CoreWorker>,
|
|
151
|
+
struct WorkerHandle {
|
|
152
|
+
sender: UnboundedSender<WorkerRequest>,
|
|
147
153
|
}
|
|
148
154
|
|
|
149
155
|
/// Box it so we can use Worker from JS
|
|
150
|
-
type BoxedWorker = JsBox<
|
|
151
|
-
impl Finalize for
|
|
152
|
-
|
|
153
|
-
///
|
|
154
|
-
fn tokio_runtime() ->
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
.build()
|
|
161
|
-
.expect("Tokio runtime must construct properly")
|
|
162
|
-
})
|
|
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")
|
|
163
166
|
}
|
|
164
167
|
|
|
165
|
-
/// Send a result to JS via callback using
|
|
166
|
-
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)
|
|
167
170
|
where
|
|
168
171
|
F: for<'a> FnOnce(&mut TaskContext<'a>) -> NeonResult<Handle<'a, T>> + Send + 'static,
|
|
169
172
|
T: Value,
|
|
170
173
|
{
|
|
171
|
-
|
|
174
|
+
channel.send(move |mut cx| {
|
|
172
175
|
let callback = callback.into_inner(&mut cx);
|
|
173
176
|
let this = cx.undefined();
|
|
174
177
|
let error = cx.undefined();
|
|
@@ -179,13 +182,13 @@ where
|
|
|
179
182
|
});
|
|
180
183
|
}
|
|
181
184
|
|
|
182
|
-
/// Send an error to JS via callback using
|
|
183
|
-
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)
|
|
184
187
|
where
|
|
185
188
|
E: Object,
|
|
186
189
|
F: for<'a> FnOnce(&mut TaskContext<'a>) -> JsResult<'a, E> + Send + 'static,
|
|
187
190
|
{
|
|
188
|
-
|
|
191
|
+
channel.send(move |mut cx| {
|
|
189
192
|
let callback = callback.into_inner(&mut cx);
|
|
190
193
|
callback_with_error(&mut cx, callback, error_ctor)
|
|
191
194
|
});
|
|
@@ -226,33 +229,33 @@ where
|
|
|
226
229
|
})
|
|
227
230
|
}
|
|
228
231
|
|
|
229
|
-
/// 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
|
|
230
233
|
/// undefined
|
|
231
234
|
async fn void_future_to_js<E, F, ER, EF>(
|
|
232
|
-
|
|
235
|
+
channel: Arc<Channel>,
|
|
233
236
|
callback: Root<JsFunction>,
|
|
234
237
|
f: F,
|
|
235
238
|
error_function: EF,
|
|
236
239
|
) where
|
|
237
240
|
E: Display + Send + 'static,
|
|
238
|
-
F: Future<Output = Result<(), E>> + Send
|
|
241
|
+
F: Future<Output = Result<(), E>> + Send,
|
|
239
242
|
ER: Object,
|
|
240
243
|
EF: for<'a> FnOnce(&mut TaskContext<'a>, E) -> JsResult<'a, ER> + Send + 'static,
|
|
241
244
|
{
|
|
242
245
|
match f.await {
|
|
243
246
|
Ok(()) => {
|
|
244
|
-
send_result(
|
|
247
|
+
send_result(channel, callback, |cx| Ok(cx.undefined()));
|
|
245
248
|
}
|
|
246
249
|
Err(err) => {
|
|
247
|
-
send_error(
|
|
250
|
+
send_error(channel, callback, |cx| error_function(cx, err));
|
|
248
251
|
}
|
|
249
252
|
}
|
|
250
253
|
}
|
|
251
254
|
|
|
252
|
-
/// Builds a tokio runtime and starts polling on [
|
|
253
|
-
/// 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.
|
|
254
257
|
/// Blocks current thread until a [Shutdown] request is received in channel.
|
|
255
|
-
fn start_bridge_loop(
|
|
258
|
+
fn start_bridge_loop(channel: Arc<Channel>, receiver: &mut UnboundedReceiver<RuntimeRequest>) {
|
|
256
259
|
tokio_runtime().block_on(async {
|
|
257
260
|
loop {
|
|
258
261
|
let request_option = receiver.recv().await;
|
|
@@ -261,48 +264,65 @@ fn start_bridge_loop(event_queue: Arc<EventQueue>, receiver: &mut UnboundedRecei
|
|
|
261
264
|
Some(request) => request,
|
|
262
265
|
};
|
|
263
266
|
|
|
264
|
-
let
|
|
267
|
+
let channel = channel.clone();
|
|
265
268
|
|
|
266
269
|
match request {
|
|
267
|
-
|
|
268
|
-
send_result(
|
|
270
|
+
RuntimeRequest::Shutdown { callback } => {
|
|
271
|
+
send_result(channel, callback, |cx| Ok(cx.undefined()));
|
|
269
272
|
break;
|
|
270
273
|
}
|
|
271
|
-
|
|
274
|
+
RuntimeRequest::CreateClient {
|
|
272
275
|
runtime,
|
|
273
276
|
options,
|
|
277
|
+
headers,
|
|
274
278
|
callback,
|
|
275
279
|
} => {
|
|
276
280
|
// `metrics_meter` (second arg) can be None here since we don't use the
|
|
277
281
|
// returned client directly at the moment, when we repurpose the client to be
|
|
278
282
|
// used by a Worker, `init_worker` will attach the correct metrics meter for
|
|
279
283
|
// us.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
})
|
|
299
|
-
}
|
|
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
|
+
}
|
|
300
312
|
}
|
|
301
|
-
}
|
|
313
|
+
});
|
|
302
314
|
}
|
|
303
|
-
|
|
315
|
+
RuntimeRequest::UpdateClientHeaders {
|
|
316
|
+
client,
|
|
317
|
+
headers,
|
|
318
|
+
callback,
|
|
319
|
+
} => {
|
|
320
|
+
client.get_client().set_headers(headers);
|
|
321
|
+
send_result(channel.clone(), callback, |cx| Ok(cx.undefined()));
|
|
322
|
+
}
|
|
323
|
+
RuntimeRequest::PollLogs { callback } => {
|
|
304
324
|
let logs = fetch_global_buffered_logs();
|
|
305
|
-
send_result(
|
|
325
|
+
send_result(channel.clone(), callback, |cx| {
|
|
306
326
|
let logarr = cx.empty_array();
|
|
307
327
|
for (i, cl) in logs.into_iter().enumerate() {
|
|
308
328
|
// Not much to do here except for panic when there's an
|
|
@@ -319,21 +339,7 @@ fn start_bridge_loop(event_queue: Arc<EventQueue>, receiver: &mut UnboundedRecei
|
|
|
319
339
|
Ok(logarr)
|
|
320
340
|
});
|
|
321
341
|
}
|
|
322
|
-
|
|
323
|
-
tokio::spawn(void_future_to_js(
|
|
324
|
-
event_queue,
|
|
325
|
-
callback,
|
|
326
|
-
async move {
|
|
327
|
-
worker.shutdown().await;
|
|
328
|
-
// Wrap the empty result in a valid Result object
|
|
329
|
-
let result: Result<(), String> = Ok(());
|
|
330
|
-
result
|
|
331
|
-
},
|
|
332
|
-
|cx, err| UNEXPECTED_ERROR.from_error(cx, err),
|
|
333
|
-
));
|
|
334
|
-
}
|
|
335
|
-
Request::InitWorker {
|
|
336
|
-
runtime,
|
|
342
|
+
RuntimeRequest::InitWorker {
|
|
337
343
|
config,
|
|
338
344
|
client,
|
|
339
345
|
callback,
|
|
@@ -341,134 +347,139 @@ fn start_bridge_loop(event_queue: Arc<EventQueue>, receiver: &mut UnboundedRecei
|
|
|
341
347
|
let client = (*client).clone();
|
|
342
348
|
let worker =
|
|
343
349
|
init_worker(config, AnyClient::LowLevel(Box::new(client.into_inner())));
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}))
|
|
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 }))))
|
|
349
354
|
});
|
|
350
355
|
}
|
|
351
|
-
|
|
352
|
-
runtime,
|
|
356
|
+
RuntimeRequest::InitReplayWorker {
|
|
353
357
|
config,
|
|
354
358
|
history,
|
|
355
359
|
callback,
|
|
356
360
|
} => {
|
|
357
361
|
match init_replay_worker(config, &history) {
|
|
358
|
-
Ok(worker) =>
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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())
|
|
366
371
|
}),
|
|
367
372
|
};
|
|
368
373
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
+
} => {
|
|
375
401
|
handle_poll_workflow_activation_request(
|
|
376
|
-
|
|
377
|
-
otel_span,
|
|
378
|
-
event_queue,
|
|
379
|
-
callback,
|
|
402
|
+
&worker, otel_span, channel, callback,
|
|
380
403
|
)
|
|
381
404
|
.await
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
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,
|
|
394
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
|
+
},
|
|
395
437
|
)
|
|
396
|
-
.await
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
completion,
|
|
402
|
-
otel_span,
|
|
403
|
-
callback,
|
|
404
|
-
} => {
|
|
405
|
-
let otel_ctx =
|
|
406
|
-
opentelemetry::Context::new().with_remote_span_context(otel_span);
|
|
407
|
-
tokio::spawn(void_future_to_js(
|
|
408
|
-
event_queue,
|
|
409
|
-
callback,
|
|
410
|
-
async move {
|
|
411
|
-
worker
|
|
412
|
-
.complete_workflow_activation(completion)
|
|
413
|
-
.with_context(otel_ctx)
|
|
414
|
-
.await
|
|
415
|
-
},
|
|
416
|
-
|cx, err| match err {
|
|
417
|
-
CompleteWfError::NoWorkerForQueue(queue_name) => {
|
|
418
|
-
let args = vec![cx.string(queue_name).upcast()];
|
|
419
|
-
NO_WORKER_ERROR.construct(cx, args)
|
|
420
|
-
}
|
|
421
|
-
CompleteWfError::TonicError(_) => TRANSPORT_ERROR.from_error(cx, err),
|
|
422
|
-
CompleteWfError::MalformedWorkflowCompletion { reason, .. } => {
|
|
423
|
-
Ok(JsError::type_error(cx, reason)?.upcast())
|
|
424
|
-
}
|
|
425
|
-
},
|
|
426
|
-
));
|
|
427
|
-
}
|
|
428
|
-
Request::CompleteActivityTask {
|
|
429
|
-
worker,
|
|
430
|
-
completion,
|
|
431
|
-
otel_span,
|
|
432
|
-
callback,
|
|
433
|
-
} => {
|
|
434
|
-
let otel_ctx =
|
|
435
|
-
opentelemetry::Context::new().with_remote_span_context(otel_span);
|
|
436
|
-
tokio::spawn(void_future_to_js(
|
|
437
|
-
event_queue,
|
|
438
|
+
.await;
|
|
439
|
+
}
|
|
440
|
+
WorkerRequest::CompleteActivityTask {
|
|
441
|
+
completion,
|
|
442
|
+
otel_span,
|
|
438
443
|
callback,
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
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
|
+
}
|
|
461
471
|
}
|
|
462
472
|
}
|
|
463
|
-
}
|
|
464
|
-
|
|
473
|
+
})
|
|
474
|
+
.await;
|
|
475
|
+
worker.finalize_shutdown().await;
|
|
465
476
|
}
|
|
466
477
|
|
|
467
478
|
/// Called within the poll loop thread, calls core and triggers JS callback with result
|
|
468
479
|
async fn handle_poll_workflow_activation_request(
|
|
469
|
-
worker: &
|
|
480
|
+
worker: &CoreWorker,
|
|
470
481
|
span_context: SpanContext,
|
|
471
|
-
|
|
482
|
+
channel: Arc<Channel>,
|
|
472
483
|
callback: Root<JsFunction>,
|
|
473
484
|
) {
|
|
474
485
|
let otel_ctx = opentelemetry::Context::new().with_remote_span_context(span_context);
|
|
@@ -478,24 +489,19 @@ async fn handle_poll_workflow_activation_request(
|
|
|
478
489
|
.await
|
|
479
490
|
{
|
|
480
491
|
Ok(task) => {
|
|
481
|
-
send_result(
|
|
492
|
+
send_result(channel, callback, move |cx| {
|
|
482
493
|
let len = task.encoded_len();
|
|
483
|
-
let mut result = JsArrayBuffer::new(cx, len
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
};
|
|
489
|
-
});
|
|
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
|
+
};
|
|
490
499
|
Ok(result)
|
|
491
500
|
});
|
|
492
501
|
}
|
|
493
502
|
Err(err) => {
|
|
494
|
-
send_error(
|
|
503
|
+
send_error(channel, callback, move |cx| match err {
|
|
495
504
|
PollWfError::ShutDown => SHUTDOWN_ERROR.from_error(cx, err),
|
|
496
|
-
PollWfError::AutocompleteError(CompleteWfError::NoWorkerForQueue(_)) => {
|
|
497
|
-
UNEXPECTED_ERROR.from_error(cx, "TODO this error shouldn't exist")
|
|
498
|
-
}
|
|
499
505
|
PollWfError::TonicError(_)
|
|
500
506
|
| PollWfError::AutocompleteError(CompleteWfError::TonicError(_)) => {
|
|
501
507
|
TRANSPORT_ERROR.from_error(cx, err)
|
|
@@ -511,28 +517,26 @@ async fn handle_poll_workflow_activation_request(
|
|
|
511
517
|
|
|
512
518
|
/// Called within the poll loop thread, calls core and triggers JS callback with result
|
|
513
519
|
async fn handle_poll_activity_task_request(
|
|
514
|
-
worker: &
|
|
520
|
+
worker: &CoreWorker,
|
|
515
521
|
span_context: SpanContext,
|
|
516
|
-
|
|
522
|
+
channel: Arc<Channel>,
|
|
517
523
|
callback: Root<JsFunction>,
|
|
518
524
|
) {
|
|
519
525
|
let otel_ctx = opentelemetry::Context::new().with_remote_span_context(span_context);
|
|
520
526
|
match worker.poll_activity_task().with_context(otel_ctx).await {
|
|
521
527
|
Ok(task) => {
|
|
522
|
-
send_result(
|
|
528
|
+
send_result(channel, callback, move |cx| {
|
|
523
529
|
let len = task.encoded_len();
|
|
524
|
-
let mut result = JsArrayBuffer::new(cx, len
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
};
|
|
530
|
-
});
|
|
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
|
+
};
|
|
531
535
|
Ok(result)
|
|
532
536
|
});
|
|
533
537
|
}
|
|
534
538
|
Err(err) => {
|
|
535
|
-
send_error(
|
|
539
|
+
send_error(channel, callback, move |cx| match err {
|
|
536
540
|
PollActivityError::ShutDown => SHUTDOWN_ERROR.from_error(cx, err),
|
|
537
541
|
PollActivityError::TonicError(_) => TRANSPORT_ERROR.from_error(cx, err),
|
|
538
542
|
});
|
|
@@ -554,12 +558,12 @@ fn init_telemetry(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
554
558
|
}
|
|
555
559
|
|
|
556
560
|
/// Create the tokio runtime required to run Core.
|
|
557
|
-
/// Immediately spawns a poller thread that will block on [
|
|
561
|
+
/// Immediately spawns a poller thread that will block on [RuntimeRequest]s
|
|
558
562
|
fn runtime_new(mut cx: FunctionContext) -> JsResult<BoxedRuntime> {
|
|
559
|
-
let
|
|
560
|
-
let (sender, mut receiver) = unbounded_channel::<
|
|
563
|
+
let channel = Arc::new(cx.channel());
|
|
564
|
+
let (sender, mut receiver) = unbounded_channel::<RuntimeRequest>();
|
|
561
565
|
|
|
562
|
-
std::thread::spawn(move || start_bridge_loop(
|
|
566
|
+
std::thread::spawn(move || start_bridge_loop(channel, &mut receiver));
|
|
563
567
|
|
|
564
568
|
Ok(cx.boxed(Arc::new(RuntimeHandle { sender })))
|
|
565
569
|
}
|
|
@@ -568,12 +572,28 @@ fn runtime_new(mut cx: FunctionContext) -> JsResult<BoxedRuntime> {
|
|
|
568
572
|
/// Client will be returned in the supplied `callback`.
|
|
569
573
|
fn client_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
570
574
|
let runtime = cx.argument::<BoxedRuntime>(0)?;
|
|
571
|
-
let
|
|
575
|
+
let opts = cx.argument::<JsObject>(1)?;
|
|
572
576
|
let callback = cx.argument::<JsFunction>(2)?;
|
|
573
577
|
|
|
574
|
-
let
|
|
578
|
+
let client_options = opts.as_client_options(&mut cx)?;
|
|
579
|
+
let headers = match js_optional_getter!(&mut cx, &opts, "metadata", JsObject) {
|
|
580
|
+
None => None,
|
|
581
|
+
Some(h) => Some(
|
|
582
|
+
h.as_hash_map_of_string_to_string(&mut cx)
|
|
583
|
+
.map_err(|reason| {
|
|
584
|
+
cx.throw_type_error::<_, HashMap<String, String>>(format!(
|
|
585
|
+
"Invalid metadata: {}",
|
|
586
|
+
reason
|
|
587
|
+
))
|
|
588
|
+
.unwrap_err()
|
|
589
|
+
})?,
|
|
590
|
+
),
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
let request = RuntimeRequest::CreateClient {
|
|
575
594
|
runtime: (**runtime).clone(),
|
|
576
595
|
options: client_options,
|
|
596
|
+
headers,
|
|
577
597
|
callback: callback.root(&mut cx),
|
|
578
598
|
};
|
|
579
599
|
if let Err(err) = runtime.sender.send(request) {
|
|
@@ -583,6 +603,33 @@ fn client_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
583
603
|
Ok(cx.undefined())
|
|
584
604
|
}
|
|
585
605
|
|
|
606
|
+
/// Update a Client's HTTP request headers
|
|
607
|
+
fn client_update_headers(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
608
|
+
let client = cx.argument::<BoxedClient>(0)?;
|
|
609
|
+
let headers = cx
|
|
610
|
+
.argument::<JsObject>(1)?
|
|
611
|
+
.as_hash_map_of_string_to_string(&mut cx)?;
|
|
612
|
+
let callback = cx.argument::<JsFunction>(2)?;
|
|
613
|
+
|
|
614
|
+
match &*client.borrow() {
|
|
615
|
+
None => {
|
|
616
|
+
callback_with_unexpected_error(&mut cx, callback, "Tried to use closed Client")?;
|
|
617
|
+
}
|
|
618
|
+
Some(client) => {
|
|
619
|
+
let request = RuntimeRequest::UpdateClientHeaders {
|
|
620
|
+
client: client.core_client.clone(),
|
|
621
|
+
headers,
|
|
622
|
+
callback: callback.root(&mut cx),
|
|
623
|
+
};
|
|
624
|
+
if let Err(err) = client.runtime.sender.send(request) {
|
|
625
|
+
callback_with_unexpected_error(&mut cx, callback, err)?;
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
Ok(cx.undefined())
|
|
631
|
+
}
|
|
632
|
+
|
|
586
633
|
/// Create a new worker asynchronously.
|
|
587
634
|
/// Worker uses the provided connection and returned to JS using supplied `callback`.
|
|
588
635
|
fn worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
@@ -593,14 +640,11 @@ fn worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
593
640
|
let config = worker_options.as_worker_config(&mut cx)?;
|
|
594
641
|
match &*client.borrow() {
|
|
595
642
|
None => {
|
|
596
|
-
|
|
597
|
-
UNEXPECTED_ERROR.from_string(cx, "Tried to use closed Client".to_string())
|
|
598
|
-
})?;
|
|
643
|
+
callback_with_unexpected_error(&mut cx, callback, "Tried to use closed Client")?;
|
|
599
644
|
}
|
|
600
645
|
Some(client) => {
|
|
601
|
-
let request =
|
|
646
|
+
let request = RuntimeRequest::InitWorker {
|
|
602
647
|
client: client.core_client.clone(),
|
|
603
|
-
runtime: client.runtime.clone(),
|
|
604
648
|
config,
|
|
605
649
|
callback: callback.root(&mut cx),
|
|
606
650
|
};
|
|
@@ -622,13 +666,10 @@ fn replay_worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
622
666
|
let callback = cx.argument::<JsFunction>(3)?;
|
|
623
667
|
|
|
624
668
|
let config = worker_options.as_worker_config(&mut cx)?;
|
|
625
|
-
|
|
626
|
-
match
|
|
627
|
-
History::decode_length_delimited(data.as_slice::<u8>())
|
|
628
|
-
}) {
|
|
669
|
+
let data = history_binary.as_slice(&mut cx);
|
|
670
|
+
match History::decode_length_delimited(data) {
|
|
629
671
|
Ok(history) => {
|
|
630
|
-
let request =
|
|
631
|
-
runtime: (**runtime).clone(),
|
|
672
|
+
let request = RuntimeRequest::InitReplayWorker {
|
|
632
673
|
config,
|
|
633
674
|
history,
|
|
634
675
|
callback: callback.root(&mut cx),
|
|
@@ -649,7 +690,7 @@ fn replay_worker_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
649
690
|
fn runtime_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
650
691
|
let runtime = cx.argument::<BoxedRuntime>(0)?;
|
|
651
692
|
let callback = cx.argument::<JsFunction>(1)?;
|
|
652
|
-
let request =
|
|
693
|
+
let request = RuntimeRequest::Shutdown {
|
|
653
694
|
callback: callback.root(&mut cx),
|
|
654
695
|
};
|
|
655
696
|
if let Err(err) = runtime.sender.send(request) {
|
|
@@ -662,7 +703,7 @@ fn runtime_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
662
703
|
fn poll_logs(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
663
704
|
let runtime = cx.argument::<BoxedRuntime>(0)?;
|
|
664
705
|
let callback = cx.argument::<JsFunction>(1)?;
|
|
665
|
-
let request =
|
|
706
|
+
let request = RuntimeRequest::PollLogs {
|
|
666
707
|
callback: callback.root(&mut cx),
|
|
667
708
|
};
|
|
668
709
|
if let Err(err) = runtime.sender.send(request) {
|
|
@@ -677,13 +718,19 @@ fn worker_poll_workflow_activation(mut cx: FunctionContext) -> JsResult<JsUndefi
|
|
|
677
718
|
let worker = cx.argument::<BoxedWorker>(0)?;
|
|
678
719
|
let otel_span = cx.argument::<JsObject>(1)?;
|
|
679
720
|
let callback = cx.argument::<JsFunction>(2)?;
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
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
|
+
}
|
|
687
734
|
}
|
|
688
735
|
Ok(cx.undefined())
|
|
689
736
|
}
|
|
@@ -694,13 +741,19 @@ fn worker_poll_activity_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
694
741
|
let worker = cx.argument::<BoxedWorker>(0)?;
|
|
695
742
|
let otel_span = cx.argument::<JsObject>(1)?;
|
|
696
743
|
let callback = cx.argument::<JsFunction>(2)?;
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
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
|
+
}
|
|
704
757
|
}
|
|
705
758
|
Ok(cx.undefined())
|
|
706
759
|
}
|
|
@@ -711,24 +764,29 @@ fn worker_complete_workflow_activation(mut cx: FunctionContext) -> JsResult<JsUn
|
|
|
711
764
|
let otel_span = cx.argument::<JsObject>(1)?;
|
|
712
765
|
let completion = cx.argument::<JsArrayBuffer>(2)?;
|
|
713
766
|
let callback = cx.argument::<JsFunction>(3)?;
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
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
|
+
}
|
|
728
789
|
}
|
|
729
|
-
Err(_) => callback_with_error(&mut cx, callback, |cx| {
|
|
730
|
-
JsError::type_error(cx, "Cannot decode Completion from buffer")
|
|
731
|
-
})?,
|
|
732
790
|
};
|
|
733
791
|
Ok(cx.undefined())
|
|
734
792
|
}
|
|
@@ -739,24 +797,27 @@ fn worker_complete_activity_task(mut cx: FunctionContext) -> JsResult<JsUndefine
|
|
|
739
797
|
let otel_span = cx.argument::<JsObject>(1)?;
|
|
740
798
|
let result = cx.argument::<JsArrayBuffer>(2)?;
|
|
741
799
|
let callback = cx.argument::<JsFunction>(3)?;
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
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
|
+
}
|
|
756
820
|
}
|
|
757
|
-
Err(_) => callback_with_error(&mut cx, callback, |cx| {
|
|
758
|
-
JsError::type_error(cx, "Cannot decode Completion from buffer")
|
|
759
|
-
})?,
|
|
760
821
|
};
|
|
761
822
|
Ok(cx.undefined())
|
|
762
823
|
}
|
|
@@ -765,41 +826,59 @@ fn worker_complete_activity_task(mut cx: FunctionContext) -> JsResult<JsUndefine
|
|
|
765
826
|
fn worker_record_activity_heartbeat(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
766
827
|
let worker = cx.argument::<BoxedWorker>(0)?;
|
|
767
828
|
let heartbeat = cx.argument::<JsArrayBuffer>(1)?;
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
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")?,
|
|
782
844
|
}
|
|
783
845
|
}
|
|
784
|
-
|
|
785
|
-
|
|
846
|
+
};
|
|
847
|
+
Ok(cx.undefined())
|
|
786
848
|
}
|
|
787
849
|
|
|
788
850
|
/// Request shutdown of the worker.
|
|
789
851
|
/// Once complete Core will stop polling on new tasks and activations on worker's task queue.
|
|
790
|
-
/// 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
|
|
791
853
|
/// the loop to ensure graceful shutdown.
|
|
792
|
-
fn
|
|
854
|
+
fn worker_initiate_shutdown(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
793
855
|
let worker = cx.argument::<BoxedWorker>(0)?;
|
|
794
856
|
let callback = cx.argument::<JsFunction>(1)?;
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
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")
|
|
801
879
|
.and_then(|err| cx.throw(err))?;
|
|
802
|
-
}
|
|
880
|
+
}
|
|
881
|
+
|
|
803
882
|
Ok(cx.undefined())
|
|
804
883
|
}
|
|
805
884
|
|
|
@@ -808,7 +887,7 @@ fn client_close(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|
|
808
887
|
let client = cx.argument::<BoxedClient>(0)?;
|
|
809
888
|
if client.replace(None).is_none() {
|
|
810
889
|
ILLEGAL_STATE_ERROR
|
|
811
|
-
.
|
|
890
|
+
.from_string(&mut cx, "Client already closed")
|
|
812
891
|
.and_then(|err| cx.throw(err))?;
|
|
813
892
|
};
|
|
814
893
|
Ok(cx.undefined())
|
|
@@ -843,9 +922,11 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
|
|
843
922
|
cx.export_function("initTelemetry", init_telemetry)?;
|
|
844
923
|
cx.export_function("newRuntime", runtime_new)?;
|
|
845
924
|
cx.export_function("newClient", client_new)?;
|
|
925
|
+
cx.export_function("clientUpdateHeaders", client_update_headers)?;
|
|
846
926
|
cx.export_function("newWorker", worker_new)?;
|
|
847
927
|
cx.export_function("newReplayWorker", replay_worker_new)?;
|
|
848
|
-
cx.export_function("
|
|
928
|
+
cx.export_function("workerInitiateShutdown", worker_initiate_shutdown)?;
|
|
929
|
+
cx.export_function("workerFinalizeShutdown", worker_finalize_shutdown)?;
|
|
849
930
|
cx.export_function("clientClose", client_close)?;
|
|
850
931
|
cx.export_function("runtimeShutdown", runtime_shutdown)?;
|
|
851
932
|
cx.export_function("pollLogs", poll_logs)?;
|