@temporalio/core-bridge 1.13.0 → 1.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +239 -382
- package/Cargo.toml +11 -11
- package/lib/native.d.ts +10 -3
- package/package.json +3 -3
- 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/.cargo/config.toml +71 -11
- package/sdk-core/.clippy.toml +1 -0
- package/sdk-core/.github/workflows/heavy.yml +2 -0
- package/sdk-core/.github/workflows/per-pr.yml +50 -18
- package/sdk-core/ARCHITECTURE.md +44 -48
- package/sdk-core/Cargo.toml +26 -7
- package/sdk-core/README.md +4 -0
- package/sdk-core/arch_docs/diagrams/TimerMachine_Coverage.puml +14 -0
- package/sdk-core/arch_docs/diagrams/initial_event_history.png +0 -0
- package/sdk-core/arch_docs/sdks_intro.md +299 -0
- package/sdk-core/client/Cargo.toml +8 -7
- package/sdk-core/client/src/callback_based.rs +1 -2
- package/sdk-core/client/src/lib.rs +485 -299
- package/sdk-core/client/src/metrics.rs +32 -8
- package/sdk-core/client/src/proxy.rs +124 -5
- package/sdk-core/client/src/raw.rs +598 -307
- package/sdk-core/client/src/replaceable.rs +253 -0
- package/sdk-core/client/src/retry.rs +9 -6
- package/sdk-core/client/src/worker_registry/mod.rs +19 -3
- package/sdk-core/client/src/workflow_handle/mod.rs +20 -17
- package/sdk-core/core/Cargo.toml +100 -31
- package/sdk-core/core/src/core_tests/activity_tasks.rs +55 -225
- package/sdk-core/core/src/core_tests/mod.rs +2 -8
- package/sdk-core/core/src/core_tests/queries.rs +3 -5
- package/sdk-core/core/src/core_tests/replay_flag.rs +3 -62
- package/sdk-core/core/src/core_tests/updates.rs +4 -5
- package/sdk-core/core/src/core_tests/workers.rs +4 -3
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +10 -7
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +28 -291
- package/sdk-core/core/src/ephemeral_server/mod.rs +15 -3
- package/sdk-core/core/src/internal_flags.rs +11 -1
- package/sdk-core/core/src/lib.rs +50 -36
- package/sdk-core/core/src/pollers/mod.rs +5 -5
- package/sdk-core/core/src/pollers/poll_buffer.rs +2 -2
- package/sdk-core/core/src/protosext/mod.rs +13 -5
- package/sdk-core/core/src/protosext/protocol_messages.rs +4 -11
- package/sdk-core/core/src/retry_logic.rs +256 -108
- package/sdk-core/core/src/telemetry/metrics.rs +1 -0
- package/sdk-core/core/src/telemetry/mod.rs +8 -2
- package/sdk-core/core/src/telemetry/prometheus_meter.rs +2 -2
- package/sdk-core/core/src/test_help/integ_helpers.rs +971 -0
- package/sdk-core/core/src/test_help/mod.rs +10 -1100
- package/sdk-core/core/src/test_help/unit_helpers.rs +218 -0
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +42 -6
- package/sdk-core/core/src/worker/activities/local_activities.rs +19 -19
- package/sdk-core/core/src/worker/activities.rs +10 -3
- package/sdk-core/core/src/worker/client/mocks.rs +3 -3
- package/sdk-core/core/src/worker/client.rs +130 -93
- package/sdk-core/core/src/worker/heartbeat.rs +12 -13
- package/sdk-core/core/src/worker/mod.rs +31 -21
- package/sdk-core/core/src/worker/nexus.rs +14 -3
- package/sdk-core/core/src/worker/slot_provider.rs +9 -0
- package/sdk-core/core/src/worker/tuner.rs +159 -0
- package/sdk-core/core/src/worker/workflow/history_update.rs +3 -265
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -54
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +0 -82
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +0 -67
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -192
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +0 -43
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +6 -554
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -71
- package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +102 -3
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +10 -539
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +0 -139
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -119
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +6 -63
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +9 -4
- package/sdk-core/core/src/worker/workflow/mod.rs +5 -1
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +8 -3
- package/sdk-core/core-api/Cargo.toml +4 -4
- package/sdk-core/core-api/src/envconfig.rs +153 -54
- package/sdk-core/core-api/src/lib.rs +68 -0
- package/sdk-core/core-api/src/telemetry/metrics.rs +2 -1
- package/sdk-core/core-api/src/telemetry.rs +13 -0
- package/sdk-core/core-c-bridge/Cargo.toml +13 -8
- package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +184 -22
- package/sdk-core/core-c-bridge/src/client.rs +462 -184
- package/sdk-core/core-c-bridge/src/envconfig.rs +314 -0
- package/sdk-core/core-c-bridge/src/lib.rs +1 -0
- package/sdk-core/core-c-bridge/src/random.rs +4 -4
- package/sdk-core/core-c-bridge/src/runtime.rs +22 -23
- package/sdk-core/core-c-bridge/src/testing.rs +1 -4
- package/sdk-core/core-c-bridge/src/tests/context.rs +31 -31
- package/sdk-core/core-c-bridge/src/tests/mod.rs +32 -28
- package/sdk-core/core-c-bridge/src/tests/utils.rs +7 -7
- package/sdk-core/core-c-bridge/src/worker.rs +319 -66
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -1
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +5 -5
- package/sdk-core/sdk/Cargo.toml +8 -2
- package/sdk-core/sdk/src/activity_context.rs +1 -1
- package/sdk-core/sdk/src/app_data.rs +1 -1
- package/sdk-core/sdk/src/interceptors.rs +1 -4
- package/sdk-core/sdk/src/lib.rs +1 -5
- package/sdk-core/sdk/src/workflow_context/options.rs +10 -1
- package/sdk-core/sdk/src/workflow_future.rs +1 -1
- package/sdk-core/sdk-core-protos/Cargo.toml +6 -6
- package/sdk-core/sdk-core-protos/build.rs +10 -23
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +9 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +254 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +234 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +6 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -6
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
- package/sdk-core/{test-utils → sdk-core-protos}/src/canned_histories.rs +5 -5
- package/sdk-core/sdk-core-protos/src/history_builder.rs +2 -2
- package/sdk-core/sdk-core-protos/src/lib.rs +25 -9
- package/sdk-core/sdk-core-protos/src/test_utils.rs +89 -0
- package/sdk-core/sdk-core-protos/src/utilities.rs +14 -5
- package/sdk-core/tests/c_bridge_smoke_test.c +10 -0
- package/sdk-core/tests/cloud_tests.rs +10 -8
- package/sdk-core/tests/common/http_proxy.rs +134 -0
- package/sdk-core/{test-utils/src/lib.rs → tests/common/mod.rs} +214 -281
- package/sdk-core/{test-utils/src → tests/common}/workflows.rs +4 -3
- package/sdk-core/tests/fuzzy_workflow.rs +1 -1
- package/sdk-core/tests/global_metric_tests.rs +8 -7
- package/sdk-core/tests/heavy_tests.rs +7 -3
- package/sdk-core/tests/integ_tests/client_tests.rs +111 -24
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +14 -9
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +4 -4
- package/sdk-core/tests/integ_tests/metrics_tests.rs +114 -14
- package/sdk-core/tests/integ_tests/pagination_tests.rs +273 -0
- package/sdk-core/tests/integ_tests/polling_tests.rs +311 -93
- package/sdk-core/tests/integ_tests/queries_tests.rs +4 -4
- package/sdk-core/tests/integ_tests/update_tests.rs +13 -7
- package/sdk-core/tests/integ_tests/visibility_tests.rs +26 -9
- package/sdk-core/tests/integ_tests/worker_tests.rs +668 -13
- package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +40 -24
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +244 -11
- package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +78 -2
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +61 -2
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +465 -7
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +41 -2
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +315 -3
- package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1990 -14
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +65 -2
- package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +123 -23
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +525 -3
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +65 -16
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +32 -23
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +126 -5
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +1 -2
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +124 -8
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +62 -2
- package/sdk-core/tests/integ_tests/workflow_tests.rs +67 -8
- package/sdk-core/tests/main.rs +26 -17
- package/sdk-core/tests/manual_tests.rs +5 -1
- package/sdk-core/tests/runner.rs +22 -40
- package/sdk-core/tests/shared_tests/mod.rs +1 -1
- package/sdk-core/tests/shared_tests/priority.rs +1 -1
- package/sdk-core/{core/benches/workflow_replay.rs → tests/workflow_replay_bench.rs} +10 -5
- package/src/client.rs +97 -20
- package/src/helpers/callbacks.rs +4 -4
- package/src/helpers/errors.rs +7 -1
- package/src/helpers/handles.rs +1 -0
- package/src/helpers/try_from_js.rs +4 -3
- package/src/lib.rs +3 -2
- package/src/metrics.rs +3 -0
- package/src/runtime.rs +5 -2
- package/src/worker.rs +9 -12
- package/ts/native.ts +13 -3
- package/sdk-core/arch_docs/diagrams/workflow_internals.svg +0 -1
- package/sdk-core/core/src/core_tests/child_workflows.rs +0 -281
- package/sdk-core/core/src/core_tests/determinism.rs +0 -318
- package/sdk-core/core/src/core_tests/local_activities.rs +0 -1442
- package/sdk-core/test-utils/Cargo.toml +0 -38
- package/sdk-core/test-utils/src/histfetch.rs +0 -28
- package/sdk-core/test-utils/src/interceptors.rs +0 -46
|
@@ -1,12 +1,34 @@
|
|
|
1
|
-
use crate::
|
|
1
|
+
use crate::{
|
|
2
|
+
common::{
|
|
3
|
+
CoreWfStarter, INTEG_CLIENT_NAME, INTEG_CLIENT_VERSION, get_integ_server_options,
|
|
4
|
+
init_core_and_create_wf, init_integ_telem, integ_dev_server_config, integ_worker_config,
|
|
5
|
+
},
|
|
6
|
+
integ_tests::activity_functions::echo,
|
|
7
|
+
};
|
|
2
8
|
use assert_matches::assert_matches;
|
|
3
|
-
use
|
|
9
|
+
use futures_util::{FutureExt, StreamExt, future::join_all};
|
|
10
|
+
use std::{
|
|
11
|
+
process::Stdio,
|
|
12
|
+
sync::{
|
|
13
|
+
Arc, Mutex,
|
|
14
|
+
atomic::{AtomicBool, Ordering},
|
|
15
|
+
},
|
|
16
|
+
time::Duration,
|
|
17
|
+
};
|
|
4
18
|
use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowOptions};
|
|
5
19
|
use temporal_sdk::{ActivityOptions, WfContext};
|
|
6
20
|
use temporal_sdk_core::{
|
|
7
|
-
ClientOptionsBuilder,
|
|
21
|
+
ClientOptionsBuilder, CoreRuntime,
|
|
22
|
+
ephemeral_server::{TemporalDevServerConfigBuilder, default_cached_download},
|
|
23
|
+
init_worker,
|
|
24
|
+
telemetry::CoreLogStreamConsumer,
|
|
25
|
+
test_help::{NAMESPACE, WorkerTestHelpers, drain_pollers_and_shutdown},
|
|
26
|
+
};
|
|
27
|
+
use temporal_sdk_core_api::{
|
|
28
|
+
Worker,
|
|
29
|
+
telemetry::{Logger, TelemetryOptionsBuilder},
|
|
30
|
+
worker::PollerBehavior,
|
|
8
31
|
};
|
|
9
|
-
use temporal_sdk_core_api::{Worker, worker::PollerBehavior};
|
|
10
32
|
use temporal_sdk_core_protos::{
|
|
11
33
|
coresdk::{
|
|
12
34
|
AsJsonPayloadExt, IntoCompletion,
|
|
@@ -15,13 +37,11 @@ use temporal_sdk_core_protos::{
|
|
|
15
37
|
workflow_commands::{ActivityCancellationType, RequestCancelActivity, StartTimer},
|
|
16
38
|
workflow_completion::WorkflowActivationCompletion,
|
|
17
39
|
},
|
|
40
|
+
prost_dur,
|
|
18
41
|
temporal::api::enums::v1::EventType,
|
|
42
|
+
test_utils::schedule_activity_cmd,
|
|
19
43
|
};
|
|
20
|
-
use
|
|
21
|
-
CoreWfStarter, WorkerTestHelpers, default_cached_download, drain_pollers_and_shutdown,
|
|
22
|
-
init_core_and_create_wf, init_integ_telem, integ_worker_config, schedule_activity_cmd,
|
|
23
|
-
};
|
|
24
|
-
use tokio::time::timeout;
|
|
44
|
+
use tokio::{sync::Notify, time::timeout};
|
|
25
45
|
use tracing::info;
|
|
26
46
|
use url::Url;
|
|
27
47
|
|
|
@@ -115,101 +135,117 @@ async fn switching_worker_client_changes_poll() {
|
|
|
115
135
|
])
|
|
116
136
|
.build()
|
|
117
137
|
.unwrap();
|
|
118
|
-
let mut server1 = server_config
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// Connect clients to both servers
|
|
122
|
-
info!("Connecting clients");
|
|
123
|
-
let mut client_common_config = ClientOptionsBuilder::default();
|
|
124
|
-
client_common_config
|
|
125
|
-
.identity("integ_tester".to_owned())
|
|
126
|
-
.client_name("temporal-core".to_owned())
|
|
127
|
-
.client_version("0.1.0".to_owned());
|
|
128
|
-
let client1 = client_common_config
|
|
129
|
-
.clone()
|
|
130
|
-
.target_url(Url::parse(&format!("http://{}", server1.target)).unwrap())
|
|
131
|
-
.build()
|
|
132
|
-
.unwrap()
|
|
133
|
-
.connect("default", None)
|
|
138
|
+
let mut server1 = server_config
|
|
139
|
+
.start_server_with_output(Stdio::null(), Stdio::null())
|
|
134
140
|
.await
|
|
135
141
|
.unwrap();
|
|
136
|
-
let
|
|
137
|
-
.
|
|
138
|
-
.target_url(Url::parse(&format!("http://{}", server2.target)).unwrap())
|
|
139
|
-
.build()
|
|
140
|
-
.unwrap()
|
|
141
|
-
.connect("default", None)
|
|
142
|
+
let mut server2 = server_config
|
|
143
|
+
.start_server_with_output(Stdio::null(), Stdio::null())
|
|
142
144
|
.await
|
|
143
145
|
.unwrap();
|
|
144
146
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
"
|
|
164
|
-
|
|
165
|
-
|
|
147
|
+
let result = std::panic::AssertUnwindSafe(async {
|
|
148
|
+
// Connect clients to both servers
|
|
149
|
+
info!("Connecting clients");
|
|
150
|
+
let mut client_common_config = ClientOptionsBuilder::default();
|
|
151
|
+
client_common_config
|
|
152
|
+
.identity("integ_tester".to_owned())
|
|
153
|
+
.client_name("temporal-core".to_owned())
|
|
154
|
+
.client_version("0.1.0".to_owned());
|
|
155
|
+
let client1 = client_common_config
|
|
156
|
+
.clone()
|
|
157
|
+
.target_url(Url::parse(&format!("http://{}", server1.target)).unwrap())
|
|
158
|
+
.build()
|
|
159
|
+
.unwrap()
|
|
160
|
+
.connect("default", None)
|
|
161
|
+
.await
|
|
162
|
+
.unwrap();
|
|
163
|
+
let client2 = client_common_config
|
|
164
|
+
.clone()
|
|
165
|
+
.target_url(Url::parse(&format!("http://{}", server2.target)).unwrap())
|
|
166
|
+
.build()
|
|
167
|
+
.unwrap()
|
|
168
|
+
.connect("default", None)
|
|
169
|
+
.await
|
|
170
|
+
.unwrap();
|
|
171
|
+
|
|
172
|
+
// Start a workflow on both servers
|
|
173
|
+
info!("Starting workflows");
|
|
174
|
+
let wf1 = client1
|
|
175
|
+
.start_workflow(
|
|
176
|
+
vec![],
|
|
177
|
+
"my-task-queue".to_owned(),
|
|
178
|
+
"my-workflow-1".to_owned(),
|
|
179
|
+
"my-workflow-type".to_owned(),
|
|
180
|
+
None,
|
|
181
|
+
WorkflowOptions::default(),
|
|
182
|
+
)
|
|
183
|
+
.await
|
|
184
|
+
.unwrap();
|
|
185
|
+
let wf2 = client2
|
|
186
|
+
.start_workflow(
|
|
187
|
+
vec![],
|
|
188
|
+
"my-task-queue".to_owned(),
|
|
189
|
+
"my-workflow-2".to_owned(),
|
|
190
|
+
"my-workflow-type".to_owned(),
|
|
191
|
+
None,
|
|
192
|
+
WorkflowOptions::default(),
|
|
193
|
+
)
|
|
194
|
+
.await
|
|
195
|
+
.unwrap();
|
|
196
|
+
|
|
197
|
+
// Create a worker only on the first server
|
|
198
|
+
let worker = init_worker(
|
|
199
|
+
init_integ_telem().unwrap(),
|
|
200
|
+
integ_worker_config("my-task-queue")
|
|
201
|
+
// We want a cache so we don't get extra remove-job activations
|
|
202
|
+
.max_cached_workflows(100_usize)
|
|
203
|
+
.build()
|
|
204
|
+
.unwrap(),
|
|
205
|
+
client1.clone(),
|
|
166
206
|
)
|
|
167
|
-
.await
|
|
168
207
|
.unwrap();
|
|
169
208
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
209
|
+
// Poll for first task, confirm it's first wf, complete, and wait for complete
|
|
210
|
+
info!("Doing initial poll");
|
|
211
|
+
let act1 = worker.poll_workflow_activation().await.unwrap();
|
|
212
|
+
assert_eq!(wf1.run_id, act1.run_id);
|
|
213
|
+
worker.complete_execution(&act1.run_id).await;
|
|
214
|
+
worker.handle_eviction().await;
|
|
215
|
+
info!("Waiting on first workflow complete");
|
|
216
|
+
client1
|
|
217
|
+
.get_untyped_workflow_handle("my-workflow-1", wf1.run_id)
|
|
218
|
+
.get_workflow_result(Default::default())
|
|
219
|
+
.await
|
|
220
|
+
.unwrap();
|
|
181
221
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
222
|
+
// Swap client, poll for next task, confirm it's second wf, and respond w/ empty
|
|
223
|
+
info!("Replacing client and polling again");
|
|
224
|
+
worker.replace_client(client2.get_client().inner().clone());
|
|
225
|
+
let act2 = worker.poll_workflow_activation().await.unwrap();
|
|
226
|
+
assert_eq!(wf2.run_id, act2.run_id);
|
|
227
|
+
worker.complete_execution(&act2.run_id).await;
|
|
228
|
+
worker.handle_eviction().await;
|
|
229
|
+
info!("Waiting on second workflow complete");
|
|
230
|
+
client2
|
|
231
|
+
.get_untyped_workflow_handle("my-workflow-2", wf2.run_id)
|
|
232
|
+
.get_workflow_result(Default::default())
|
|
233
|
+
.await
|
|
234
|
+
.unwrap();
|
|
194
235
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
worker.complete_execution(&act2.run_id).await;
|
|
201
|
-
worker.handle_eviction().await;
|
|
202
|
-
info!("Waiting on second workflow complete");
|
|
203
|
-
client2
|
|
204
|
-
.get_untyped_workflow_handle("my-workflow-2", wf2.run_id)
|
|
205
|
-
.get_workflow_result(Default::default())
|
|
206
|
-
.await
|
|
207
|
-
.unwrap();
|
|
236
|
+
// Shutdown workers and servers
|
|
237
|
+
drain_pollers_and_shutdown(&(Arc::new(worker) as Arc<dyn Worker>)).await;
|
|
238
|
+
})
|
|
239
|
+
.catch_unwind()
|
|
240
|
+
.await;
|
|
208
241
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
242
|
+
let shutdown_results = join_all([server1.shutdown(), server2.shutdown()]).await;
|
|
243
|
+
if let Err(e) = result {
|
|
244
|
+
std::panic::resume_unwind(e);
|
|
245
|
+
}
|
|
246
|
+
for r in shutdown_results {
|
|
247
|
+
r.unwrap();
|
|
248
|
+
}
|
|
213
249
|
}
|
|
214
250
|
|
|
215
251
|
#[rstest::rstest]
|
|
@@ -292,3 +328,185 @@ async fn small_workflow_slots_and_pollers(#[values(false, true)] use_autoscaling
|
|
|
292
328
|
.any(|e| e.event_type() == EventType::WorkflowTaskTimedOut);
|
|
293
329
|
assert!(!any_task_timeouts);
|
|
294
330
|
}
|
|
331
|
+
|
|
332
|
+
#[tokio::test]
|
|
333
|
+
async fn replace_client_works_after_polling_failure() {
|
|
334
|
+
let (log_consumer, mut log_rx) = CoreLogStreamConsumer::new(100);
|
|
335
|
+
let telem_opts = TelemetryOptionsBuilder::default()
|
|
336
|
+
.logging(Logger::Push {
|
|
337
|
+
filter: "OFF,temporal_client=DEBUG".into(),
|
|
338
|
+
consumer: Arc::new(log_consumer),
|
|
339
|
+
})
|
|
340
|
+
.build()
|
|
341
|
+
.unwrap();
|
|
342
|
+
let rt = Arc::new(CoreRuntime::new_assume_tokio(telem_opts).unwrap());
|
|
343
|
+
|
|
344
|
+
// Spawning background task to read logs and notify the test when polling failure occurs.
|
|
345
|
+
let look_for_poll_failure_log = Arc::new(AtomicBool::new(false));
|
|
346
|
+
let poll_retry_log_found = Arc::new(Notify::new());
|
|
347
|
+
let log_reader_join_handle = tokio::spawn({
|
|
348
|
+
let look_for_poll_retry_log = look_for_poll_failure_log.clone();
|
|
349
|
+
let poll_retry_log_found = poll_retry_log_found.clone();
|
|
350
|
+
async move {
|
|
351
|
+
let mut enabled = false;
|
|
352
|
+
loop {
|
|
353
|
+
let Some(log) = log_rx.next().await else {
|
|
354
|
+
break;
|
|
355
|
+
};
|
|
356
|
+
if !enabled {
|
|
357
|
+
enabled = look_for_poll_retry_log.load(Ordering::Acquire);
|
|
358
|
+
}
|
|
359
|
+
if enabled
|
|
360
|
+
&& (log
|
|
361
|
+
.message
|
|
362
|
+
.starts_with("gRPC call poll_workflow_task_queue failed")
|
|
363
|
+
|| log
|
|
364
|
+
.message
|
|
365
|
+
.starts_with("gRPC call poll_workflow_task_queue retried"))
|
|
366
|
+
{
|
|
367
|
+
poll_retry_log_found.notify_one();
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
let abort_handles = Arc::new(Mutex::new(vec![log_reader_join_handle.abort_handle()]));
|
|
374
|
+
|
|
375
|
+
// Starting a second dev server for the worker to connect to initially. Later this server will be shut down
|
|
376
|
+
// and the worker client replaced with a client connected to the main integration test server.
|
|
377
|
+
let initial_server_config = integ_dev_server_config(vec![]).build().unwrap();
|
|
378
|
+
let initial_server = Arc::new(Mutex::new(Some(
|
|
379
|
+
initial_server_config
|
|
380
|
+
.start_server_with_output(Stdio::null(), Stdio::null())
|
|
381
|
+
.await
|
|
382
|
+
.unwrap(),
|
|
383
|
+
)));
|
|
384
|
+
|
|
385
|
+
let result = {
|
|
386
|
+
let initial_server = initial_server.clone();
|
|
387
|
+
let abort_handles = abort_handles.clone();
|
|
388
|
+
std::panic::AssertUnwindSafe(async move {
|
|
389
|
+
let initial_server_target = format!(
|
|
390
|
+
"http://{}",
|
|
391
|
+
initial_server.lock().unwrap().as_ref().unwrap().target
|
|
392
|
+
);
|
|
393
|
+
let client_for_initial_server = ClientOptionsBuilder::default()
|
|
394
|
+
.identity("client_for_initial_server".to_string())
|
|
395
|
+
.target_url(Url::parse(&initial_server_target).unwrap())
|
|
396
|
+
.client_name(INTEG_CLIENT_NAME.to_string())
|
|
397
|
+
.client_version(INTEG_CLIENT_VERSION.to_string())
|
|
398
|
+
.build()
|
|
399
|
+
.unwrap()
|
|
400
|
+
.connect(NAMESPACE, rt.telemetry().get_temporal_metric_meter())
|
|
401
|
+
.await
|
|
402
|
+
.unwrap();
|
|
403
|
+
|
|
404
|
+
let wf_name = "replace_client_works_after_polling_failure";
|
|
405
|
+
let task_queue = format!("{wf_name}_tq");
|
|
406
|
+
|
|
407
|
+
let worker = Arc::new(
|
|
408
|
+
init_worker(
|
|
409
|
+
&rt,
|
|
410
|
+
integ_worker_config(&task_queue)
|
|
411
|
+
.max_cached_workflows(100_usize)
|
|
412
|
+
.build()
|
|
413
|
+
.unwrap(),
|
|
414
|
+
client_for_initial_server.clone(),
|
|
415
|
+
)
|
|
416
|
+
.unwrap(),
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
// Polling the initial server the first time is successful.
|
|
420
|
+
let wf_1 = client_for_initial_server
|
|
421
|
+
.start_workflow(
|
|
422
|
+
vec![],
|
|
423
|
+
task_queue.clone(),
|
|
424
|
+
wf_name.into(),
|
|
425
|
+
wf_name.into(),
|
|
426
|
+
None,
|
|
427
|
+
WorkflowOptions::default(),
|
|
428
|
+
)
|
|
429
|
+
.await
|
|
430
|
+
.unwrap();
|
|
431
|
+
let act_1 =
|
|
432
|
+
tokio::time::timeout(Duration::from_secs(60), worker.poll_workflow_activation())
|
|
433
|
+
.await
|
|
434
|
+
.unwrap()
|
|
435
|
+
.unwrap();
|
|
436
|
+
assert_eq!(act_1.run_id, wf_1.run_id);
|
|
437
|
+
|
|
438
|
+
// Initial server is shut down.
|
|
439
|
+
let mut server = initial_server.lock().unwrap().take().unwrap();
|
|
440
|
+
server.shutdown().await.unwrap();
|
|
441
|
+
|
|
442
|
+
// Start polling in a background task.
|
|
443
|
+
look_for_poll_failure_log.store(true, Ordering::Release);
|
|
444
|
+
let poll_join_handle = tokio::spawn({
|
|
445
|
+
let worker = worker.clone();
|
|
446
|
+
async move { worker.poll_workflow_activation().await }
|
|
447
|
+
});
|
|
448
|
+
abort_handles
|
|
449
|
+
.try_lock()
|
|
450
|
+
.unwrap()
|
|
451
|
+
.push(poll_join_handle.abort_handle());
|
|
452
|
+
|
|
453
|
+
// Wait until polling failure is detected.
|
|
454
|
+
tokio::time::timeout(Duration::from_secs(60), poll_retry_log_found.notified())
|
|
455
|
+
.await
|
|
456
|
+
.unwrap();
|
|
457
|
+
|
|
458
|
+
// Start a new WF on main integration server.
|
|
459
|
+
let client_for_integ_server = get_integ_server_options()
|
|
460
|
+
.connect(NAMESPACE, rt.telemetry().get_temporal_metric_meter())
|
|
461
|
+
.await
|
|
462
|
+
.unwrap();
|
|
463
|
+
let wf_2 = client_for_integ_server
|
|
464
|
+
.start_workflow(
|
|
465
|
+
vec![],
|
|
466
|
+
task_queue,
|
|
467
|
+
wf_name.into(),
|
|
468
|
+
wf_name.into(),
|
|
469
|
+
None,
|
|
470
|
+
WorkflowOptions {
|
|
471
|
+
execution_timeout: Some(Duration::from_secs(60)),
|
|
472
|
+
..Default::default()
|
|
473
|
+
},
|
|
474
|
+
)
|
|
475
|
+
.await
|
|
476
|
+
.unwrap();
|
|
477
|
+
|
|
478
|
+
// Switch worker over to the main integration server.
|
|
479
|
+
// The polling started on the initial server should complete with a task from the new server.
|
|
480
|
+
worker.replace_client(client_for_integ_server);
|
|
481
|
+
let act_2 = tokio::time::timeout(Duration::from_secs(60), poll_join_handle)
|
|
482
|
+
.await
|
|
483
|
+
.unwrap()
|
|
484
|
+
.unwrap()
|
|
485
|
+
.unwrap();
|
|
486
|
+
assert_eq!(act_2.run_id, wf_2.run_id);
|
|
487
|
+
})
|
|
488
|
+
}
|
|
489
|
+
.catch_unwind()
|
|
490
|
+
.await;
|
|
491
|
+
|
|
492
|
+
// Cleaning up spawned background tasks if they're still running.
|
|
493
|
+
for handle in &*abort_handles.lock().unwrap() {
|
|
494
|
+
handle.abort();
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// If the test panicked, we may or may not need to shut down the server here.
|
|
498
|
+
// If the test succeeded, the server should always be shut down by this point.
|
|
499
|
+
let server = initial_server.lock().unwrap().take();
|
|
500
|
+
if let Some(mut server) = server {
|
|
501
|
+
let _ = server.shutdown().await;
|
|
502
|
+
assert_matches!(
|
|
503
|
+
result,
|
|
504
|
+
Err(_),
|
|
505
|
+
"Server should have been shut down during the test"
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if let Err(e) = result {
|
|
510
|
+
std::panic::resume_unwind(e);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
use crate::common::{CoreWfStarter, init_core_and_create_wf};
|
|
1
2
|
use assert_matches::assert_matches;
|
|
2
3
|
use futures_util::{FutureExt, StreamExt, future::join_all, stream::FuturesUnordered};
|
|
3
4
|
use std::time::{Duration, Instant};
|
|
4
5
|
use temporal_client::WorkflowClientTrait;
|
|
6
|
+
use temporal_sdk_core::test_help::{WorkerTestHelpers, drain_pollers_and_shutdown};
|
|
5
7
|
use temporal_sdk_core_protos::{
|
|
6
8
|
coresdk::{
|
|
7
9
|
workflow_activation::{WorkflowActivationJob, workflow_activation_job},
|
|
8
10
|
workflow_commands::{QueryResult, QuerySuccess, StartTimer},
|
|
9
11
|
workflow_completion::WorkflowActivationCompletion,
|
|
10
12
|
},
|
|
13
|
+
prost_dur,
|
|
11
14
|
temporal::api::{failure::v1::Failure, query::v1::WorkflowQuery},
|
|
12
|
-
|
|
13
|
-
use temporal_sdk_core_test_utils::{
|
|
14
|
-
CoreWfStarter, WorkerTestHelpers, drain_pollers_and_shutdown, init_core_and_create_wf,
|
|
15
|
-
start_timer_cmd,
|
|
15
|
+
test_utils::start_timer_cmd,
|
|
16
16
|
};
|
|
17
17
|
use tokio::join;
|
|
18
18
|
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
use crate::common::{
|
|
2
|
+
CoreWfStarter, WorkflowHandleExt, init_core_and_create_wf, init_core_replay_preloaded,
|
|
3
|
+
};
|
|
1
4
|
use anyhow::anyhow;
|
|
2
5
|
use assert_matches::assert_matches;
|
|
3
6
|
use futures_util::{StreamExt, future, future::join_all};
|
|
@@ -12,7 +15,10 @@ use temporal_client::{
|
|
|
12
15
|
Client, NamespacedClient, RetryClient, WorkflowClientTrait, WorkflowService,
|
|
13
16
|
};
|
|
14
17
|
use temporal_sdk::{ActContext, ActivityOptions, LocalActivityOptions, UpdateContext, WfContext};
|
|
15
|
-
use temporal_sdk_core::
|
|
18
|
+
use temporal_sdk_core::{
|
|
19
|
+
replay::HistoryForReplay,
|
|
20
|
+
test_help::{WorkerTestHelpers, drain_pollers_and_shutdown},
|
|
21
|
+
};
|
|
16
22
|
use temporal_sdk_core_api::Worker;
|
|
17
23
|
use temporal_sdk_core_protos::{
|
|
18
24
|
coresdk::{
|
|
@@ -26,18 +32,17 @@ use temporal_sdk_core_protos::{
|
|
|
26
32
|
},
|
|
27
33
|
workflow_completion::WorkflowActivationCompletion,
|
|
28
34
|
},
|
|
35
|
+
prost_dur,
|
|
29
36
|
temporal::api::{
|
|
30
37
|
common::v1::WorkflowExecution,
|
|
31
38
|
enums::v1::{EventType, ResetReapplyType, UpdateWorkflowExecutionLifecycleStage},
|
|
32
39
|
update::{self, v1::WaitPolicy},
|
|
33
40
|
workflowservice::v1::ResetWorkflowExecutionRequest,
|
|
34
41
|
},
|
|
35
|
-
|
|
36
|
-
use temporal_sdk_core_test_utils::{
|
|
37
|
-
CoreWfStarter, WorkerTestHelpers, WorkflowHandleExt, drain_pollers_and_shutdown,
|
|
38
|
-
init_core_and_create_wf, init_core_replay_preloaded, start_timer_cmd,
|
|
42
|
+
test_utils::start_timer_cmd,
|
|
39
43
|
};
|
|
40
44
|
use tokio::{join, sync::Barrier};
|
|
45
|
+
use tonic::IntoRequest;
|
|
41
46
|
use uuid::Uuid;
|
|
42
47
|
|
|
43
48
|
#[derive(Clone, Copy)]
|
|
@@ -112,7 +117,7 @@ async fn reapplied_updates_due_to_reset() {
|
|
|
112
117
|
Arc::make_mut(&mut client_mut),
|
|
113
118
|
#[allow(deprecated)]
|
|
114
119
|
ResetWorkflowExecutionRequest {
|
|
115
|
-
namespace: client.namespace()
|
|
120
|
+
namespace: client.namespace(),
|
|
116
121
|
workflow_execution: Some(WorkflowExecution {
|
|
117
122
|
workflow_id: workflow_id.into(),
|
|
118
123
|
run_id: pre_reset_run_id.clone(),
|
|
@@ -121,7 +126,8 @@ async fn reapplied_updates_due_to_reset() {
|
|
|
121
126
|
reset_reapply_type: ResetReapplyType::AllEligible as i32,
|
|
122
127
|
request_id: Uuid::new_v4().to_string(),
|
|
123
128
|
..Default::default()
|
|
124
|
-
}
|
|
129
|
+
}
|
|
130
|
+
.into_request(),
|
|
125
131
|
)
|
|
126
132
|
.await
|
|
127
133
|
.unwrap()
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
+
use crate::common::{CoreWfStarter, NAMESPACE, eventually, get_integ_server_options};
|
|
1
2
|
use assert_matches::assert_matches;
|
|
2
3
|
use std::{sync::Arc, time::Duration};
|
|
3
4
|
use temporal_client::{
|
|
4
5
|
ListClosedFilters, ListOpenFilters, Namespace, RegisterNamespaceOptions, StartTimeFilter,
|
|
5
6
|
WorkflowClientTrait, WorkflowExecutionFilter,
|
|
6
7
|
};
|
|
8
|
+
use temporal_sdk_core::test_help::{WorkerTestHelpers, drain_pollers_and_shutdown};
|
|
7
9
|
use temporal_sdk_core_protos::coresdk::workflow_activation::{
|
|
8
10
|
WorkflowActivationJob, workflow_activation_job,
|
|
9
11
|
};
|
|
10
|
-
use temporal_sdk_core_test_utils::{
|
|
11
|
-
CoreWfStarter, NAMESPACE, WorkerTestHelpers, drain_pollers_and_shutdown,
|
|
12
|
-
get_integ_server_options,
|
|
13
|
-
};
|
|
14
12
|
use tokio::time::sleep;
|
|
15
13
|
|
|
16
14
|
#[tokio::test]
|
|
@@ -42,11 +40,30 @@ async fn client_list_open_closed_workflow_executions() {
|
|
|
42
40
|
workflow_id: wf_name.clone(),
|
|
43
41
|
run_id: "".to_owned(),
|
|
44
42
|
});
|
|
45
|
-
let open_workflows =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
let open_workflows = eventually(
|
|
44
|
+
|| async {
|
|
45
|
+
let open_workflows = client
|
|
46
|
+
.list_open_workflow_executions(
|
|
47
|
+
1,
|
|
48
|
+
Default::default(),
|
|
49
|
+
Some(start_time_filter),
|
|
50
|
+
Some(filter.clone()),
|
|
51
|
+
)
|
|
52
|
+
.await
|
|
53
|
+
.unwrap();
|
|
54
|
+
if open_workflows.executions.len() == 1 {
|
|
55
|
+
Ok(open_workflows)
|
|
56
|
+
} else {
|
|
57
|
+
Err(format!(
|
|
58
|
+
"Expected 1 open workflow, got {}",
|
|
59
|
+
open_workflows.executions.len()
|
|
60
|
+
))
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
Duration::from_secs(5),
|
|
64
|
+
)
|
|
65
|
+
.await
|
|
66
|
+
.unwrap();
|
|
50
67
|
let workflow = open_workflows.executions[0].clone();
|
|
51
68
|
assert_eq!(workflow.execution.as_ref().unwrap().workflow_id, wf_name);
|
|
52
69
|
|