temporalio 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +25 -23
- data/bridge/Cargo.lock +168 -59
- data/bridge/Cargo.toml +4 -2
- data/bridge/sdk-core/README.md +19 -6
- data/bridge/sdk-core/client/src/lib.rs +215 -39
- data/bridge/sdk-core/client/src/metrics.rs +17 -8
- data/bridge/sdk-core/client/src/raw.rs +4 -4
- data/bridge/sdk-core/client/src/retry.rs +32 -20
- data/bridge/sdk-core/core/Cargo.toml +22 -9
- data/bridge/sdk-core/core/src/abstractions.rs +203 -14
- data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +76 -41
- data/bridge/sdk-core/core/src/core_tests/determinism.rs +165 -2
- data/bridge/sdk-core/core/src/core_tests/local_activities.rs +204 -83
- data/bridge/sdk-core/core/src/core_tests/queries.rs +3 -4
- data/bridge/sdk-core/core/src/core_tests/workers.rs +1 -3
- data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +397 -54
- data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +106 -12
- data/bridge/sdk-core/core/src/internal_flags.rs +136 -0
- data/bridge/sdk-core/core/src/lib.rs +16 -9
- data/bridge/sdk-core/core/src/telemetry/log_export.rs +1 -1
- data/bridge/sdk-core/core/src/telemetry/metrics.rs +69 -35
- data/bridge/sdk-core/core/src/telemetry/mod.rs +29 -13
- data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +17 -12
- data/bridge/sdk-core/core/src/test_help/mod.rs +62 -12
- data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +112 -156
- data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
- data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +352 -122
- data/bridge/sdk-core/core/src/worker/activities.rs +233 -157
- data/bridge/sdk-core/core/src/worker/client/mocks.rs +22 -2
- data/bridge/sdk-core/core/src/worker/client.rs +18 -2
- data/bridge/sdk-core/core/src/worker/mod.rs +165 -58
- data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
- data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
- data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +856 -277
- data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +100 -43
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +7 -7
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +87 -27
- data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +137 -62
- data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +25 -17
- data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +7 -6
- data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +103 -152
- data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +7 -7
- data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +9 -9
- data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
- data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +14 -7
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +5 -16
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +201 -121
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +11 -14
- data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +30 -15
- data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +1026 -376
- data/bridge/sdk-core/core/src/worker/workflow/mod.rs +460 -384
- data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
- data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
- data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +448 -718
- data/bridge/sdk-core/core-api/Cargo.toml +2 -1
- data/bridge/sdk-core/core-api/src/errors.rs +1 -34
- data/bridge/sdk-core/core-api/src/lib.rs +6 -2
- data/bridge/sdk-core/core-api/src/telemetry.rs +0 -6
- data/bridge/sdk-core/core-api/src/worker.rs +14 -1
- data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +18 -15
- data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +8 -3
- data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +5 -17
- data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +11 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +6 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +5 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +22 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +48 -19
- data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +3 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/{enums/v1/interaction_type.proto → protocol/v1/message.proto} +29 -11
- data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +111 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +59 -28
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +7 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +6 -0
- data/bridge/sdk-core/sdk/Cargo.toml +3 -2
- data/bridge/sdk-core/sdk/src/lib.rs +87 -20
- data/bridge/sdk-core/sdk/src/workflow_future.rs +9 -8
- data/bridge/sdk-core/sdk-core-protos/Cargo.toml +5 -2
- data/bridge/sdk-core/sdk-core-protos/build.rs +36 -1
- data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +100 -87
- data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +5 -1
- data/bridge/sdk-core/sdk-core-protos/src/lib.rs +175 -57
- data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
- data/bridge/sdk-core/test-utils/Cargo.toml +3 -1
- data/bridge/sdk-core/test-utils/src/canned_histories.rs +106 -296
- data/bridge/sdk-core/test-utils/src/histfetch.rs +1 -1
- data/bridge/sdk-core/test-utils/src/lib.rs +82 -23
- data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
- data/bridge/sdk-core/test-utils/src/workflows.rs +29 -0
- data/bridge/sdk-core/tests/fuzzy_workflow.rs +130 -0
- data/bridge/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
- data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
- data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -3
- data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
- data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
- data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
- data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -69
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +72 -191
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +7 -28
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +12 -7
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -4
- data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +10 -11
- data/bridge/sdk-core/tests/main.rs +3 -13
- data/bridge/sdk-core/tests/runner.rs +75 -36
- data/bridge/sdk-core/tests/wf_input_replay.rs +32 -0
- data/bridge/src/connection.rs +41 -25
- data/bridge/src/lib.rs +269 -14
- data/bridge/src/runtime.rs +1 -1
- data/bridge/src/test_server.rs +153 -0
- data/bridge/src/worker.rs +89 -16
- data/lib/gen/temporal/api/command/v1/message_pb.rb +4 -18
- data/lib/gen/temporal/api/common/v1/message_pb.rb +4 -0
- data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +1 -3
- data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +3 -3
- data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +2 -0
- data/lib/gen/temporal/api/enums/v1/update_pb.rb +6 -4
- data/lib/gen/temporal/api/history/v1/message_pb.rb +27 -19
- data/lib/gen/temporal/api/namespace/v1/message_pb.rb +1 -0
- data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +3 -0
- data/lib/gen/temporal/api/protocol/v1/message_pb.rb +30 -0
- data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +23 -0
- data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +49 -0
- data/lib/gen/temporal/api/testservice/v1/service_pb.rb +21 -0
- data/lib/gen/temporal/api/update/v1/message_pb.rb +72 -0
- data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +26 -16
- data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +10 -6
- data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/common/common_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/core_interface_pb.rb +9 -3
- data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +27 -21
- data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +28 -24
- data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +12 -5
- data/lib/temporalio/activity/context.rb +13 -8
- data/lib/temporalio/activity/info.rb +1 -1
- data/lib/temporalio/bridge/connect_options.rb +15 -0
- data/lib/temporalio/bridge/retry_config.rb +24 -0
- data/lib/temporalio/bridge/tls_options.rb +19 -0
- data/lib/temporalio/client/implementation.rb +8 -8
- data/lib/temporalio/connection/retry_config.rb +44 -0
- data/lib/temporalio/connection/service.rb +20 -0
- data/lib/temporalio/connection/test_service.rb +92 -0
- data/lib/temporalio/connection/tls_options.rb +51 -0
- data/lib/temporalio/connection/workflow_service.rb +731 -0
- data/lib/temporalio/connection.rb +55 -720
- data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
- data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
- data/lib/temporalio/interceptor/chain.rb +5 -5
- data/lib/temporalio/interceptor/client.rb +8 -4
- data/lib/temporalio/interceptor.rb +22 -0
- data/lib/temporalio/retry_policy.rb +13 -3
- data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
- data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
- data/lib/temporalio/testing/workflow_environment.rb +112 -0
- data/lib/temporalio/testing.rb +175 -0
- data/lib/temporalio/version.rb +1 -1
- data/lib/temporalio/worker/activity_runner.rb +26 -4
- data/lib/temporalio/worker/activity_worker.rb +44 -18
- data/lib/temporalio/worker/sync_worker.rb +47 -11
- data/lib/temporalio/worker.rb +27 -21
- data/lib/temporalio/workflow/async.rb +46 -0
- data/lib/temporalio/workflow/future.rb +138 -0
- data/lib/temporalio/workflow/info.rb +76 -0
- data/temporalio.gemspec +4 -3
- metadata +67 -17
- data/bridge/sdk-core/Cargo.lock +0 -2606
- data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +0 -87
- data/lib/bridge.so +0 -0
- data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +0 -25
- data/lib/gen/temporal/api/interaction/v1/message_pb.rb +0 -49
- data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
use assert_matches::assert_matches;
|
|
2
2
|
use std::{sync::Arc, time::Duration};
|
|
3
3
|
use temporal_client::{
|
|
4
|
-
ListClosedFilters, ListOpenFilters, Namespace,
|
|
5
|
-
|
|
4
|
+
ListClosedFilters, ListOpenFilters, Namespace, RegisterNamespaceOptions, StartTimeFilter,
|
|
5
|
+
WorkflowClientTrait, WorkflowExecutionFilter,
|
|
6
6
|
};
|
|
7
7
|
use temporal_sdk_core_protos::coresdk::workflow_activation::{
|
|
8
8
|
workflow_activation_job, WorkflowActivationJob,
|
|
9
9
|
};
|
|
10
10
|
use temporal_sdk_core_test_utils::{
|
|
11
|
-
get_integ_server_options, CoreWfStarter, WorkerTestHelpers,
|
|
11
|
+
drain_pollers_and_shutdown, get_integ_server_options, CoreWfStarter, WorkerTestHelpers,
|
|
12
|
+
NAMESPACE,
|
|
12
13
|
};
|
|
14
|
+
use tokio::time::sleep;
|
|
13
15
|
|
|
14
16
|
#[tokio::test]
|
|
15
17
|
async fn client_list_open_closed_workflow_executions() {
|
|
@@ -22,9 +24,7 @@ async fn client_list_open_closed_workflow_executions() {
|
|
|
22
24
|
let latest = earliest + Duration::from_secs(60);
|
|
23
25
|
|
|
24
26
|
// start workflow
|
|
25
|
-
let run_id = starter
|
|
26
|
-
.start_wf_with_id(wf_name.to_owned(), WorkflowOptions::default())
|
|
27
|
-
.await;
|
|
27
|
+
let run_id = starter.start_wf_with_id(wf_name.to_owned()).await;
|
|
28
28
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
29
29
|
assert_matches!(
|
|
30
30
|
task.jobs.as_slice(),
|
|
@@ -52,28 +52,86 @@ async fn client_list_open_closed_workflow_executions() {
|
|
|
52
52
|
|
|
53
53
|
// Complete workflow
|
|
54
54
|
core.complete_execution(&task.run_id).await;
|
|
55
|
+
drain_pollers_and_shutdown(&core).await;
|
|
55
56
|
|
|
56
|
-
// List above CLOSED workflow
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
57
|
+
// List above CLOSED workflow. Visibility doesn't always update immediately so we give this a
|
|
58
|
+
// few tries.
|
|
59
|
+
let mut passed = false;
|
|
60
|
+
for _ in 1..=5 {
|
|
61
|
+
let closed_workflows = client
|
|
62
|
+
.list_closed_workflow_executions(
|
|
63
|
+
1,
|
|
64
|
+
Default::default(),
|
|
65
|
+
Some(StartTimeFilter {
|
|
66
|
+
earliest_time: Some(earliest).and_then(|t| t.try_into().ok()),
|
|
67
|
+
latest_time: Some(latest).and_then(|t| t.try_into().ok()),
|
|
68
|
+
}),
|
|
69
|
+
Some(ListClosedFilters::ExecutionFilter(
|
|
70
|
+
WorkflowExecutionFilter {
|
|
71
|
+
workflow_id: wf_name.clone(),
|
|
72
|
+
run_id: run_id.clone(),
|
|
73
|
+
},
|
|
74
|
+
)),
|
|
75
|
+
)
|
|
76
|
+
.await
|
|
77
|
+
.unwrap();
|
|
78
|
+
if closed_workflows.executions.len() == 1 {
|
|
79
|
+
let workflow = &closed_workflows.executions[0];
|
|
80
|
+
if workflow.execution.as_ref().unwrap().workflow_id == wf_name {
|
|
81
|
+
passed = true;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
sleep(Duration::from_millis(100)).await;
|
|
86
|
+
}
|
|
87
|
+
assert!(passed);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#[tokio::test]
|
|
91
|
+
async fn client_create_namespace() {
|
|
92
|
+
let client = Arc::new(
|
|
93
|
+
get_integ_server_options()
|
|
94
|
+
.connect(NAMESPACE.to_owned(), None, None)
|
|
95
|
+
.await
|
|
96
|
+
.expect("Must connect"),
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
let register_options = RegisterNamespaceOptions::builder()
|
|
100
|
+
.namespace("test-create-namespace")
|
|
101
|
+
.description("it's alive")
|
|
102
|
+
.build()
|
|
103
|
+
.unwrap();
|
|
104
|
+
|
|
105
|
+
client
|
|
106
|
+
.register_namespace(register_options.clone())
|
|
72
107
|
.await
|
|
73
108
|
.unwrap();
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
109
|
+
|
|
110
|
+
//#Hack, not sure how else to wait for a proper response. RegisterNamespace isn't safe to read
|
|
111
|
+
//after write
|
|
112
|
+
let mut attempts = 0;
|
|
113
|
+
let wait_time = Duration::from_secs(1);
|
|
114
|
+
loop {
|
|
115
|
+
attempts += 1;
|
|
116
|
+
let resp = client
|
|
117
|
+
.describe_namespace(Namespace::Name(register_options.namespace.clone()))
|
|
118
|
+
.await;
|
|
119
|
+
|
|
120
|
+
match resp {
|
|
121
|
+
Ok(n) => {
|
|
122
|
+
let namespace_info = n.namespace_info.unwrap();
|
|
123
|
+
assert_eq!(namespace_info.name, register_options.namespace);
|
|
124
|
+
assert_eq!(namespace_info.description, register_options.description);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
_ => {
|
|
128
|
+
if attempts == 12 {
|
|
129
|
+
panic!("failed to query registered namespace");
|
|
130
|
+
}
|
|
131
|
+
sleep(wait_time).await
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
77
135
|
}
|
|
78
136
|
|
|
79
137
|
#[tokio::test]
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
use anyhow::anyhow;
|
|
1
2
|
use assert_matches::assert_matches;
|
|
2
3
|
use std::time::Duration;
|
|
3
4
|
use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowExecutionResult, WorkflowOptions};
|
|
@@ -23,10 +24,11 @@ use temporal_sdk_core_protos::{
|
|
|
23
24
|
enums::v1::RetryState,
|
|
24
25
|
failure::v1::{failure::FailureInfo, ActivityFailureInfo, Failure},
|
|
25
26
|
},
|
|
26
|
-
TaskToken,
|
|
27
|
+
TaskToken, DEFAULT_ACTIVITY_TYPE,
|
|
27
28
|
};
|
|
28
29
|
use temporal_sdk_core_test_utils::{
|
|
29
|
-
init_core_and_create_wf, schedule_activity_cmd, CoreWfStarter,
|
|
30
|
+
drain_pollers_and_shutdown, init_core_and_create_wf, schedule_activity_cmd, CoreWfStarter,
|
|
31
|
+
WorkerTestHelpers,
|
|
30
32
|
};
|
|
31
33
|
use tokio::time::sleep;
|
|
32
34
|
|
|
@@ -97,7 +99,7 @@ async fn activity_workflow() {
|
|
|
97
99
|
assert_matches!(
|
|
98
100
|
task.variant,
|
|
99
101
|
Some(act_task::Variant::Start(start_activity)) => {
|
|
100
|
-
assert_eq!(start_activity.activity_type,
|
|
102
|
+
assert_eq!(start_activity.activity_type, DEFAULT_ACTIVITY_TYPE.to_string())
|
|
101
103
|
}
|
|
102
104
|
);
|
|
103
105
|
let response_payload = Payload {
|
|
@@ -154,16 +156,78 @@ async fn activity_non_retryable_failure() {
|
|
|
154
156
|
)
|
|
155
157
|
.await
|
|
156
158
|
.unwrap();
|
|
157
|
-
// Poll activity and verify that it's been scheduled
|
|
159
|
+
// Poll activity and verify that it's been scheduled
|
|
158
160
|
let task = core.poll_activity_task().await.unwrap();
|
|
161
|
+
assert_matches!(task.variant, Some(act_task::Variant::Start(_)));
|
|
162
|
+
// Fail activity with non-retryable error
|
|
163
|
+
let failure = Failure::application_failure("activity failed".to_string(), true);
|
|
164
|
+
core.complete_activity_task(ActivityTaskCompletion {
|
|
165
|
+
task_token: task.task_token,
|
|
166
|
+
result: Some(ActivityExecutionResult::fail(failure.clone())),
|
|
167
|
+
})
|
|
168
|
+
.await
|
|
169
|
+
.unwrap();
|
|
170
|
+
// Poll workflow task and verify that activity has failed.
|
|
171
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
159
172
|
assert_matches!(
|
|
160
|
-
task.
|
|
161
|
-
|
|
162
|
-
|
|
173
|
+
task.jobs.as_slice(),
|
|
174
|
+
[
|
|
175
|
+
WorkflowActivationJob {
|
|
176
|
+
variant: Some(workflow_activation_job::Variant::ResolveActivity(
|
|
177
|
+
ResolveActivity {seq, result: Some(ActivityResolution{
|
|
178
|
+
status: Some(act_res::Status::Failed(activity_result::Failure{
|
|
179
|
+
failure: Some(f),
|
|
180
|
+
}))})}
|
|
181
|
+
)),
|
|
182
|
+
},
|
|
183
|
+
] => {
|
|
184
|
+
assert_eq!(*seq, 0);
|
|
185
|
+
assert_eq!(f, &Failure{
|
|
186
|
+
message: "Activity task failed".to_owned(),
|
|
187
|
+
cause: Some(Box::new(failure)),
|
|
188
|
+
failure_info: Some(FailureInfo::ActivityFailureInfo(ActivityFailureInfo{
|
|
189
|
+
activity_id: "act-1".to_owned(),
|
|
190
|
+
activity_type: Some(ActivityType {
|
|
191
|
+
name: DEFAULT_ACTIVITY_TYPE.to_owned(),
|
|
192
|
+
}),
|
|
193
|
+
scheduled_event_id: 5,
|
|
194
|
+
started_event_id: 6,
|
|
195
|
+
identity: "integ_tester".to_owned(),
|
|
196
|
+
retry_state: RetryState::NonRetryableFailure as i32,
|
|
197
|
+
})),
|
|
198
|
+
..Default::default()
|
|
199
|
+
});
|
|
163
200
|
}
|
|
164
201
|
);
|
|
202
|
+
core.complete_execution(&task.run_id).await;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
#[tokio::test]
|
|
206
|
+
async fn activity_non_retryable_failure_with_error() {
|
|
207
|
+
let mut starter = init_core_and_create_wf("activity_non_retryable_failure").await;
|
|
208
|
+
let core = starter.get_worker().await;
|
|
209
|
+
let task_q = starter.get_task_queue();
|
|
210
|
+
let activity_id = "act-1";
|
|
211
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
212
|
+
// Complete workflow task and schedule activity
|
|
213
|
+
core.complete_workflow_activation(
|
|
214
|
+
schedule_activity_cmd(
|
|
215
|
+
0,
|
|
216
|
+
task_q,
|
|
217
|
+
activity_id,
|
|
218
|
+
ActivityCancellationType::TryCancel,
|
|
219
|
+
Duration::from_secs(60),
|
|
220
|
+
Duration::from_secs(60),
|
|
221
|
+
)
|
|
222
|
+
.into_completion(task.run_id),
|
|
223
|
+
)
|
|
224
|
+
.await
|
|
225
|
+
.unwrap();
|
|
226
|
+
// Poll activity and verify that it's been scheduled
|
|
227
|
+
let task = core.poll_activity_task().await.unwrap();
|
|
228
|
+
assert_matches!(task.variant, Some(act_task::Variant::Start(_)));
|
|
165
229
|
// Fail activity with non-retryable error
|
|
166
|
-
let failure = Failure::
|
|
230
|
+
let failure = Failure::application_failure_from_error(anyhow!("activity failed"), true);
|
|
167
231
|
core.complete_activity_task(ActivityTaskCompletion {
|
|
168
232
|
task_token: task.task_token,
|
|
169
233
|
result: Some(ActivityExecutionResult::fail(failure.clone())),
|
|
@@ -191,7 +255,7 @@ async fn activity_non_retryable_failure() {
|
|
|
191
255
|
failure_info: Some(FailureInfo::ActivityFailureInfo(ActivityFailureInfo{
|
|
192
256
|
activity_id: "act-1".to_owned(),
|
|
193
257
|
activity_type: Some(ActivityType {
|
|
194
|
-
name:
|
|
258
|
+
name: DEFAULT_ACTIVITY_TYPE.to_owned(),
|
|
195
259
|
}),
|
|
196
260
|
scheduled_event_id: 5,
|
|
197
261
|
started_event_id: 6,
|
|
@@ -228,12 +292,7 @@ async fn activity_retry() {
|
|
|
228
292
|
.unwrap();
|
|
229
293
|
// Poll activity 1st time
|
|
230
294
|
let task = core.poll_activity_task().await.unwrap();
|
|
231
|
-
assert_matches!(
|
|
232
|
-
task.variant,
|
|
233
|
-
Some(act_task::Variant::Start(start_activity)) => {
|
|
234
|
-
assert_eq!(start_activity.activity_type, "test_activity".to_string())
|
|
235
|
-
}
|
|
236
|
-
);
|
|
295
|
+
assert_matches!(task.variant, Some(act_task::Variant::Start(_)));
|
|
237
296
|
// Fail activity with retryable error
|
|
238
297
|
let failure = Failure::application_failure("activity failed".to_string(), false);
|
|
239
298
|
core.complete_activity_task(ActivityTaskCompletion {
|
|
@@ -244,12 +303,7 @@ async fn activity_retry() {
|
|
|
244
303
|
.unwrap();
|
|
245
304
|
// Poll 2nd time
|
|
246
305
|
let task = core.poll_activity_task().await.unwrap();
|
|
247
|
-
assert_matches!(
|
|
248
|
-
task.variant,
|
|
249
|
-
Some(act_task::Variant::Start(start_activity)) => {
|
|
250
|
-
assert_eq!(start_activity.activity_type, "test_activity".to_string())
|
|
251
|
-
}
|
|
252
|
-
);
|
|
306
|
+
assert_matches!(task.variant, Some(act_task::Variant::Start(_)));
|
|
253
307
|
// Complete activity successfully
|
|
254
308
|
let response_payload = Payload {
|
|
255
309
|
data: b"hello ".to_vec(),
|
|
@@ -308,15 +362,10 @@ async fn activity_cancellation_try_cancel() {
|
|
|
308
362
|
)
|
|
309
363
|
.await
|
|
310
364
|
.unwrap();
|
|
311
|
-
// Poll activity and verify that it's been scheduled
|
|
312
|
-
//
|
|
365
|
+
// Poll activity and verify that it's been scheduled, we don't expect to complete it in this
|
|
366
|
+
// test as activity is try-cancelled.
|
|
313
367
|
let activity_task = core.poll_activity_task().await.unwrap();
|
|
314
|
-
assert_matches!(
|
|
315
|
-
activity_task.variant,
|
|
316
|
-
Some(act_task::Variant::Start(start_activity)) => {
|
|
317
|
-
assert_eq!(start_activity.activity_type, "test_activity".to_string())
|
|
318
|
-
}
|
|
319
|
-
);
|
|
368
|
+
assert_matches!(activity_task.variant, Some(act_task::Variant::Start(_)));
|
|
320
369
|
// Poll workflow task and verify that activity has failed.
|
|
321
370
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
322
371
|
assert_matches!(
|
|
@@ -453,15 +502,10 @@ async fn started_activity_timeout() {
|
|
|
453
502
|
)
|
|
454
503
|
.await
|
|
455
504
|
.unwrap();
|
|
456
|
-
// Poll activity and verify that it's been scheduled
|
|
457
|
-
//
|
|
505
|
+
// Poll activity and verify that it's been scheduled, we don't expect to complete it in this
|
|
506
|
+
// test as activity is timed out after 1 second.
|
|
458
507
|
let activity_task = core.poll_activity_task().await.unwrap();
|
|
459
|
-
assert_matches!(
|
|
460
|
-
activity_task.variant,
|
|
461
|
-
Some(act_task::Variant::Start(start_activity)) => {
|
|
462
|
-
assert_eq!(start_activity.activity_type, "test_activity".to_string())
|
|
463
|
-
}
|
|
464
|
-
);
|
|
508
|
+
assert_matches!(activity_task.variant, Some(act_task::Variant::Start(_)));
|
|
465
509
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
466
510
|
assert_matches!(
|
|
467
511
|
task.jobs.as_slice(),
|
|
@@ -517,15 +561,10 @@ async fn activity_cancellation_wait_cancellation_completed() {
|
|
|
517
561
|
)
|
|
518
562
|
.await
|
|
519
563
|
.unwrap();
|
|
520
|
-
// Poll activity and verify that it's been scheduled
|
|
521
|
-
//
|
|
564
|
+
// Poll activity and verify that it's been scheduled, we don't expect to complete it in this
|
|
565
|
+
// test as activity is wait-cancelled.
|
|
522
566
|
let activity_task = core.poll_activity_task().await.unwrap();
|
|
523
|
-
assert_matches!(
|
|
524
|
-
activity_task.variant,
|
|
525
|
-
Some(act_task::Variant::Start(start_activity)) => {
|
|
526
|
-
assert_eq!(start_activity.activity_type, "test_activity".to_string())
|
|
527
|
-
}
|
|
528
|
-
);
|
|
567
|
+
assert_matches!(activity_task.variant, Some(act_task::Variant::Start(_)));
|
|
529
568
|
// Poll workflow task and verify that activity has failed.
|
|
530
569
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
531
570
|
assert_matches!(
|
|
@@ -584,15 +623,10 @@ async fn activity_cancellation_abandon() {
|
|
|
584
623
|
)
|
|
585
624
|
.await
|
|
586
625
|
.unwrap();
|
|
587
|
-
// Poll activity and verify that it's been scheduled
|
|
588
|
-
//
|
|
626
|
+
// Poll activity and verify that it's been scheduled, we don't expect to complete it in this
|
|
627
|
+
// test as activity is abandoned.
|
|
589
628
|
let activity_task = core.poll_activity_task().await.unwrap();
|
|
590
|
-
assert_matches!(
|
|
591
|
-
activity_task.variant,
|
|
592
|
-
Some(act_task::Variant::Start(start_activity)) => {
|
|
593
|
-
assert_eq!(start_activity.activity_type, "test_activity".to_string())
|
|
594
|
-
}
|
|
595
|
-
);
|
|
629
|
+
assert_matches!(activity_task.variant, Some(act_task::Variant::Start(_)));
|
|
596
630
|
// Poll workflow task and verify that activity has failed.
|
|
597
631
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
598
632
|
assert_matches!(
|
|
@@ -640,14 +674,9 @@ async fn async_activity_completion_workflow() {
|
|
|
640
674
|
)
|
|
641
675
|
.await
|
|
642
676
|
.unwrap();
|
|
643
|
-
// Poll activity and verify that it's been scheduled
|
|
677
|
+
// Poll activity and verify that it's been scheduled
|
|
644
678
|
let task = core.poll_activity_task().await.unwrap();
|
|
645
|
-
assert_matches!(
|
|
646
|
-
task.variant,
|
|
647
|
-
Some(act_task::Variant::Start(start_activity)) => {
|
|
648
|
-
assert_eq!(start_activity.activity_type, "test_activity".to_string())
|
|
649
|
-
}
|
|
650
|
-
);
|
|
679
|
+
assert_matches!(task.variant, Some(act_task::Variant::Start(_)));
|
|
651
680
|
let response_payload = Payload {
|
|
652
681
|
data: b"hello ".to_vec(),
|
|
653
682
|
metadata: Default::default(),
|
|
@@ -712,14 +741,9 @@ async fn activity_cancelled_after_heartbeat_times_out() {
|
|
|
712
741
|
)
|
|
713
742
|
.await
|
|
714
743
|
.unwrap();
|
|
715
|
-
// Poll activity and verify that it's been scheduled
|
|
744
|
+
// Poll activity and verify that it's been scheduled
|
|
716
745
|
let task = core.poll_activity_task().await.unwrap();
|
|
717
|
-
assert_matches!(
|
|
718
|
-
task.variant,
|
|
719
|
-
Some(act_task::Variant::Start(start_activity)) => {
|
|
720
|
-
assert_eq!(start_activity.activity_type, "test_activity".to_string())
|
|
721
|
-
}
|
|
722
|
-
);
|
|
746
|
+
assert_matches!(task.variant, Some(act_task::Variant::Start(_)));
|
|
723
747
|
// Delay the heartbeat
|
|
724
748
|
sleep(Duration::from_secs(2)).await;
|
|
725
749
|
core.record_activity_heartbeat(ActivityHeartbeat {
|
|
@@ -741,7 +765,7 @@ async fn activity_cancelled_after_heartbeat_times_out() {
|
|
|
741
765
|
.unwrap();
|
|
742
766
|
|
|
743
767
|
// Verify shutdown completes
|
|
744
|
-
core
|
|
768
|
+
drain_pollers_and_shutdown(&core).await;
|
|
745
769
|
// Cleanup just in case
|
|
746
770
|
starter
|
|
747
771
|
.get_client()
|
|
@@ -822,7 +846,7 @@ async fn it_can_complete_async() {
|
|
|
822
846
|
Some(act_res::Status::Completed(activity_result::Success { result })) => result
|
|
823
847
|
.map(|p| String::from_json_payload(&p).unwrap())
|
|
824
848
|
.unwrap(),
|
|
825
|
-
_ => panic!("activity task failed {:?}"
|
|
849
|
+
_ => panic!("activity task failed {activity_resolution:?}"),
|
|
826
850
|
};
|
|
827
851
|
|
|
828
852
|
assert_eq!(&res, async_response);
|
|
@@ -33,6 +33,7 @@ async fn cancel_receiver(mut ctx: WfContext) -> WorkflowResult<()> {
|
|
|
33
33
|
#[tokio::test]
|
|
34
34
|
async fn sends_cancel_to_other_wf() {
|
|
35
35
|
let mut starter = CoreWfStarter::new("sends_cancel_to_other_wf");
|
|
36
|
+
starter.no_remote_activities();
|
|
36
37
|
let mut worker = starter.worker().await;
|
|
37
38
|
worker.register_wf("sender", cancel_sender);
|
|
38
39
|
worker.register_wf("receiver", cancel_receiver);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
use std::time::Duration;
|
|
2
|
-
use temporal_client::
|
|
2
|
+
use temporal_client::WorkflowClientTrait;
|
|
3
3
|
use temporal_sdk::{WfContext, WfExitValue, WorkflowResult};
|
|
4
4
|
use temporal_sdk_core_protos::temporal::api::enums::v1::WorkflowExecutionStatus;
|
|
5
5
|
use temporal_sdk_core_test_utils::CoreWfStarter;
|
|
@@ -21,25 +21,18 @@ async fn cancelled_wf(mut ctx: WfContext) -> WorkflowResult<()> {
|
|
|
21
21
|
async fn cancel_during_timer() {
|
|
22
22
|
let wf_name = "cancel_during_timer";
|
|
23
23
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
24
|
+
starter.no_remote_activities();
|
|
24
25
|
let mut worker = starter.worker().await;
|
|
25
26
|
let client = starter.get_client().await;
|
|
26
27
|
worker.register_wf(wf_name.to_string(), cancelled_wf);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
.submit_wf(
|
|
30
|
-
wf_name.to_owned(),
|
|
31
|
-
wf_name.to_owned(),
|
|
32
|
-
vec![],
|
|
33
|
-
WorkflowOptions::default(),
|
|
34
|
-
)
|
|
35
|
-
.await
|
|
36
|
-
.unwrap();
|
|
28
|
+
starter.start_with_worker(wf_name, &mut worker).await;
|
|
29
|
+
let wf_id = starter.get_task_queue().to_string();
|
|
37
30
|
|
|
38
31
|
let canceller = async {
|
|
39
32
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
|
40
33
|
// Cancel the workflow externally
|
|
41
34
|
client
|
|
42
|
-
.cancel_workflow_execution(
|
|
35
|
+
.cancel_workflow_execution(wf_id.clone(), None, "Dieee".to_string(), None)
|
|
43
36
|
.await
|
|
44
37
|
.unwrap();
|
|
45
38
|
};
|
|
@@ -47,7 +40,7 @@ async fn cancel_during_timer() {
|
|
|
47
40
|
let (_, res) = tokio::join!(canceller, worker.run_until_done());
|
|
48
41
|
res.unwrap();
|
|
49
42
|
let desc = client
|
|
50
|
-
.describe_workflow_execution(
|
|
43
|
+
.describe_workflow_execution(wf_id, None)
|
|
51
44
|
.await
|
|
52
45
|
.unwrap();
|
|
53
46
|
|
|
@@ -32,6 +32,7 @@ async fn parent_wf(ctx: WfContext) -> WorkflowResult<()> {
|
|
|
32
32
|
#[tokio::test]
|
|
33
33
|
async fn child_workflow_happy_path() {
|
|
34
34
|
let mut starter = CoreWfStarter::new("child-workflows");
|
|
35
|
+
starter.no_remote_activities();
|
|
35
36
|
let mut worker = starter.worker().await;
|
|
36
37
|
|
|
37
38
|
worker.register_wf(PARENT_WF_TYPE.to_string(), parent_wf);
|
|
@@ -21,6 +21,7 @@ async fn continue_as_new_wf(ctx: WfContext) -> WorkflowResult<()> {
|
|
|
21
21
|
async fn continue_as_new_happy_path() {
|
|
22
22
|
let wf_name = "continue_as_new_happy_path";
|
|
23
23
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
24
|
+
starter.no_remote_activities();
|
|
24
25
|
let mut worker = starter.worker().await;
|
|
25
26
|
worker.register_wf(wf_name.to_string(), continue_as_new_wf);
|
|
26
27
|
|
|
@@ -40,11 +41,14 @@ async fn continue_as_new_happy_path() {
|
|
|
40
41
|
async fn continue_as_new_multiple_concurrent() {
|
|
41
42
|
let wf_name = "continue_as_new_multiple_concurrent";
|
|
42
43
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
43
|
-
starter
|
|
44
|
+
starter
|
|
45
|
+
.no_remote_activities()
|
|
46
|
+
.max_cached_workflows(3)
|
|
47
|
+
.max_wft(3);
|
|
44
48
|
let mut worker = starter.worker().await;
|
|
45
49
|
worker.register_wf(wf_name.to_string(), continue_as_new_wf);
|
|
46
50
|
|
|
47
|
-
let wf_names = (1..=20).map(|i| format!("{}-{}"
|
|
51
|
+
let wf_names = (1..=20).map(|i| format!("{wf_name}-{i}"));
|
|
48
52
|
for name in wf_names.clone() {
|
|
49
53
|
worker
|
|
50
54
|
.submit_wf(
|
|
@@ -2,7 +2,7 @@ use std::{
|
|
|
2
2
|
sync::atomic::{AtomicUsize, Ordering},
|
|
3
3
|
time::Duration,
|
|
4
4
|
};
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
use temporal_sdk::{ActivityOptions, WfContext, WorkflowResult};
|
|
7
7
|
use temporal_sdk_core_test_utils::CoreWfStarter;
|
|
8
8
|
|
|
@@ -36,18 +36,11 @@ pub async fn timer_wf_nondeterministic(ctx: WfContext) -> WorkflowResult<()> {
|
|
|
36
36
|
async fn test_determinism_error_then_recovers() {
|
|
37
37
|
let wf_name = "test_determinism_error_then_recovers";
|
|
38
38
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
39
|
+
starter.no_remote_activities();
|
|
39
40
|
let mut worker = starter.worker().await;
|
|
40
41
|
|
|
41
42
|
worker.register_wf(wf_name.to_owned(), timer_wf_nondeterministic);
|
|
42
|
-
worker
|
|
43
|
-
.submit_wf(
|
|
44
|
-
wf_name.to_owned(),
|
|
45
|
-
wf_name.to_owned(),
|
|
46
|
-
vec![],
|
|
47
|
-
WorkflowOptions::default(),
|
|
48
|
-
)
|
|
49
|
-
.await
|
|
50
|
-
.unwrap();
|
|
43
|
+
starter.start_with_worker(wf_name, &mut worker).await;
|
|
51
44
|
worker.run_until_done().await.unwrap();
|
|
52
45
|
// 4 because we still add on the 3rd and final attempt
|
|
53
46
|
assert_eq!(RUN_CT.load(Ordering::Relaxed), 4);
|