@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,10 +1,25 @@
|
|
|
1
|
+
use crate::common::{CoreWfStarter, WorkflowHandleExt, mock_sdk, mock_sdk_cfg};
|
|
1
2
|
use std::{
|
|
2
3
|
sync::atomic::{AtomicBool, AtomicUsize, Ordering},
|
|
3
4
|
time::Duration,
|
|
4
5
|
};
|
|
5
|
-
use
|
|
6
|
-
use
|
|
7
|
-
|
|
6
|
+
use temporal_client::WorkflowOptions;
|
|
7
|
+
use temporal_sdk::{
|
|
8
|
+
ActContext, ActivityOptions, ChildWorkflowOptions, LocalActivityOptions, WfContext,
|
|
9
|
+
WorkflowResult,
|
|
10
|
+
};
|
|
11
|
+
use temporal_sdk_core::{
|
|
12
|
+
replay::DEFAULT_WORKFLOW_TYPE,
|
|
13
|
+
test_help::{CoreInternalFlags, MockPollCfg, ResponseType, mock_worker_client},
|
|
14
|
+
};
|
|
15
|
+
use temporal_sdk_core_protos::{
|
|
16
|
+
DEFAULT_ACTIVITY_TYPE, TestHistoryBuilder, canned_histories,
|
|
17
|
+
coresdk::AsJsonPayloadExt,
|
|
18
|
+
temporal::api::{
|
|
19
|
+
enums::v1::{EventType, WorkflowTaskFailedCause},
|
|
20
|
+
failure::v1::Failure,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
8
23
|
|
|
9
24
|
static RUN_CT: AtomicUsize = AtomicUsize::new(1);
|
|
10
25
|
|
|
@@ -83,3 +98,300 @@ async fn task_fail_causes_replay_unset_too_soon() {
|
|
|
83
98
|
.await
|
|
84
99
|
.unwrap();
|
|
85
100
|
}
|
|
101
|
+
|
|
102
|
+
async fn timer_wf_fails_once(ctx: WfContext) -> WorkflowResult<()> {
|
|
103
|
+
static DID_FAIL: AtomicBool = AtomicBool::new(false);
|
|
104
|
+
|
|
105
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
106
|
+
if DID_FAIL
|
|
107
|
+
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
|
108
|
+
.is_ok()
|
|
109
|
+
{
|
|
110
|
+
panic!("Ahh");
|
|
111
|
+
}
|
|
112
|
+
Ok(().into())
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// Verifies that workflow panics (which in this case the Rust SDK turns into workflow activation
|
|
116
|
+
/// failures) are turned into unspecified WFT failures.
|
|
117
|
+
#[tokio::test]
|
|
118
|
+
async fn test_panic_wf_task_rejected_properly() {
|
|
119
|
+
let wf_id = "fakeid";
|
|
120
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
121
|
+
let t = canned_histories::workflow_fails_with_failure_after_timer("1");
|
|
122
|
+
let mock = mock_worker_client();
|
|
123
|
+
let mut mh = MockPollCfg::from_resp_batches(wf_id, t, [1, 2, 2], mock);
|
|
124
|
+
// We should see one wft failure which has unspecified cause, since panics don't have a defined
|
|
125
|
+
// type.
|
|
126
|
+
mh.num_expected_fails = 1;
|
|
127
|
+
mh.expect_fail_wft_matcher =
|
|
128
|
+
Box::new(|_, cause, _| matches!(cause, WorkflowTaskFailedCause::Unspecified));
|
|
129
|
+
let mut worker = mock_sdk(mh);
|
|
130
|
+
|
|
131
|
+
worker.register_wf(wf_type.to_owned(), timer_wf_fails_once);
|
|
132
|
+
worker
|
|
133
|
+
.submit_wf(
|
|
134
|
+
wf_id.to_owned(),
|
|
135
|
+
wf_type.to_owned(),
|
|
136
|
+
vec![],
|
|
137
|
+
WorkflowOptions::default(),
|
|
138
|
+
)
|
|
139
|
+
.await
|
|
140
|
+
.unwrap();
|
|
141
|
+
worker.run_until_done().await.unwrap();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/// Verifies nondeterministic behavior in workflows results in automatic WFT failure with the
|
|
145
|
+
/// appropriate nondeterminism cause.
|
|
146
|
+
#[rstest::rstest]
|
|
147
|
+
#[case::with_cache(true)]
|
|
148
|
+
#[case::without_cache(false)]
|
|
149
|
+
#[tokio::test]
|
|
150
|
+
async fn test_wf_task_rejected_properly_due_to_nondeterminism(#[case] use_cache: bool) {
|
|
151
|
+
let wf_id = "fakeid";
|
|
152
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
153
|
+
let t = canned_histories::single_timer_wf_completes("1");
|
|
154
|
+
let mock = mock_worker_client();
|
|
155
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
156
|
+
wf_id,
|
|
157
|
+
t,
|
|
158
|
+
// Two polls are needed, since the first will fail
|
|
159
|
+
[ResponseType::AllHistory, ResponseType::AllHistory],
|
|
160
|
+
mock,
|
|
161
|
+
);
|
|
162
|
+
// We should see one wft failure which has nondeterminism cause
|
|
163
|
+
mh.num_expected_fails = 1;
|
|
164
|
+
mh.expect_fail_wft_matcher =
|
|
165
|
+
Box::new(|_, cause, _| matches!(cause, WorkflowTaskFailedCause::NonDeterministicError));
|
|
166
|
+
let mut worker = mock_sdk_cfg(mh, |cfg| {
|
|
167
|
+
if use_cache {
|
|
168
|
+
cfg.max_cached_workflows = 2;
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
let started_count: &'static _ = Box::leak(Box::new(AtomicUsize::new(0)));
|
|
173
|
+
worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
|
|
174
|
+
// The workflow is replaying all of history, so the when it schedules an extra timer it
|
|
175
|
+
// should not have, it causes a nondeterminism error.
|
|
176
|
+
if started_count.fetch_add(1, Ordering::Relaxed) == 0 {
|
|
177
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
178
|
+
}
|
|
179
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
180
|
+
Ok(().into())
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
worker
|
|
184
|
+
.submit_wf(
|
|
185
|
+
wf_id.to_owned(),
|
|
186
|
+
wf_type.to_owned(),
|
|
187
|
+
vec![],
|
|
188
|
+
WorkflowOptions::default(),
|
|
189
|
+
)
|
|
190
|
+
.await
|
|
191
|
+
.unwrap();
|
|
192
|
+
worker.run_until_done().await.unwrap();
|
|
193
|
+
// Started count is two since we start, restart once due to error, then we unblock the real
|
|
194
|
+
// timer and proceed without restarting
|
|
195
|
+
assert_eq!(2, started_count.load(Ordering::Relaxed));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
#[rstest::rstest]
|
|
199
|
+
#[tokio::test]
|
|
200
|
+
async fn activity_id_or_type_change_is_nondeterministic(
|
|
201
|
+
#[values(true, false)] use_cache: bool,
|
|
202
|
+
#[values(true, false)] id_change: bool,
|
|
203
|
+
#[values(true, false)] local_act: bool,
|
|
204
|
+
) {
|
|
205
|
+
let wf_id = "fakeid";
|
|
206
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
207
|
+
let mut t: TestHistoryBuilder = if local_act {
|
|
208
|
+
canned_histories::single_local_activity("1")
|
|
209
|
+
} else {
|
|
210
|
+
canned_histories::single_activity("1")
|
|
211
|
+
};
|
|
212
|
+
t.set_flags_first_wft(&[CoreInternalFlags::IdAndTypeDeterminismChecks as u32], &[]);
|
|
213
|
+
let mock = mock_worker_client();
|
|
214
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
215
|
+
wf_id,
|
|
216
|
+
t,
|
|
217
|
+
// Two polls are needed, since the first will fail
|
|
218
|
+
[ResponseType::AllHistory, ResponseType::AllHistory],
|
|
219
|
+
mock,
|
|
220
|
+
);
|
|
221
|
+
// We should see one wft failure which has nondeterminism cause
|
|
222
|
+
mh.num_expected_fails = 1;
|
|
223
|
+
mh.expect_fail_wft_matcher = Box::new(move |_, cause, f| {
|
|
224
|
+
let should_contain = if id_change {
|
|
225
|
+
"does not match activity id"
|
|
226
|
+
} else {
|
|
227
|
+
"does not match activity type"
|
|
228
|
+
};
|
|
229
|
+
matches!(cause, WorkflowTaskFailedCause::NonDeterministicError)
|
|
230
|
+
&& matches!(f, Some(Failure {
|
|
231
|
+
message,
|
|
232
|
+
..
|
|
233
|
+
}) if message.contains(should_contain))
|
|
234
|
+
});
|
|
235
|
+
let mut worker = mock_sdk_cfg(mh, |cfg| {
|
|
236
|
+
if use_cache {
|
|
237
|
+
cfg.max_cached_workflows = 2;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
|
|
242
|
+
if local_act {
|
|
243
|
+
ctx.local_activity(if id_change {
|
|
244
|
+
LocalActivityOptions {
|
|
245
|
+
activity_id: Some("I'm bad and wrong!".to_string()),
|
|
246
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
247
|
+
..Default::default()
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
250
|
+
LocalActivityOptions {
|
|
251
|
+
activity_type: "not the default act type".to_string(),
|
|
252
|
+
..Default::default()
|
|
253
|
+
}
|
|
254
|
+
})
|
|
255
|
+
.await;
|
|
256
|
+
} else {
|
|
257
|
+
ctx.activity(if id_change {
|
|
258
|
+
ActivityOptions {
|
|
259
|
+
activity_id: Some("I'm bad and wrong!".to_string()),
|
|
260
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
261
|
+
..Default::default()
|
|
262
|
+
}
|
|
263
|
+
} else {
|
|
264
|
+
ActivityOptions {
|
|
265
|
+
activity_type: "not the default act type".to_string(),
|
|
266
|
+
..Default::default()
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
.await;
|
|
270
|
+
}
|
|
271
|
+
Ok(().into())
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
worker
|
|
275
|
+
.submit_wf(
|
|
276
|
+
wf_id.to_owned(),
|
|
277
|
+
wf_type.to_owned(),
|
|
278
|
+
vec![],
|
|
279
|
+
WorkflowOptions::default(),
|
|
280
|
+
)
|
|
281
|
+
.await
|
|
282
|
+
.unwrap();
|
|
283
|
+
worker.run_until_done().await.unwrap();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
#[rstest::rstest]
|
|
287
|
+
#[tokio::test]
|
|
288
|
+
async fn child_wf_id_or_type_change_is_nondeterministic(
|
|
289
|
+
#[values(true, false)] use_cache: bool,
|
|
290
|
+
#[values(true, false)] id_change: bool,
|
|
291
|
+
) {
|
|
292
|
+
let wf_id = "fakeid";
|
|
293
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
294
|
+
let mut t = canned_histories::single_child_workflow("1");
|
|
295
|
+
t.set_flags_first_wft(&[CoreInternalFlags::IdAndTypeDeterminismChecks as u32], &[]);
|
|
296
|
+
let mock = mock_worker_client();
|
|
297
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
298
|
+
wf_id,
|
|
299
|
+
t,
|
|
300
|
+
// Two polls are needed, since the first will fail
|
|
301
|
+
[ResponseType::AllHistory, ResponseType::AllHistory],
|
|
302
|
+
mock,
|
|
303
|
+
);
|
|
304
|
+
// We should see one wft failure which has nondeterminism cause
|
|
305
|
+
mh.num_expected_fails = 1;
|
|
306
|
+
mh.expect_fail_wft_matcher = Box::new(move |_, cause, f| {
|
|
307
|
+
let should_contain = if id_change {
|
|
308
|
+
"does not match child workflow id"
|
|
309
|
+
} else {
|
|
310
|
+
"does not match child workflow type"
|
|
311
|
+
};
|
|
312
|
+
matches!(cause, WorkflowTaskFailedCause::NonDeterministicError)
|
|
313
|
+
&& matches!(f, Some(Failure {
|
|
314
|
+
message,
|
|
315
|
+
..
|
|
316
|
+
}) if message.contains(should_contain))
|
|
317
|
+
});
|
|
318
|
+
let mut worker = mock_sdk_cfg(mh, |cfg| {
|
|
319
|
+
if use_cache {
|
|
320
|
+
cfg.max_cached_workflows = 2;
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
|
|
325
|
+
ctx.child_workflow(if id_change {
|
|
326
|
+
ChildWorkflowOptions {
|
|
327
|
+
workflow_id: "I'm bad and wrong!".to_string(),
|
|
328
|
+
workflow_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
329
|
+
..Default::default()
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
ChildWorkflowOptions {
|
|
333
|
+
workflow_id: "1".to_string(),
|
|
334
|
+
workflow_type: "not the child wf type".to_string(),
|
|
335
|
+
..Default::default()
|
|
336
|
+
}
|
|
337
|
+
})
|
|
338
|
+
.start(&ctx)
|
|
339
|
+
.await;
|
|
340
|
+
Ok(().into())
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
worker
|
|
344
|
+
.submit_wf(
|
|
345
|
+
wf_id.to_owned(),
|
|
346
|
+
wf_type.to_owned(),
|
|
347
|
+
vec![],
|
|
348
|
+
WorkflowOptions::default(),
|
|
349
|
+
)
|
|
350
|
+
.await
|
|
351
|
+
.unwrap();
|
|
352
|
+
worker.run_until_done().await.unwrap();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/// Repros a situation where if, upon completing a task there is some internal error which causes
|
|
356
|
+
/// us to want to auto-fail the workflow task while there is also an outstanding eviction, the wf
|
|
357
|
+
/// would get evicted but then try to send some info down the completion channel afterward, causing
|
|
358
|
+
/// a panic.
|
|
359
|
+
#[tokio::test]
|
|
360
|
+
async fn repro_channel_missing_because_nondeterminism() {
|
|
361
|
+
for _ in 1..50 {
|
|
362
|
+
let wf_id = "fakeid";
|
|
363
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
364
|
+
let mut t = TestHistoryBuilder::default();
|
|
365
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
366
|
+
t.add_full_wf_task();
|
|
367
|
+
t.add_has_change_marker("patch-1", false);
|
|
368
|
+
let _ts = t.add_by_type(EventType::TimerStarted);
|
|
369
|
+
t.add_workflow_task_scheduled_and_started();
|
|
370
|
+
|
|
371
|
+
let mock = mock_worker_client();
|
|
372
|
+
let mut mh =
|
|
373
|
+
MockPollCfg::from_resp_batches(wf_id, t, [1.into(), ResponseType::AllHistory], mock);
|
|
374
|
+
mh.num_expected_fails = 1;
|
|
375
|
+
let mut worker = mock_sdk_cfg(mh, |cfg| {
|
|
376
|
+
cfg.max_cached_workflows = 2;
|
|
377
|
+
cfg.ignore_evicts_on_shutdown = false;
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
|
|
381
|
+
ctx.patched("wrongid");
|
|
382
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
383
|
+
Ok(().into())
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
worker
|
|
387
|
+
.submit_wf(
|
|
388
|
+
wf_id.to_owned(),
|
|
389
|
+
wf_type.to_owned(),
|
|
390
|
+
vec![],
|
|
391
|
+
WorkflowOptions::default(),
|
|
392
|
+
)
|
|
393
|
+
.await
|
|
394
|
+
.unwrap();
|
|
395
|
+
worker.run_until_done().await.unwrap();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
use crate::common::{CoreWfStarter, NAMESPACE, get_integ_server_options};
|
|
1
2
|
use std::time::Duration;
|
|
2
3
|
use temporal_client::WorkflowClientTrait;
|
|
3
4
|
use temporal_sdk::{WfContext, WorkflowResult};
|
|
4
|
-
use temporal_sdk_core_test_utils::{CoreWfStarter, NAMESPACE, get_integ_server_options};
|
|
5
5
|
|
|
6
6
|
pub(crate) async fn eager_wf(_context: WfContext) -> WorkflowResult<()> {
|
|
7
7
|
Ok(().into())
|