@temporalio/core-bridge 1.15.0 → 1.16.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 +172 -70
- package/lib/native.d.ts +1 -1
- package/package.json +2 -2
- 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/.github/workflows/per-pr.yml +6 -6
- package/sdk-core/AGENTS.md +41 -30
- package/sdk-core/Cargo.toml +3 -0
- package/sdk-core/README.md +15 -9
- package/sdk-core/crates/client/Cargo.toml +4 -0
- package/sdk-core/crates/client/README.md +139 -0
- package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
- package/sdk-core/crates/client/src/callback_based.rs +7 -0
- package/sdk-core/crates/client/src/errors.rs +294 -0
- package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +280 -159
- package/sdk-core/crates/client/src/lib.rs +920 -1326
- package/sdk-core/crates/client/src/metrics.rs +24 -33
- package/sdk-core/crates/client/src/options_structs.rs +457 -0
- package/sdk-core/crates/client/src/replaceable.rs +5 -4
- package/sdk-core/crates/client/src/request_extensions.rs +8 -9
- package/sdk-core/crates/client/src/retry.rs +99 -54
- package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +1 -1
- package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
- package/sdk-core/crates/common/Cargo.toml +61 -2
- package/sdk-core/crates/common/build.rs +742 -12
- package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
- package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
- package/sdk-core/crates/common/protos/api_upstream/buf.yaml +0 -3
- package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
- package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +1166 -770
- package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +1243 -750
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +2 -2
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +4 -3
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +16 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -6
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +88 -33
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +4 -2
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +4 -0
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +5 -5
- package/sdk-core/crates/common/src/activity_definition.rs +20 -0
- package/sdk-core/crates/common/src/data_converters.rs +770 -0
- package/sdk-core/crates/common/src/envconfig.rs +5 -0
- package/sdk-core/crates/common/src/lib.rs +15 -211
- package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
- package/sdk-core/crates/common/src/priority.rs +110 -0
- package/sdk-core/crates/common/src/protos/canned_histories.rs +3 -0
- package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
- package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
- package/sdk-core/crates/common/src/protos/mod.rs +122 -27
- package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
- package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +5 -7
- package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
- package/sdk-core/crates/common/src/telemetry/metrics.rs +268 -223
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
- package/sdk-core/crates/common/src/telemetry.rs +264 -4
- package/sdk-core/crates/common/src/worker.rs +68 -603
- package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
- package/sdk-core/crates/macros/Cargo.toml +5 -1
- package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
- package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
- package/sdk-core/crates/macros/src/lib.rs +138 -512
- package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
- package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
- package/sdk-core/crates/sdk/Cargo.toml +19 -6
- package/sdk-core/crates/sdk/README.md +415 -0
- package/sdk-core/crates/sdk/src/activities.rs +417 -0
- package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
- package/sdk-core/crates/sdk/src/lib.rs +757 -442
- package/sdk-core/crates/sdk/src/workflow_context/options.rs +45 -35
- package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
- package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
- package/sdk-core/crates/sdk/src/workflows.rs +711 -0
- package/sdk-core/crates/sdk-core/Cargo.toml +57 -64
- package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +41 -35
- package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
- package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
- package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
- package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +13 -15
- package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
- package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
- package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
- package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +493 -26
- package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +4 -8
- package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +7 -7
- package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
- package/sdk-core/crates/sdk-core/src/lib.rs +41 -111
- package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
- package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +118 -19
- package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
- package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
- package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +179 -196
- package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -280
- package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +6 -9
- package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
- package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
- package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
- package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +9 -5
- package/sdk-core/crates/sdk-core/src/worker/client.rs +103 -81
- package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +7 -11
- package/sdk-core/crates/sdk-core/src/worker/mod.rs +1124 -229
- package/sdk-core/crates/sdk-core/src/worker/nexus.rs +145 -23
- package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
- package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
- package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +13 -13
- package/sdk-core/crates/sdk-core/src/worker/tuner.rs +28 -8
- package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +19 -4
- package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +14 -18
- package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +4 -6
- package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
- package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
- package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
- package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
- package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
- package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
- package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
- package/sdk-core/crates/sdk-core/tests/common/mod.rs +241 -196
- package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
- package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +3 -5
- package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -64
- package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +298 -252
- package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
- package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +16 -12
- package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +48 -40
- package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +327 -255
- package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
- package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +147 -126
- package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
- package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -453
- package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +360 -231
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +248 -185
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -43
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +428 -315
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -56
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -28
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -243
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +101 -42
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -147
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -28
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1036
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -41
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +397 -238
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +414 -189
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +154 -137
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -105
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -38
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -40
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -54
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +363 -226
- package/sdk-core/crates/sdk-core/tests/main.rs +17 -15
- package/sdk-core/crates/sdk-core/tests/manual_tests.rs +207 -152
- package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +65 -34
- package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
- package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +7 -1
- package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +14 -14
- package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +83 -74
- package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +9 -14
- package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +1 -2
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +13 -13
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +6 -6
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +3 -4
- package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +62 -75
- package/sdk-core/rustfmt.toml +2 -1
- package/src/client.rs +205 -318
- package/src/metrics.rs +22 -30
- package/src/runtime.rs +4 -5
- package/src/worker.rs +16 -19
- package/ts/native.ts +1 -1
- package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
- package/sdk-core/crates/common/src/errors.rs +0 -85
- package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
- package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
- package/sdk-core/crates/sdk/src/app_data.rs +0 -37
- package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
use crate::common::{
|
|
1
|
+
use crate::common::{
|
|
2
|
+
ActivationAssertionsInterceptor, CoreWfStarter, WorkflowHandleExt, build_fake_sdk,
|
|
3
|
+
};
|
|
2
4
|
use std::{
|
|
3
5
|
collections::{HashSet, VecDeque, hash_map::RandomState},
|
|
4
6
|
sync::{
|
|
@@ -7,59 +9,74 @@ use std::{
|
|
|
7
9
|
},
|
|
8
10
|
time::Duration,
|
|
9
11
|
};
|
|
10
|
-
use temporalio_client::
|
|
11
|
-
use temporalio_common::
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
command::v1::{
|
|
21
|
-
RecordMarkerCommandAttributes, ScheduleActivityTaskCommandAttributes,
|
|
22
|
-
UpsertWorkflowSearchAttributesCommandAttributes, command::Attributes,
|
|
12
|
+
use temporalio_client::{WorkflowSignalOptions, WorkflowStartOptions};
|
|
13
|
+
use temporalio_common::{
|
|
14
|
+
data_converters::RawValue,
|
|
15
|
+
protos::{
|
|
16
|
+
DEFAULT_WORKFLOW_TYPE, TestHistoryBuilder, VERSION_SEARCH_ATTR_KEY,
|
|
17
|
+
constants::PATCH_MARKER_NAME,
|
|
18
|
+
coresdk::{
|
|
19
|
+
AsJsonPayloadExt, FromJsonPayloadExt,
|
|
20
|
+
common::decode_change_marker_details,
|
|
21
|
+
workflow_activation::{NotifyHasPatch, WorkflowActivationJob, workflow_activation_job},
|
|
23
22
|
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
temporal::api::{
|
|
24
|
+
command::v1::{
|
|
25
|
+
RecordMarkerCommandAttributes, ScheduleActivityTaskCommandAttributes,
|
|
26
|
+
UpsertWorkflowSearchAttributesCommandAttributes, command::Attributes,
|
|
27
|
+
},
|
|
28
|
+
common::v1::ActivityType,
|
|
29
|
+
enums::v1::{CommandType, EventType},
|
|
30
|
+
history::v1::{
|
|
31
|
+
ActivityTaskCompletedEventAttributes, ActivityTaskScheduledEventAttributes,
|
|
32
|
+
ActivityTaskStartedEventAttributes, TimerFiredEventAttributes,
|
|
33
|
+
history_event::Attributes as EventAttributes,
|
|
34
|
+
},
|
|
29
35
|
},
|
|
30
36
|
},
|
|
31
37
|
};
|
|
32
38
|
|
|
33
39
|
use temporalio_common::worker::WorkerTaskTypes;
|
|
34
|
-
use
|
|
40
|
+
use temporalio_macros::{activities, workflow, workflow_methods};
|
|
41
|
+
use temporalio_sdk::{
|
|
42
|
+
ActivityOptions, SyncWorkflowContext, WorkflowContext, WorkflowResult,
|
|
43
|
+
activities::{ActivityContext, ActivityError},
|
|
44
|
+
};
|
|
35
45
|
use temporalio_sdk_core::test_help::{CoreInternalFlags, MockPollCfg, ResponseType};
|
|
36
46
|
use tokio::{join, sync::Notify};
|
|
37
|
-
use tokio_stream::StreamExt;
|
|
38
47
|
|
|
39
48
|
const MY_PATCH_ID: &str = "integ_test_change_name";
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
ctx.
|
|
50
|
-
|
|
50
|
+
#[workflow]
|
|
51
|
+
#[derive(Default)]
|
|
52
|
+
pub(crate) struct ChangesWf;
|
|
53
|
+
|
|
54
|
+
#[workflow_methods]
|
|
55
|
+
impl ChangesWf {
|
|
56
|
+
#[run(name = "writes_change_markers")]
|
|
57
|
+
pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
58
|
+
if ctx.patched(MY_PATCH_ID) {
|
|
59
|
+
ctx.timer(Duration::from_millis(100)).await;
|
|
60
|
+
} else {
|
|
61
|
+
ctx.timer(Duration::from_millis(200)).await;
|
|
62
|
+
}
|
|
51
63
|
ctx.timer(Duration::from_millis(200)).await;
|
|
64
|
+
if ctx.patched(MY_PATCH_ID) {
|
|
65
|
+
ctx.timer(Duration::from_millis(100)).await;
|
|
66
|
+
} else {
|
|
67
|
+
ctx.timer(Duration::from_millis(200)).await;
|
|
68
|
+
}
|
|
69
|
+
Ok(())
|
|
52
70
|
}
|
|
53
|
-
Ok(().into())
|
|
54
71
|
}
|
|
55
72
|
|
|
56
73
|
#[tokio::test]
|
|
57
74
|
async fn writes_change_markers() {
|
|
58
75
|
let wf_name = "writes_change_markers";
|
|
59
76
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
60
|
-
starter.
|
|
77
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
61
78
|
let mut worker = starter.worker().await;
|
|
62
|
-
worker.
|
|
79
|
+
worker.register_workflow::<ChangesWf>();
|
|
63
80
|
|
|
64
81
|
starter.start_with_worker(wf_name, &mut worker).await;
|
|
65
82
|
worker.run_until_done().await.unwrap();
|
|
@@ -67,57 +84,77 @@ async fn writes_change_markers() {
|
|
|
67
84
|
|
|
68
85
|
/// This one simulates a run as if the worker had the "old" code, then it fails at the end as
|
|
69
86
|
/// a cheapo way of being re-run, at which point it runs with change checks and the "new" code.
|
|
70
|
-
|
|
87
|
+
#[workflow]
|
|
88
|
+
pub(crate) struct NoChangeThenChangeWf {
|
|
89
|
+
did_die: Arc<AtomicBool>,
|
|
90
|
+
}
|
|
71
91
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
#[workflow_methods(factory_only)]
|
|
93
|
+
impl NoChangeThenChangeWf {
|
|
94
|
+
#[run(name = "can_add_change_markers")]
|
|
95
|
+
pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
96
|
+
if ctx.state(|wf| wf.did_die.load(Ordering::Acquire)) {
|
|
97
|
+
assert!(!ctx.patched(MY_PATCH_ID));
|
|
98
|
+
}
|
|
99
|
+
ctx.timer(Duration::from_millis(200)).await;
|
|
100
|
+
ctx.timer(Duration::from_millis(200)).await;
|
|
101
|
+
if ctx.state(|wf| wf.did_die.load(Ordering::Acquire)) {
|
|
102
|
+
assert!(!ctx.patched(MY_PATCH_ID));
|
|
103
|
+
}
|
|
104
|
+
ctx.timer(Duration::from_millis(200)).await;
|
|
82
105
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
106
|
+
if !ctx.state(|wf| wf.did_die.load(Ordering::Acquire)) {
|
|
107
|
+
ctx.state(|wf| wf.did_die.store(true, Ordering::Release));
|
|
108
|
+
ctx.force_task_fail(anyhow::anyhow!("i'm ded"));
|
|
109
|
+
}
|
|
110
|
+
Ok(())
|
|
86
111
|
}
|
|
87
|
-
Ok(().into())
|
|
88
112
|
}
|
|
89
113
|
|
|
90
114
|
#[tokio::test]
|
|
91
115
|
async fn can_add_change_markers() {
|
|
92
116
|
let wf_name = "can_add_change_markers";
|
|
93
117
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
94
|
-
starter.
|
|
118
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
95
119
|
let mut worker = starter.worker().await;
|
|
96
|
-
|
|
120
|
+
let did_die = Arc::new(AtomicBool::new(false));
|
|
121
|
+
worker.register_workflow_with_factory(move || NoChangeThenChangeWf {
|
|
122
|
+
did_die: did_die.clone(),
|
|
123
|
+
});
|
|
97
124
|
|
|
98
125
|
starter.start_with_worker(wf_name, &mut worker).await;
|
|
99
126
|
worker.run_until_done().await.unwrap();
|
|
100
127
|
}
|
|
101
128
|
|
|
102
|
-
|
|
129
|
+
#[workflow]
|
|
130
|
+
pub(crate) struct ReplayWithChangeMarkerWf {
|
|
131
|
+
did_die: Arc<AtomicBool>,
|
|
132
|
+
}
|
|
103
133
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
ctx.
|
|
134
|
+
#[workflow_methods(factory_only)]
|
|
135
|
+
impl ReplayWithChangeMarkerWf {
|
|
136
|
+
#[run(name = "replaying_with_patch_marker")]
|
|
137
|
+
pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
138
|
+
assert!(ctx.patched(MY_PATCH_ID));
|
|
139
|
+
ctx.timer(Duration::from_millis(200)).await;
|
|
140
|
+
if !ctx.state(|wf| wf.did_die.load(Ordering::Acquire)) {
|
|
141
|
+
ctx.state(|wf| wf.did_die.store(true, Ordering::Release));
|
|
142
|
+
ctx.force_task_fail(anyhow::anyhow!("i'm ded"));
|
|
143
|
+
}
|
|
144
|
+
Ok(())
|
|
110
145
|
}
|
|
111
|
-
Ok(().into())
|
|
112
146
|
}
|
|
113
147
|
|
|
114
148
|
#[tokio::test]
|
|
115
149
|
async fn replaying_with_patch_marker() {
|
|
116
150
|
let wf_name = "replaying_with_patch_marker";
|
|
117
151
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
118
|
-
starter.
|
|
152
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
119
153
|
let mut worker = starter.worker().await;
|
|
120
|
-
|
|
154
|
+
let did_die = Arc::new(AtomicBool::new(false));
|
|
155
|
+
worker.register_workflow_with_factory(move || ReplayWithChangeMarkerWf {
|
|
156
|
+
did_die: did_die.clone(),
|
|
157
|
+
});
|
|
121
158
|
|
|
122
159
|
starter.start_with_worker(wf_name, &mut worker).await;
|
|
123
160
|
worker.run_until_done().await.unwrap();
|
|
@@ -126,98 +163,148 @@ async fn replaying_with_patch_marker() {
|
|
|
126
163
|
/// Test that the internal patching mechanism works on the second workflow task when replaying.
|
|
127
164
|
/// Used as regression test for a bug that detected that we did not look ahead far enough to find
|
|
128
165
|
/// the next workflow task completion, which the flags are attached to.
|
|
166
|
+
#[workflow]
|
|
167
|
+
struct TimerPatchedTimerWf {
|
|
168
|
+
fail_once: Arc<AtomicBool>,
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
#[workflow_methods(factory_only)]
|
|
172
|
+
impl TimerPatchedTimerWf {
|
|
173
|
+
#[run(name = "timer_patched_timer")]
|
|
174
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
175
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
176
|
+
if ctx.state(|wf| wf.fail_once.load(Ordering::Acquire)) {
|
|
177
|
+
ctx.state(|wf| wf.fail_once.store(false, Ordering::Release));
|
|
178
|
+
panic!("Enchi is hungry!");
|
|
179
|
+
}
|
|
180
|
+
assert!(ctx.patched(MY_PATCH_ID));
|
|
181
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
182
|
+
Ok(())
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
129
186
|
#[tokio::test]
|
|
130
187
|
async fn patched_on_second_workflow_task_is_deterministic() {
|
|
131
188
|
let wf_name = "timer_patched_timer";
|
|
132
189
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
133
190
|
// Disable caching to force replay from beginning
|
|
134
|
-
starter.
|
|
135
|
-
starter.
|
|
191
|
+
starter.sdk_config.max_cached_workflows = 0_usize;
|
|
192
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
136
193
|
let mut worker = starter.worker().await;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
ctx.timer(Duration::from_millis(1)).await;
|
|
141
|
-
if FAIL_ONCE.load(Ordering::Acquire) {
|
|
142
|
-
FAIL_ONCE.store(false, Ordering::Release);
|
|
143
|
-
panic!("Enchi is hungry!");
|
|
144
|
-
}
|
|
145
|
-
assert!(ctx.patched(MY_PATCH_ID));
|
|
146
|
-
ctx.timer(Duration::from_millis(1)).await;
|
|
147
|
-
Ok(().into())
|
|
194
|
+
let fail_once = Arc::new(AtomicBool::new(true));
|
|
195
|
+
worker.register_workflow_with_factory(move || TimerPatchedTimerWf {
|
|
196
|
+
fail_once: fail_once.clone(),
|
|
148
197
|
});
|
|
149
198
|
|
|
150
199
|
starter.start_with_worker(wf_name, &mut worker).await;
|
|
151
200
|
worker.run_until_done().await.unwrap();
|
|
152
201
|
}
|
|
153
202
|
|
|
203
|
+
#[workflow]
|
|
204
|
+
struct RemoveDeprecatedPatchNearOtherPatchWf {
|
|
205
|
+
did_die: Arc<AtomicBool>,
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
#[workflow_methods(factory_only)]
|
|
209
|
+
impl RemoveDeprecatedPatchNearOtherPatchWf {
|
|
210
|
+
#[run(name = "can_add_change_markers")]
|
|
211
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
212
|
+
ctx.timer(Duration::from_millis(200)).await;
|
|
213
|
+
if !ctx.state(|wf| wf.did_die.load(Ordering::Acquire)) {
|
|
214
|
+
assert!(ctx.deprecate_patch("getting-deprecated"));
|
|
215
|
+
assert!(ctx.patched("staying"));
|
|
216
|
+
} else {
|
|
217
|
+
assert!(ctx.patched("staying"));
|
|
218
|
+
}
|
|
219
|
+
ctx.timer(Duration::from_millis(200)).await;
|
|
220
|
+
|
|
221
|
+
if !ctx.state(|wf| wf.did_die.load(Ordering::Acquire)) {
|
|
222
|
+
ctx.state(|wf| wf.did_die.store(true, Ordering::Release));
|
|
223
|
+
ctx.force_task_fail(anyhow::anyhow!("i'm ded"));
|
|
224
|
+
}
|
|
225
|
+
Ok(())
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
154
229
|
#[tokio::test]
|
|
155
230
|
async fn can_remove_deprecated_patch_near_other_patch() {
|
|
156
231
|
let wf_name = "can_add_change_markers";
|
|
157
232
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
158
|
-
starter.
|
|
233
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
159
234
|
let mut worker = starter.worker().await;
|
|
160
235
|
let did_die = Arc::new(AtomicBool::new(false));
|
|
161
|
-
worker.
|
|
162
|
-
|
|
163
|
-
async move {
|
|
164
|
-
ctx.timer(Duration::from_millis(200)).await;
|
|
165
|
-
if !did_die.load(Ordering::Acquire) {
|
|
166
|
-
assert!(ctx.deprecate_patch("getting-deprecated"));
|
|
167
|
-
assert!(ctx.patched("staying"));
|
|
168
|
-
} else {
|
|
169
|
-
assert!(ctx.patched("staying"));
|
|
170
|
-
}
|
|
171
|
-
ctx.timer(Duration::from_millis(200)).await;
|
|
172
|
-
|
|
173
|
-
if !did_die.load(Ordering::Acquire) {
|
|
174
|
-
did_die.store(true, Ordering::Release);
|
|
175
|
-
ctx.force_task_fail(anyhow::anyhow!("i'm ded"));
|
|
176
|
-
}
|
|
177
|
-
Ok(().into())
|
|
178
|
-
}
|
|
236
|
+
worker.register_workflow_with_factory(move || RemoveDeprecatedPatchNearOtherPatchWf {
|
|
237
|
+
did_die: did_die.clone(),
|
|
179
238
|
});
|
|
180
239
|
|
|
181
240
|
starter.start_with_worker(wf_name, &mut worker).await;
|
|
182
241
|
worker.run_until_done().await.unwrap();
|
|
183
242
|
}
|
|
184
243
|
|
|
244
|
+
#[workflow]
|
|
245
|
+
struct DeprecatedPatchRemovalWf {
|
|
246
|
+
did_die: Arc<AtomicBool>,
|
|
247
|
+
notify: Arc<Notify>,
|
|
248
|
+
signal_received: bool,
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
#[workflow_methods(factory_only)]
|
|
252
|
+
impl DeprecatedPatchRemovalWf {
|
|
253
|
+
#[run(name = "deprecated_patch_removal")]
|
|
254
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
255
|
+
if !ctx.state(|wf| wf.did_die.load(Ordering::Acquire)) {
|
|
256
|
+
assert!(ctx.deprecate_patch("getting-deprecated"));
|
|
257
|
+
}
|
|
258
|
+
ctx.state(|wf| wf.notify.notify_one());
|
|
259
|
+
ctx.wait_condition(|s| s.signal_received).await;
|
|
260
|
+
|
|
261
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
262
|
+
|
|
263
|
+
if !ctx.state(|wf| wf.did_die.load(Ordering::Acquire)) {
|
|
264
|
+
ctx.state(|wf| wf.did_die.store(true, Ordering::Release));
|
|
265
|
+
ctx.force_task_fail(anyhow::anyhow!("i'm ded"));
|
|
266
|
+
}
|
|
267
|
+
Ok(())
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
#[signal]
|
|
271
|
+
fn handle_sig(&mut self, _ctx: &mut SyncWorkflowContext<Self>) {
|
|
272
|
+
self.signal_received = true;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
185
276
|
#[tokio::test]
|
|
186
277
|
async fn deprecated_patch_removal() {
|
|
187
278
|
let wf_name = "deprecated_patch_removal";
|
|
188
279
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
189
|
-
starter.
|
|
280
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
190
281
|
let mut worker = starter.worker().await;
|
|
191
|
-
let client = starter.get_client().await;
|
|
192
282
|
let wf_id = starter.get_task_queue().to_string();
|
|
193
283
|
let did_die = Arc::new(AtomicBool::new(false));
|
|
194
284
|
let send_sig = Arc::new(Notify::new());
|
|
195
|
-
let
|
|
196
|
-
worker.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if !did_die.load(Ordering::Acquire) {
|
|
201
|
-
assert!(ctx.deprecate_patch("getting-deprecated"));
|
|
202
|
-
}
|
|
203
|
-
send_sig_c.notify_one();
|
|
204
|
-
ctx.make_signal_channel("sig").next().await;
|
|
205
|
-
|
|
206
|
-
ctx.timer(Duration::from_millis(1)).await;
|
|
207
|
-
|
|
208
|
-
if !did_die.load(Ordering::Acquire) {
|
|
209
|
-
did_die.store(true, Ordering::Release);
|
|
210
|
-
ctx.force_task_fail(anyhow::anyhow!("i'm ded"));
|
|
211
|
-
}
|
|
212
|
-
Ok(().into())
|
|
213
|
-
}
|
|
285
|
+
let send_sig_clone = send_sig.clone();
|
|
286
|
+
worker.register_workflow_with_factory(move || DeprecatedPatchRemovalWf {
|
|
287
|
+
did_die: did_die.clone(),
|
|
288
|
+
notify: send_sig_clone.clone(),
|
|
289
|
+
signal_received: false,
|
|
214
290
|
});
|
|
215
291
|
|
|
216
|
-
|
|
292
|
+
let handle = worker
|
|
293
|
+
.submit_workflow(
|
|
294
|
+
DeprecatedPatchRemovalWf::run,
|
|
295
|
+
(),
|
|
296
|
+
WorkflowStartOptions::new(wf_id.clone(), wf_id).build(),
|
|
297
|
+
)
|
|
298
|
+
.await
|
|
299
|
+
.unwrap();
|
|
217
300
|
let sig_fut = async {
|
|
218
301
|
send_sig.notified().await;
|
|
219
|
-
|
|
220
|
-
.
|
|
302
|
+
handle
|
|
303
|
+
.signal(
|
|
304
|
+
DeprecatedPatchRemovalWf::handle_sig,
|
|
305
|
+
(),
|
|
306
|
+
WorkflowSignalOptions::default(),
|
|
307
|
+
)
|
|
221
308
|
.await
|
|
222
309
|
.unwrap()
|
|
223
310
|
};
|
|
@@ -312,47 +399,81 @@ fn patch_marker_single_activity(
|
|
|
312
399
|
t
|
|
313
400
|
}
|
|
314
401
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
402
|
+
struct FakeAct;
|
|
403
|
+
#[activities]
|
|
404
|
+
impl FakeAct {
|
|
405
|
+
#[activity(name = "")]
|
|
406
|
+
fn nameless(_: ActivityContext) -> Result<RawValue, ActivityError> {
|
|
407
|
+
unimplemented!()
|
|
408
|
+
}
|
|
321
409
|
}
|
|
322
410
|
|
|
323
|
-
async fn
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
411
|
+
async fn v1(ctx: &mut WorkflowContext<PatchWf>) {
|
|
412
|
+
let _ = ctx
|
|
413
|
+
.start_activity(
|
|
414
|
+
FakeAct::nameless,
|
|
415
|
+
(),
|
|
416
|
+
ActivityOptions {
|
|
417
|
+
activity_id: Some("no_change".to_owned()),
|
|
418
|
+
..Default::default()
|
|
419
|
+
},
|
|
420
|
+
)
|
|
329
421
|
.await;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
async fn v2(ctx: &mut WorkflowContext<PatchWf>) -> bool {
|
|
425
|
+
if ctx.patched(MY_PATCH_ID) {
|
|
426
|
+
let _ = ctx
|
|
427
|
+
.start_activity(
|
|
428
|
+
FakeAct::nameless,
|
|
429
|
+
(),
|
|
430
|
+
ActivityOptions {
|
|
431
|
+
activity_id: Some("had_change".to_owned()),
|
|
432
|
+
..Default::default()
|
|
433
|
+
},
|
|
434
|
+
)
|
|
435
|
+
.await;
|
|
330
436
|
true
|
|
331
437
|
} else {
|
|
332
|
-
ctx
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
438
|
+
let _ = ctx
|
|
439
|
+
.start_activity(
|
|
440
|
+
FakeAct::nameless,
|
|
441
|
+
(),
|
|
442
|
+
ActivityOptions {
|
|
443
|
+
activity_id: Some("no_change".to_owned()),
|
|
444
|
+
..Default::default()
|
|
445
|
+
},
|
|
446
|
+
)
|
|
447
|
+
.await;
|
|
337
448
|
false
|
|
338
449
|
}
|
|
339
450
|
}
|
|
340
451
|
|
|
341
|
-
async fn v3(ctx: &mut
|
|
452
|
+
async fn v3(ctx: &mut WorkflowContext<PatchWf>) {
|
|
342
453
|
ctx.deprecate_patch(MY_PATCH_ID);
|
|
343
|
-
ctx
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
454
|
+
let _ = ctx
|
|
455
|
+
.start_activity(
|
|
456
|
+
FakeAct::nameless,
|
|
457
|
+
(),
|
|
458
|
+
ActivityOptions {
|
|
459
|
+
activity_id: Some("had_change".to_owned()),
|
|
460
|
+
..Default::default()
|
|
461
|
+
},
|
|
462
|
+
)
|
|
463
|
+
.await;
|
|
348
464
|
}
|
|
349
465
|
|
|
350
|
-
async fn v4(ctx: &mut
|
|
351
|
-
ctx
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
466
|
+
async fn v4(ctx: &mut WorkflowContext<PatchWf>) {
|
|
467
|
+
let _ = ctx
|
|
468
|
+
.start_activity(
|
|
469
|
+
FakeAct::nameless,
|
|
470
|
+
(),
|
|
471
|
+
ActivityOptions {
|
|
472
|
+
activity_id: Some("had_change".to_owned()),
|
|
473
|
+
..Default::default()
|
|
474
|
+
},
|
|
475
|
+
)
|
|
476
|
+
.await;
|
|
356
477
|
}
|
|
357
478
|
|
|
358
479
|
fn patch_setup(replaying: bool, marker_type: MarkerType, workflow_version: usize) -> MockPollCfg {
|
|
@@ -364,27 +485,32 @@ fn patch_setup(replaying: bool, marker_type: MarkerType, workflow_version: usize
|
|
|
364
485
|
}
|
|
365
486
|
}
|
|
366
487
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
488
|
+
#[workflow]
|
|
489
|
+
struct PatchWf {
|
|
490
|
+
version: usize,
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
#[workflow_methods(factory_only)]
|
|
494
|
+
impl PatchWf {
|
|
495
|
+
#[run(name = DEFAULT_WORKFLOW_TYPE)]
|
|
496
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
497
|
+
match ctx.state(|wf| wf.version) {
|
|
498
|
+
1 => {
|
|
499
|
+
v1(ctx).await;
|
|
500
|
+
}
|
|
501
|
+
2 => {
|
|
502
|
+
v2(ctx).await;
|
|
503
|
+
}
|
|
504
|
+
3 => {
|
|
505
|
+
v3(ctx).await;
|
|
506
|
+
}
|
|
507
|
+
4 => {
|
|
508
|
+
v4(ctx).await;
|
|
384
509
|
}
|
|
385
|
-
|
|
510
|
+
_ => panic!("Invalid workflow version for test setup"),
|
|
386
511
|
}
|
|
387
|
-
|
|
512
|
+
Ok(())
|
|
513
|
+
}
|
|
388
514
|
}
|
|
389
515
|
|
|
390
516
|
#[rstest]
|
|
@@ -436,7 +562,9 @@ async fn v1_and_v4_changes(
|
|
|
436
562
|
|
|
437
563
|
let mut worker = build_fake_sdk(mock_cfg);
|
|
438
564
|
worker.set_worker_interceptor(aai);
|
|
439
|
-
worker.
|
|
565
|
+
worker.register_workflow_with_factory(move || PatchWf {
|
|
566
|
+
version: wf_version,
|
|
567
|
+
});
|
|
440
568
|
worker.run().await.unwrap();
|
|
441
569
|
}
|
|
442
570
|
|
|
@@ -541,10 +669,39 @@ async fn v2_and_v3_changes(
|
|
|
541
669
|
|
|
542
670
|
let mut worker = build_fake_sdk(mock_cfg);
|
|
543
671
|
worker.set_worker_interceptor(aai);
|
|
544
|
-
worker.
|
|
672
|
+
worker.register_workflow_with_factory(move || PatchWf {
|
|
673
|
+
version: wf_version,
|
|
674
|
+
});
|
|
545
675
|
worker.run().await.unwrap();
|
|
546
676
|
}
|
|
547
677
|
|
|
678
|
+
#[workflow]
|
|
679
|
+
#[derive(Default)]
|
|
680
|
+
struct SameChangeMultipleSpotsWf;
|
|
681
|
+
|
|
682
|
+
#[workflow_methods]
|
|
683
|
+
impl SameChangeMultipleSpotsWf {
|
|
684
|
+
#[run(name = DEFAULT_WORKFLOW_TYPE)]
|
|
685
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
686
|
+
if ctx.patched(MY_PATCH_ID) {
|
|
687
|
+
let _ = ctx
|
|
688
|
+
.start_activity(FakeAct::nameless, (), ActivityOptions::default())
|
|
689
|
+
.await;
|
|
690
|
+
} else {
|
|
691
|
+
ctx.timer(ONE_SECOND).await;
|
|
692
|
+
}
|
|
693
|
+
ctx.timer(ONE_SECOND).await;
|
|
694
|
+
if ctx.patched(MY_PATCH_ID) {
|
|
695
|
+
let _ = ctx
|
|
696
|
+
.start_activity(FakeAct::nameless, (), ActivityOptions::default())
|
|
697
|
+
.await;
|
|
698
|
+
} else {
|
|
699
|
+
ctx.timer(ONE_SECOND).await;
|
|
700
|
+
}
|
|
701
|
+
Ok(())
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
548
705
|
#[rstest]
|
|
549
706
|
#[case::has_change_replay(true, true)]
|
|
550
707
|
#[case::no_change_replay(false, true)]
|
|
@@ -634,26 +791,30 @@ async fn same_change_multiple_spots(#[case] have_marker_in_hist: bool, #[case] r
|
|
|
634
791
|
MockPollCfg::from_hist_builder(t)
|
|
635
792
|
};
|
|
636
793
|
|
|
637
|
-
// Errors would appear as nondeterminism problems, so just run it.
|
|
638
794
|
let mut worker = build_fake_sdk(mock_cfg);
|
|
639
|
-
worker.
|
|
640
|
-
if ctx.patched(MY_PATCH_ID) {
|
|
641
|
-
ctx.activity(ActivityOptions::default()).await;
|
|
642
|
-
} else {
|
|
643
|
-
ctx.timer(ONE_SECOND).await;
|
|
644
|
-
}
|
|
645
|
-
ctx.timer(ONE_SECOND).await;
|
|
646
|
-
if ctx.patched(MY_PATCH_ID) {
|
|
647
|
-
ctx.activity(ActivityOptions::default()).await;
|
|
648
|
-
} else {
|
|
649
|
-
ctx.timer(ONE_SECOND).await;
|
|
650
|
-
}
|
|
651
|
-
Ok(().into())
|
|
652
|
-
});
|
|
795
|
+
worker.register_workflow::<SameChangeMultipleSpotsWf>();
|
|
653
796
|
worker.run().await.unwrap();
|
|
654
797
|
}
|
|
655
798
|
|
|
656
799
|
const SIZE_OVERFLOW_PATCH_AMOUNT: usize = 180;
|
|
800
|
+
|
|
801
|
+
#[workflow]
|
|
802
|
+
struct ManyPatchesWf {
|
|
803
|
+
num_patches: usize,
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
#[workflow_methods(factory_only)]
|
|
807
|
+
impl ManyPatchesWf {
|
|
808
|
+
#[run(name = DEFAULT_WORKFLOW_TYPE)]
|
|
809
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
810
|
+
for i in 1..=ctx.state(|wf| wf.num_patches) {
|
|
811
|
+
let _dontcare = ctx.patched(&format!("patch-{i}"));
|
|
812
|
+
ctx.timer(ONE_SECOND).await;
|
|
813
|
+
}
|
|
814
|
+
Ok(())
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
657
818
|
#[rstest]
|
|
658
819
|
#[case::happy_path(50)]
|
|
659
820
|
// We start exceeding the 2k size limit at 180 patches with this format
|
|
@@ -713,12 +874,76 @@ async fn many_patches_combine_in_search_attrib_update(#[case] num_patches: usize
|
|
|
713
874
|
});
|
|
714
875
|
|
|
715
876
|
let mut worker = build_fake_sdk(mock_cfg);
|
|
716
|
-
worker.
|
|
717
|
-
for i in 1..=num_patches {
|
|
718
|
-
let _dontcare = ctx.patched(&format!("patch-{i}"));
|
|
719
|
-
ctx.timer(ONE_SECOND).await;
|
|
720
|
-
}
|
|
721
|
-
Ok(().into())
|
|
722
|
-
});
|
|
877
|
+
worker.register_workflow_with_factory(move || ManyPatchesWf { num_patches });
|
|
723
878
|
worker.run().await.unwrap();
|
|
724
879
|
}
|
|
880
|
+
|
|
881
|
+
const MANY_PATCHES_IN_ONE_WFT_COUNT: usize = 200;
|
|
882
|
+
|
|
883
|
+
#[workflow]
|
|
884
|
+
#[derive(Default)]
|
|
885
|
+
struct ManyPatchesInOneWftWf;
|
|
886
|
+
|
|
887
|
+
#[workflow_methods]
|
|
888
|
+
impl ManyPatchesInOneWftWf {
|
|
889
|
+
#[run(name = DEFAULT_WORKFLOW_TYPE)]
|
|
890
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
891
|
+
for i in 1..=MANY_PATCHES_IN_ONE_WFT_COUNT {
|
|
892
|
+
let _ = ctx.patched(&format!("patch-{i}"));
|
|
893
|
+
}
|
|
894
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
895
|
+
Ok(())
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
// The main difference with many_patches_combine_in_search_attrib_update are that
|
|
900
|
+
// this one creates multiple patches in a single WFT, rather than spread them out
|
|
901
|
+
// over multiple WFTs. See https://github.com/temporalio/sdk-core/issues/1223.
|
|
902
|
+
#[tokio::test]
|
|
903
|
+
async fn patch_marker_size_overflow_replay_is_deterministic() {
|
|
904
|
+
let wf_name = "patch_marker_size_overflow_replay_is_deterministic";
|
|
905
|
+
let mut starter = CoreWfStarter::new(wf_name);
|
|
906
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
907
|
+
let mut worker = starter.worker().await;
|
|
908
|
+
worker.register_workflow::<ManyPatchesInOneWftWf>();
|
|
909
|
+
|
|
910
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
911
|
+
let handle = worker
|
|
912
|
+
.submit_workflow(
|
|
913
|
+
ManyPatchesInOneWftWf::run,
|
|
914
|
+
(),
|
|
915
|
+
WorkflowStartOptions::new(task_queue, wf_name.to_owned()).build(),
|
|
916
|
+
)
|
|
917
|
+
.await
|
|
918
|
+
.unwrap();
|
|
919
|
+
worker.run_until_done().await.unwrap();
|
|
920
|
+
|
|
921
|
+
// Confirm that the original execution did in fact hit the size limit: the last upsert SA
|
|
922
|
+
// event in history must contain fewer than the total number of patches issued by the workflow.
|
|
923
|
+
let history = handle.fetch_history(Default::default()).await.unwrap();
|
|
924
|
+
let last_upsert_patches = history
|
|
925
|
+
.events()
|
|
926
|
+
.iter()
|
|
927
|
+
.rev()
|
|
928
|
+
.find_map(|e| match &e.attributes {
|
|
929
|
+
Some(EventAttributes::UpsertWorkflowSearchAttributesEventAttributes(a)) => a
|
|
930
|
+
.search_attributes
|
|
931
|
+
.as_ref()
|
|
932
|
+
.and_then(|sa| sa.indexed_fields.get(VERSION_SEARCH_ATTR_KEY))
|
|
933
|
+
.map(|p| HashSet::<String, RandomState>::from_json_payload(p).unwrap()),
|
|
934
|
+
_ => None,
|
|
935
|
+
})
|
|
936
|
+
.expect("history should contain at least one UpsertWorkflowSearchAttributes event");
|
|
937
|
+
assert!(
|
|
938
|
+
last_upsert_patches.len() < MANY_PATCHES_IN_ONE_WFT_COUNT,
|
|
939
|
+
"expected the last upsert SA event to be missing patches due to size overflow, \
|
|
940
|
+
but it contained all {MANY_PATCHES_IN_ONE_WFT_COUNT} of them",
|
|
941
|
+
);
|
|
942
|
+
|
|
943
|
+
// Replay the workflow from the fetched history. This must succeed: the SDK must produce the
|
|
944
|
+
// same sequence of upsert SA commands during replay as it did during the original execution.
|
|
945
|
+
handle
|
|
946
|
+
.fetch_history_and_replay(worker.inner_mut())
|
|
947
|
+
.await
|
|
948
|
+
.unwrap();
|
|
949
|
+
}
|