@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.
Files changed (181) hide show
  1. package/Cargo.lock +239 -382
  2. package/Cargo.toml +11 -11
  3. package/lib/native.d.ts +10 -3
  4. package/package.json +3 -3
  5. package/releases/aarch64-apple-darwin/index.node +0 -0
  6. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  7. package/releases/x86_64-apple-darwin/index.node +0 -0
  8. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  9. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  10. package/sdk-core/.cargo/config.toml +71 -11
  11. package/sdk-core/.clippy.toml +1 -0
  12. package/sdk-core/.github/workflows/heavy.yml +2 -0
  13. package/sdk-core/.github/workflows/per-pr.yml +50 -18
  14. package/sdk-core/ARCHITECTURE.md +44 -48
  15. package/sdk-core/Cargo.toml +26 -7
  16. package/sdk-core/README.md +4 -0
  17. package/sdk-core/arch_docs/diagrams/TimerMachine_Coverage.puml +14 -0
  18. package/sdk-core/arch_docs/diagrams/initial_event_history.png +0 -0
  19. package/sdk-core/arch_docs/sdks_intro.md +299 -0
  20. package/sdk-core/client/Cargo.toml +8 -7
  21. package/sdk-core/client/src/callback_based.rs +1 -2
  22. package/sdk-core/client/src/lib.rs +485 -299
  23. package/sdk-core/client/src/metrics.rs +32 -8
  24. package/sdk-core/client/src/proxy.rs +124 -5
  25. package/sdk-core/client/src/raw.rs +598 -307
  26. package/sdk-core/client/src/replaceable.rs +253 -0
  27. package/sdk-core/client/src/retry.rs +9 -6
  28. package/sdk-core/client/src/worker_registry/mod.rs +19 -3
  29. package/sdk-core/client/src/workflow_handle/mod.rs +20 -17
  30. package/sdk-core/core/Cargo.toml +100 -31
  31. package/sdk-core/core/src/core_tests/activity_tasks.rs +55 -225
  32. package/sdk-core/core/src/core_tests/mod.rs +2 -8
  33. package/sdk-core/core/src/core_tests/queries.rs +3 -5
  34. package/sdk-core/core/src/core_tests/replay_flag.rs +3 -62
  35. package/sdk-core/core/src/core_tests/updates.rs +4 -5
  36. package/sdk-core/core/src/core_tests/workers.rs +4 -3
  37. package/sdk-core/core/src/core_tests/workflow_cancels.rs +10 -7
  38. package/sdk-core/core/src/core_tests/workflow_tasks.rs +28 -291
  39. package/sdk-core/core/src/ephemeral_server/mod.rs +15 -3
  40. package/sdk-core/core/src/internal_flags.rs +11 -1
  41. package/sdk-core/core/src/lib.rs +50 -36
  42. package/sdk-core/core/src/pollers/mod.rs +5 -5
  43. package/sdk-core/core/src/pollers/poll_buffer.rs +2 -2
  44. package/sdk-core/core/src/protosext/mod.rs +13 -5
  45. package/sdk-core/core/src/protosext/protocol_messages.rs +4 -11
  46. package/sdk-core/core/src/retry_logic.rs +256 -108
  47. package/sdk-core/core/src/telemetry/metrics.rs +1 -0
  48. package/sdk-core/core/src/telemetry/mod.rs +8 -2
  49. package/sdk-core/core/src/telemetry/prometheus_meter.rs +2 -2
  50. package/sdk-core/core/src/test_help/integ_helpers.rs +971 -0
  51. package/sdk-core/core/src/test_help/mod.rs +10 -1100
  52. package/sdk-core/core/src/test_help/unit_helpers.rs +218 -0
  53. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +42 -6
  54. package/sdk-core/core/src/worker/activities/local_activities.rs +19 -19
  55. package/sdk-core/core/src/worker/activities.rs +10 -3
  56. package/sdk-core/core/src/worker/client/mocks.rs +3 -3
  57. package/sdk-core/core/src/worker/client.rs +130 -93
  58. package/sdk-core/core/src/worker/heartbeat.rs +12 -13
  59. package/sdk-core/core/src/worker/mod.rs +31 -21
  60. package/sdk-core/core/src/worker/nexus.rs +14 -3
  61. package/sdk-core/core/src/worker/slot_provider.rs +9 -0
  62. package/sdk-core/core/src/worker/tuner.rs +159 -0
  63. package/sdk-core/core/src/worker/workflow/history_update.rs +3 -265
  64. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -54
  65. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +0 -82
  66. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +0 -67
  67. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -192
  68. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +0 -43
  69. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +6 -554
  70. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -71
  71. package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +102 -3
  72. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +10 -539
  73. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +0 -139
  74. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -119
  75. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +6 -63
  76. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +9 -4
  77. package/sdk-core/core/src/worker/workflow/mod.rs +5 -1
  78. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +8 -3
  79. package/sdk-core/core-api/Cargo.toml +4 -4
  80. package/sdk-core/core-api/src/envconfig.rs +153 -54
  81. package/sdk-core/core-api/src/lib.rs +68 -0
  82. package/sdk-core/core-api/src/telemetry/metrics.rs +2 -1
  83. package/sdk-core/core-api/src/telemetry.rs +13 -0
  84. package/sdk-core/core-c-bridge/Cargo.toml +13 -8
  85. package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +184 -22
  86. package/sdk-core/core-c-bridge/src/client.rs +462 -184
  87. package/sdk-core/core-c-bridge/src/envconfig.rs +314 -0
  88. package/sdk-core/core-c-bridge/src/lib.rs +1 -0
  89. package/sdk-core/core-c-bridge/src/random.rs +4 -4
  90. package/sdk-core/core-c-bridge/src/runtime.rs +22 -23
  91. package/sdk-core/core-c-bridge/src/testing.rs +1 -4
  92. package/sdk-core/core-c-bridge/src/tests/context.rs +31 -31
  93. package/sdk-core/core-c-bridge/src/tests/mod.rs +32 -28
  94. package/sdk-core/core-c-bridge/src/tests/utils.rs +7 -7
  95. package/sdk-core/core-c-bridge/src/worker.rs +319 -66
  96. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -1
  97. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +5 -5
  98. package/sdk-core/sdk/Cargo.toml +8 -2
  99. package/sdk-core/sdk/src/activity_context.rs +1 -1
  100. package/sdk-core/sdk/src/app_data.rs +1 -1
  101. package/sdk-core/sdk/src/interceptors.rs +1 -4
  102. package/sdk-core/sdk/src/lib.rs +1 -5
  103. package/sdk-core/sdk/src/workflow_context/options.rs +10 -1
  104. package/sdk-core/sdk/src/workflow_future.rs +1 -1
  105. package/sdk-core/sdk-core-protos/Cargo.toml +6 -6
  106. package/sdk-core/sdk-core-protos/build.rs +10 -23
  107. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +9 -1
  108. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +254 -5
  109. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +234 -5
  110. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +1 -1
  111. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +6 -0
  112. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -2
  113. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -2
  114. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -6
  115. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  116. package/sdk-core/{test-utils → sdk-core-protos}/src/canned_histories.rs +5 -5
  117. package/sdk-core/sdk-core-protos/src/history_builder.rs +2 -2
  118. package/sdk-core/sdk-core-protos/src/lib.rs +25 -9
  119. package/sdk-core/sdk-core-protos/src/test_utils.rs +89 -0
  120. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -5
  121. package/sdk-core/tests/c_bridge_smoke_test.c +10 -0
  122. package/sdk-core/tests/cloud_tests.rs +10 -8
  123. package/sdk-core/tests/common/http_proxy.rs +134 -0
  124. package/sdk-core/{test-utils/src/lib.rs → tests/common/mod.rs} +214 -281
  125. package/sdk-core/{test-utils/src → tests/common}/workflows.rs +4 -3
  126. package/sdk-core/tests/fuzzy_workflow.rs +1 -1
  127. package/sdk-core/tests/global_metric_tests.rs +8 -7
  128. package/sdk-core/tests/heavy_tests.rs +7 -3
  129. package/sdk-core/tests/integ_tests/client_tests.rs +111 -24
  130. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +14 -9
  131. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +4 -4
  132. package/sdk-core/tests/integ_tests/metrics_tests.rs +114 -14
  133. package/sdk-core/tests/integ_tests/pagination_tests.rs +273 -0
  134. package/sdk-core/tests/integ_tests/polling_tests.rs +311 -93
  135. package/sdk-core/tests/integ_tests/queries_tests.rs +4 -4
  136. package/sdk-core/tests/integ_tests/update_tests.rs +13 -7
  137. package/sdk-core/tests/integ_tests/visibility_tests.rs +26 -9
  138. package/sdk-core/tests/integ_tests/worker_tests.rs +668 -13
  139. package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +40 -24
  140. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +244 -11
  141. package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +1 -1
  142. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +78 -2
  143. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +61 -2
  144. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +465 -7
  145. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +41 -2
  146. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +315 -3
  147. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
  148. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1990 -14
  149. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +65 -2
  150. package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +123 -23
  151. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +525 -3
  152. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +65 -16
  153. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +32 -23
  154. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +126 -5
  155. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +1 -2
  156. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +124 -8
  157. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +62 -2
  158. package/sdk-core/tests/integ_tests/workflow_tests.rs +67 -8
  159. package/sdk-core/tests/main.rs +26 -17
  160. package/sdk-core/tests/manual_tests.rs +5 -1
  161. package/sdk-core/tests/runner.rs +22 -40
  162. package/sdk-core/tests/shared_tests/mod.rs +1 -1
  163. package/sdk-core/tests/shared_tests/priority.rs +1 -1
  164. package/sdk-core/{core/benches/workflow_replay.rs → tests/workflow_replay_bench.rs} +10 -5
  165. package/src/client.rs +97 -20
  166. package/src/helpers/callbacks.rs +4 -4
  167. package/src/helpers/errors.rs +7 -1
  168. package/src/helpers/handles.rs +1 -0
  169. package/src/helpers/try_from_js.rs +4 -3
  170. package/src/lib.rs +3 -2
  171. package/src/metrics.rs +3 -0
  172. package/src/runtime.rs +5 -2
  173. package/src/worker.rs +9 -12
  174. package/ts/native.ts +13 -3
  175. package/sdk-core/arch_docs/diagrams/workflow_internals.svg +0 -1
  176. package/sdk-core/core/src/core_tests/child_workflows.rs +0 -281
  177. package/sdk-core/core/src/core_tests/determinism.rs +0 -318
  178. package/sdk-core/core/src/core_tests/local_activities.rs +0 -1442
  179. package/sdk-core/test-utils/Cargo.toml +0 -38
  180. package/sdk-core/test-utils/src/histfetch.rs +0 -28
  181. package/sdk-core/test-utils/src/interceptors.rs +0 -46
@@ -31,7 +31,7 @@ use temporal_sdk_core_protos::{
31
31
  workflow_commands::ActivityCancellationType,
32
32
  },
33
33
  temporal::api::{
34
- command::v1::{RecordMarkerCommandAttributes, command},
34
+ command::v1::{Command as ProtoCommand, RecordMarkerCommandAttributes, command},
35
35
  enums::v1::{CommandType, EventType, RetryState},
36
36
  failure::v1::{Failure, failure::FailureInfo},
37
37
  },
@@ -772,9 +772,11 @@ impl WFMachinesAdapter for LocalActivityMachine {
772
772
  header: None,
773
773
  failure: maybe_failure,
774
774
  };
775
- responses.push(MachineResponse::IssueNewCommand(
776
- command::Attributes::RecordMarkerCommandAttributes(marker_data).into(),
777
- ));
775
+ let command = ProtoCommand {
776
+ user_metadata: self.shared_state.attrs.user_metadata.clone(),
777
+ ..command::Attributes::RecordMarkerCommandAttributes(marker_data).into()
778
+ };
779
+ responses.push(MachineResponse::IssueNewCommand(command));
778
780
  }
779
781
  Ok(responses)
780
782
  }
@@ -860,553 +862,3 @@ fn verify_marker_data_matches(
860
862
 
861
863
  Ok(())
862
864
  }
863
-
864
- #[cfg(test)]
865
- mod tests {
866
- use super::*;
867
- use crate::{
868
- replay::TestHistoryBuilder,
869
- test_help::{MockPollCfg, ResponseType, build_fake_sdk, canned_histories},
870
- };
871
- use anyhow::anyhow;
872
- use rstest::rstest;
873
- use std::{
874
- sync::atomic::{AtomicI64, Ordering},
875
- time::Duration,
876
- };
877
- use temporal_sdk::{
878
- ActContext, ActivityError, CancellableFuture, LocalActivityOptions, WfContext,
879
- WorkflowResult,
880
- };
881
- use temporal_sdk_core_protos::{
882
- DEFAULT_ACTIVITY_TYPE, DEFAULT_WORKFLOW_TYPE,
883
- coresdk::{
884
- AsJsonPayloadExt,
885
- workflow_activation::{WorkflowActivationJob, workflow_activation_job},
886
- },
887
- temporal::api::{
888
- common::v1::RetryPolicy, enums::v1::WorkflowTaskFailedCause, failure::v1::Failure,
889
- },
890
- };
891
- use temporal_sdk_core_test_utils::interceptors::ActivationAssertionsInterceptor;
892
- use tokio_util::sync::CancellationToken;
893
-
894
- async fn la_wf(ctx: WfContext) -> WorkflowResult<()> {
895
- ctx.local_activity(LocalActivityOptions {
896
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
897
- input: ().as_json_payload().unwrap(),
898
- retry_policy: RetryPolicy {
899
- maximum_attempts: 1,
900
- ..Default::default()
901
- },
902
- ..Default::default()
903
- })
904
- .await;
905
- Ok(().into())
906
- }
907
-
908
- #[rstest]
909
- #[case::incremental(false, true)]
910
- #[case::replay(true, true)]
911
- #[case::incremental_fail(false, false)]
912
- #[case::replay_fail(true, false)]
913
- #[tokio::test]
914
- async fn one_la_success(#[case] replay: bool, #[case] completes_ok: bool) {
915
- let activity_id = "1";
916
- let mut t = TestHistoryBuilder::default();
917
- t.add_by_type(EventType::WorkflowExecutionStarted);
918
- t.add_full_wf_task();
919
- if completes_ok {
920
- t.add_local_activity_result_marker(1, activity_id, b"hi".into());
921
- } else {
922
- t.add_local_activity_fail_marker(
923
- 1,
924
- activity_id,
925
- Failure::application_failure("I failed".to_string(), false),
926
- );
927
- }
928
- t.add_workflow_task_scheduled_and_started();
929
-
930
- let mut mock_cfg = if replay {
931
- MockPollCfg::from_resps(t, [ResponseType::AllHistory])
932
- } else {
933
- MockPollCfg::from_hist_builder(t)
934
- };
935
- mock_cfg.completion_asserts_from_expectations(|mut asserts| {
936
- asserts.then(move |wft| {
937
- let commands = &wft.commands;
938
- if !replay {
939
- assert_eq!(commands.len(), 2);
940
- assert_eq!(commands[0].command_type(), CommandType::RecordMarker);
941
- if completes_ok {
942
- assert_matches!(
943
- commands[0].attributes.as_ref().unwrap(),
944
- command::Attributes::RecordMarkerCommandAttributes(
945
- RecordMarkerCommandAttributes { failure: None, .. }
946
- )
947
- );
948
- } else {
949
- assert_matches!(
950
- commands[0].attributes.as_ref().unwrap(),
951
- command::Attributes::RecordMarkerCommandAttributes(
952
- RecordMarkerCommandAttributes {
953
- failure: Some(_),
954
- ..
955
- }
956
- )
957
- );
958
- }
959
- assert_eq!(
960
- commands[1].command_type(),
961
- CommandType::CompleteWorkflowExecution
962
- );
963
- } else {
964
- assert_eq!(commands.len(), 1);
965
- assert_matches!(
966
- commands[0].command_type(),
967
- CommandType::CompleteWorkflowExecution
968
- );
969
- }
970
- });
971
- });
972
-
973
- let mut worker = build_fake_sdk(mock_cfg);
974
- worker.register_wf(DEFAULT_WORKFLOW_TYPE, la_wf);
975
- worker.register_activity(
976
- DEFAULT_ACTIVITY_TYPE,
977
- move |_ctx: ActContext, _: ()| async move {
978
- if replay {
979
- panic!("Should not be invoked on replay");
980
- }
981
- if completes_ok {
982
- Ok("hi")
983
- } else {
984
- Err(anyhow!("Oh no I failed!").into())
985
- }
986
- },
987
- );
988
- worker.run().await.unwrap();
989
- }
990
-
991
- async fn two_la_wf(ctx: WfContext) -> WorkflowResult<()> {
992
- ctx.local_activity(LocalActivityOptions {
993
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
994
- input: ().as_json_payload().unwrap(),
995
- ..Default::default()
996
- })
997
- .await;
998
- ctx.local_activity(LocalActivityOptions {
999
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1000
- input: ().as_json_payload().unwrap(),
1001
- ..Default::default()
1002
- })
1003
- .await;
1004
- Ok(().into())
1005
- }
1006
-
1007
- async fn two_la_wf_parallel(ctx: WfContext) -> WorkflowResult<()> {
1008
- tokio::join!(
1009
- ctx.local_activity(LocalActivityOptions {
1010
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1011
- input: ().as_json_payload().unwrap(),
1012
- ..Default::default()
1013
- }),
1014
- ctx.local_activity(LocalActivityOptions {
1015
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1016
- input: ().as_json_payload().unwrap(),
1017
- ..Default::default()
1018
- })
1019
- );
1020
- Ok(().into())
1021
- }
1022
-
1023
- #[rstest]
1024
- #[tokio::test]
1025
- async fn two_sequential_las(
1026
- #[values(true, false)] replay: bool,
1027
- #[values(true, false)] parallel: bool,
1028
- ) {
1029
- let t = canned_histories::two_local_activities_one_wft(parallel);
1030
- let mut mock_cfg = if replay {
1031
- MockPollCfg::from_resps(t, [ResponseType::AllHistory])
1032
- } else {
1033
- MockPollCfg::from_hist_builder(t)
1034
- };
1035
-
1036
- let mut aai = ActivationAssertionsInterceptor::default();
1037
- let first_act_ts_seconds: &'static _ = Box::leak(Box::new(AtomicI64::new(-1)));
1038
- aai.then(|a| {
1039
- first_act_ts_seconds.store(a.timestamp.as_ref().unwrap().seconds, Ordering::Relaxed)
1040
- });
1041
- // Verify LAs advance time (they take 1s as defined in the canned history)
1042
- aai.then(move |a| {
1043
- if !parallel {
1044
- assert_matches!(
1045
- a.jobs.as_slice(),
1046
- [WorkflowActivationJob {
1047
- variant: Some(workflow_activation_job::Variant::ResolveActivity(ra))
1048
- }] => assert_eq!(ra.seq, 1)
1049
- );
1050
- } else {
1051
- assert_matches!(
1052
- a.jobs.as_slice(),
1053
- [WorkflowActivationJob {
1054
- variant: Some(workflow_activation_job::Variant::ResolveActivity(ra))
1055
- }, WorkflowActivationJob {
1056
- variant: Some(workflow_activation_job::Variant::ResolveActivity(ra2))
1057
- }] => {assert_eq!(ra.seq, 1); assert_eq!(ra2.seq, 2)}
1058
- );
1059
- }
1060
- if replay {
1061
- assert!(
1062
- a.timestamp.as_ref().unwrap().seconds
1063
- > first_act_ts_seconds.load(Ordering::Relaxed)
1064
- )
1065
- }
1066
- });
1067
- if !parallel {
1068
- aai.then(move |a| {
1069
- assert_matches!(
1070
- a.jobs.as_slice(),
1071
- [WorkflowActivationJob {
1072
- variant: Some(workflow_activation_job::Variant::ResolveActivity(ra))
1073
- }] => assert_eq!(ra.seq, 2)
1074
- );
1075
- if replay {
1076
- assert!(
1077
- a.timestamp.as_ref().unwrap().seconds
1078
- >= first_act_ts_seconds.load(Ordering::Relaxed) + 2
1079
- )
1080
- }
1081
- });
1082
- }
1083
-
1084
- mock_cfg.completion_asserts_from_expectations(|mut asserts| {
1085
- asserts.then(move |wft| {
1086
- let commands = &wft.commands;
1087
- if !replay {
1088
- assert_eq!(commands.len(), 3);
1089
- assert_eq!(commands[0].command_type(), CommandType::RecordMarker);
1090
- assert_eq!(commands[1].command_type(), CommandType::RecordMarker);
1091
- assert_matches!(
1092
- commands[2].command_type(),
1093
- CommandType::CompleteWorkflowExecution
1094
- );
1095
- } else {
1096
- assert_eq!(commands.len(), 1);
1097
- assert_matches!(
1098
- commands[0].command_type(),
1099
- CommandType::CompleteWorkflowExecution
1100
- );
1101
- }
1102
- });
1103
- });
1104
-
1105
- let mut worker = build_fake_sdk(mock_cfg);
1106
- worker.set_worker_interceptor(aai);
1107
- if parallel {
1108
- worker.register_wf(DEFAULT_WORKFLOW_TYPE, two_la_wf_parallel);
1109
- } else {
1110
- worker.register_wf(DEFAULT_WORKFLOW_TYPE, two_la_wf);
1111
- }
1112
- worker.register_activity(
1113
- DEFAULT_ACTIVITY_TYPE,
1114
- move |_ctx: ActContext, _: ()| async move { Ok("Resolved") },
1115
- );
1116
- worker.run().await.unwrap();
1117
- }
1118
-
1119
- async fn la_timer_la(ctx: WfContext) -> WorkflowResult<()> {
1120
- ctx.local_activity(LocalActivityOptions {
1121
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1122
- input: ().as_json_payload().unwrap(),
1123
- ..Default::default()
1124
- })
1125
- .await;
1126
- ctx.timer(Duration::from_secs(5)).await;
1127
- ctx.local_activity(LocalActivityOptions {
1128
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1129
- input: ().as_json_payload().unwrap(),
1130
- ..Default::default()
1131
- })
1132
- .await;
1133
- Ok(().into())
1134
- }
1135
-
1136
- #[rstest]
1137
- #[case::incremental(false)]
1138
- #[case::replay(true)]
1139
- #[tokio::test]
1140
- async fn las_separated_by_timer(#[case] replay: bool) {
1141
- let mut t = TestHistoryBuilder::default();
1142
- t.add_by_type(EventType::WorkflowExecutionStarted);
1143
- t.add_full_wf_task();
1144
- t.add_local_activity_result_marker(1, "1", b"hi".into());
1145
- let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
1146
- t.add_timer_fired(timer_started_event_id, "1".to_string());
1147
- t.add_full_wf_task();
1148
- t.add_local_activity_result_marker(2, "2", b"hi2".into());
1149
- t.add_workflow_task_scheduled_and_started();
1150
- let mut mock_cfg = if replay {
1151
- MockPollCfg::from_resps(t, [ResponseType::AllHistory])
1152
- } else {
1153
- MockPollCfg::from_hist_builder(t)
1154
- };
1155
-
1156
- let mut aai = ActivationAssertionsInterceptor::default();
1157
- aai.skip_one()
1158
- .then(|a| {
1159
- assert_matches!(
1160
- a.jobs.as_slice(),
1161
- [WorkflowActivationJob {
1162
- variant: Some(workflow_activation_job::Variant::ResolveActivity(ra))
1163
- }] => assert_eq!(ra.seq, 1)
1164
- );
1165
- })
1166
- .then(|a| {
1167
- assert_matches!(
1168
- a.jobs.as_slice(),
1169
- [WorkflowActivationJob {
1170
- variant: Some(workflow_activation_job::Variant::FireTimer(_))
1171
- }]
1172
- );
1173
- });
1174
-
1175
- mock_cfg.completion_asserts_from_expectations(|mut asserts| {
1176
- if replay {
1177
- asserts.then(|wft| {
1178
- assert_eq!(wft.commands.len(), 1);
1179
- assert_eq!(
1180
- wft.commands[0].command_type,
1181
- CommandType::CompleteWorkflowExecution as i32
1182
- );
1183
- });
1184
- } else {
1185
- asserts
1186
- .then(|wft| {
1187
- let commands = &wft.commands;
1188
- assert_eq!(commands.len(), 2);
1189
- assert_eq!(commands[0].command_type, CommandType::RecordMarker as i32);
1190
- assert_eq!(commands[1].command_type, CommandType::StartTimer as i32);
1191
- })
1192
- .then(|wft| {
1193
- let commands = &wft.commands;
1194
- assert_eq!(commands.len(), 2);
1195
- assert_eq!(commands[0].command_type, CommandType::RecordMarker as i32);
1196
- assert_eq!(
1197
- commands[1].command_type,
1198
- CommandType::CompleteWorkflowExecution as i32
1199
- );
1200
- });
1201
- }
1202
- });
1203
-
1204
- let mut worker = build_fake_sdk(mock_cfg);
1205
- worker.set_worker_interceptor(aai);
1206
- worker.register_wf(DEFAULT_WORKFLOW_TYPE, la_timer_la);
1207
- worker.register_activity(
1208
- DEFAULT_ACTIVITY_TYPE,
1209
- move |_ctx: ActContext, _: ()| async move { Ok("Resolved") },
1210
- );
1211
- worker.run().await.unwrap();
1212
- }
1213
-
1214
- #[tokio::test]
1215
- async fn one_la_heartbeating_wft_failure_still_executes() {
1216
- let mut t = TestHistoryBuilder::default();
1217
- t.add_by_type(EventType::WorkflowExecutionStarted);
1218
- // Heartbeats
1219
- t.add_full_wf_task();
1220
- // fails a wft for some reason
1221
- t.add_workflow_task_scheduled_and_started();
1222
- t.add_workflow_task_failed_with_failure(
1223
- WorkflowTaskFailedCause::NonDeterministicError,
1224
- Default::default(),
1225
- );
1226
- t.add_workflow_task_scheduled_and_started();
1227
-
1228
- let mut mock_cfg = MockPollCfg::from_hist_builder(t);
1229
- mock_cfg.completion_asserts_from_expectations(|mut asserts| {
1230
- asserts.then(move |wft| {
1231
- assert_eq!(wft.commands.len(), 2);
1232
- assert_eq!(wft.commands[0].command_type(), CommandType::RecordMarker);
1233
- assert_matches!(
1234
- wft.commands[1].command_type(),
1235
- CommandType::CompleteWorkflowExecution
1236
- );
1237
- });
1238
- });
1239
-
1240
- let mut worker = build_fake_sdk(mock_cfg);
1241
- worker.register_wf(DEFAULT_WORKFLOW_TYPE, la_wf);
1242
- worker.register_activity(
1243
- DEFAULT_ACTIVITY_TYPE,
1244
- move |_ctx: ActContext, _: ()| async move { Ok("Resolved") },
1245
- );
1246
- worker.run().await.unwrap();
1247
- }
1248
-
1249
- #[rstest]
1250
- #[tokio::test]
1251
- async fn immediate_cancel(
1252
- #[values(
1253
- ActivityCancellationType::WaitCancellationCompleted,
1254
- ActivityCancellationType::TryCancel,
1255
- ActivityCancellationType::Abandon
1256
- )]
1257
- cancel_type: ActivityCancellationType,
1258
- ) {
1259
- let mut t = TestHistoryBuilder::default();
1260
- t.add_by_type(EventType::WorkflowExecutionStarted);
1261
- t.add_full_wf_task();
1262
- t.add_workflow_execution_completed();
1263
-
1264
- let mut mock_cfg = MockPollCfg::from_hist_builder(t);
1265
- mock_cfg.completion_asserts_from_expectations(|mut asserts| {
1266
- asserts.then(|wft| {
1267
- assert_eq!(wft.commands.len(), 2);
1268
- // We record the cancel marker
1269
- assert_eq!(wft.commands[0].command_type(), CommandType::RecordMarker);
1270
- assert_matches!(
1271
- wft.commands[1].command_type(),
1272
- CommandType::CompleteWorkflowExecution
1273
- );
1274
- });
1275
- });
1276
-
1277
- let mut worker = build_fake_sdk(mock_cfg);
1278
- worker.register_wf(DEFAULT_WORKFLOW_TYPE, move |ctx: WfContext| async move {
1279
- let la = ctx.local_activity(LocalActivityOptions {
1280
- cancel_type,
1281
- ..Default::default()
1282
- });
1283
- la.cancel(&ctx);
1284
- la.await;
1285
- Ok(().into())
1286
- });
1287
- // Explicitly don't register an activity, since we shouldn't need to run one.
1288
- worker.run().await.unwrap();
1289
- }
1290
-
1291
- #[rstest]
1292
- #[case::incremental(false)]
1293
- #[case::replay(true)]
1294
- #[tokio::test]
1295
- async fn cancel_after_act_starts(
1296
- #[case] replay: bool,
1297
- #[values(
1298
- ActivityCancellationType::WaitCancellationCompleted,
1299
- ActivityCancellationType::TryCancel,
1300
- ActivityCancellationType::Abandon
1301
- )]
1302
- cancel_type: ActivityCancellationType,
1303
- ) {
1304
- let mut t = TestHistoryBuilder::default();
1305
- t.add_wfe_started_with_wft_timeout(Duration::from_millis(100));
1306
- t.add_full_wf_task();
1307
- let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
1308
- t.add_timer_fired(timer_started_event_id, "1".to_string());
1309
- t.add_full_wf_task();
1310
- // This extra workflow task serves to prevent looking ahead and pre-resolving during
1311
- // wait-cancel.
1312
- // TODO: including this on non wait-cancel seems to cause double-send of
1313
- // marker recorded cmd
1314
- if cancel_type == ActivityCancellationType::WaitCancellationCompleted {
1315
- t.add_full_wf_task();
1316
- }
1317
- if cancel_type != ActivityCancellationType::WaitCancellationCompleted {
1318
- // With non-wait cancels, the cancel is immediate
1319
- t.add_local_activity_cancel_marker(1, "1");
1320
- }
1321
- let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
1322
- if cancel_type == ActivityCancellationType::WaitCancellationCompleted {
1323
- // With wait cancels, the cancel marker is not recorded until activity reports.
1324
- t.add_local_activity_cancel_marker(1, "1");
1325
- }
1326
- t.add_timer_fired(timer_started_event_id, "2".to_string());
1327
- t.add_full_wf_task();
1328
- t.add_workflow_execution_completed();
1329
-
1330
- let mut mock_cfg = if replay {
1331
- MockPollCfg::from_resps(t, [ResponseType::AllHistory])
1332
- } else {
1333
- MockPollCfg::from_hist_builder(t)
1334
- };
1335
- let allow_cancel_barr = CancellationToken::new();
1336
- let allow_cancel_barr_clone = allow_cancel_barr.clone();
1337
-
1338
- if !replay {
1339
- mock_cfg.completion_asserts_from_expectations(|mut asserts| {
1340
- asserts
1341
- .then(move |wft| {
1342
- assert_eq!(wft.commands.len(), 1);
1343
- assert_eq!(wft.commands[0].command_type, CommandType::StartTimer as i32);
1344
- })
1345
- .then(move |wft| {
1346
- let commands = &wft.commands;
1347
- if cancel_type == ActivityCancellationType::WaitCancellationCompleted {
1348
- assert_eq!(commands.len(), 1);
1349
- assert_eq!(commands[0].command_type, CommandType::StartTimer as i32);
1350
- } else {
1351
- // Try-cancel/abandon immediately recordsmarker (when not replaying)
1352
- assert_eq!(commands.len(), 2);
1353
- assert_eq!(commands[0].command_type, CommandType::RecordMarker as i32);
1354
- assert_eq!(commands[1].command_type, CommandType::StartTimer as i32);
1355
- }
1356
- // Allow the wait-cancel to actually cancel
1357
- allow_cancel_barr.cancel();
1358
- })
1359
- .then(move |wft| {
1360
- let commands = &wft.commands;
1361
- if cancel_type == ActivityCancellationType::WaitCancellationCompleted {
1362
- assert_eq!(commands[0].command_type, CommandType::StartTimer as i32);
1363
- assert_eq!(commands[1].command_type, CommandType::RecordMarker as i32);
1364
- } else {
1365
- assert_eq!(
1366
- commands[0].command_type,
1367
- CommandType::CompleteWorkflowExecution as i32
1368
- );
1369
- }
1370
- });
1371
- });
1372
- }
1373
-
1374
- let mut worker = build_fake_sdk(mock_cfg);
1375
- worker.register_wf(DEFAULT_WORKFLOW_TYPE, move |ctx: WfContext| async move {
1376
- let la = ctx.local_activity(LocalActivityOptions {
1377
- cancel_type,
1378
- input: ().as_json_payload().unwrap(),
1379
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1380
- ..Default::default()
1381
- });
1382
- ctx.timer(Duration::from_secs(1)).await;
1383
- la.cancel(&ctx);
1384
- // This extra timer is here to ensure the presence of another WF task doesn't mess up
1385
- // resolving the LA with cancel on replay
1386
- ctx.timer(Duration::from_secs(1)).await;
1387
- let resolution = la.await;
1388
- assert!(resolution.cancelled());
1389
- let rfail = resolution.unwrap_failure();
1390
- assert_matches!(
1391
- rfail.failure_info,
1392
- Some(FailureInfo::ActivityFailureInfo(_))
1393
- );
1394
- assert_matches!(
1395
- rfail.cause.unwrap().failure_info,
1396
- Some(FailureInfo::CanceledFailureInfo(_))
1397
- );
1398
- Ok(().into())
1399
- });
1400
- worker.register_activity(DEFAULT_ACTIVITY_TYPE, move |ctx: ActContext, _: ()| {
1401
- let allow_cancel_barr_clone = allow_cancel_barr_clone.clone();
1402
- async move {
1403
- if cancel_type == ActivityCancellationType::WaitCancellationCompleted {
1404
- ctx.cancelled().await;
1405
- }
1406
- allow_cancel_barr_clone.cancelled().await;
1407
- Result::<(), _>::Err(ActivityError::cancelled())
1408
- }
1409
- });
1410
- worker.run().await.unwrap();
1411
- }
1412
- }
@@ -99,74 +99,3 @@ impl From<Created> for CommandIssued {
99
99
  Self {}
100
100
  }
101
101
  }
102
-
103
- #[cfg(test)]
104
- mod tests {
105
- use super::*;
106
- use crate::{
107
- replay::TestHistoryBuilder,
108
- test_help::{MockPollCfg, build_fake_sdk},
109
- };
110
- use temporal_sdk::WfContext;
111
- use temporal_sdk_core_protos::{
112
- DEFAULT_WORKFLOW_TYPE,
113
- temporal::api::{
114
- command::v1::{Command, command},
115
- common::v1::Payload,
116
- },
117
- };
118
-
119
- #[tokio::test]
120
- async fn workflow_modify_props() {
121
- let mut t = TestHistoryBuilder::default();
122
- t.add_by_type(EventType::WorkflowExecutionStarted);
123
- t.add_full_wf_task();
124
- t.add_workflow_execution_completed();
125
-
126
- let (k1, k2) = ("foo", "bar");
127
-
128
- let mut mock_cfg = MockPollCfg::from_hist_builder(t);
129
- mock_cfg.completion_asserts_from_expectations(|mut asserts| {
130
- asserts.then(|wft| {
131
- assert_matches!(
132
- wft.commands.as_slice(),
133
- [Command {
134
- attributes: Some(
135
- command::Attributes::ModifyWorkflowPropertiesCommandAttributes(msg)
136
- ),
137
- ..
138
- }, ..] => {
139
- let fields = &msg.upserted_memo.as_ref().unwrap().fields;
140
- let payload1 = fields.get(k1).unwrap();
141
- let payload2 = fields.get(k2).unwrap();
142
- assert_eq!(payload1.data[0], 0x01);
143
- assert_eq!(payload2.data[0], 0x02);
144
- assert_eq!(fields.len(), 2);
145
- }
146
- );
147
- });
148
- });
149
-
150
- let mut worker = build_fake_sdk(mock_cfg);
151
- worker.register_wf(DEFAULT_WORKFLOW_TYPE, move |ctx: WfContext| async move {
152
- ctx.upsert_memo([
153
- (
154
- String::from(k1),
155
- Payload {
156
- data: vec![0x01],
157
- ..Default::default()
158
- },
159
- ),
160
- (
161
- String::from(k2),
162
- Payload {
163
- data: vec![0x02],
164
- ..Default::default()
165
- },
166
- ),
167
- ]);
168
- Ok(().into())
169
- });
170
- worker.run().await.unwrap();
171
- }
172
- }