@temporalio/core-bridge 1.11.6 → 1.11.8

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 (191) hide show
  1. package/Cargo.lock +902 -468
  2. package/package.json +3 -3
  3. package/releases/aarch64-apple-darwin/index.node +0 -0
  4. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  5. package/releases/x86_64-apple-darwin/index.node +0 -0
  6. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  7. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  8. package/sdk-core/.cargo/config.toml +5 -0
  9. package/sdk-core/.github/workflows/per-pr.yml +59 -5
  10. package/sdk-core/Cargo.toml +3 -2
  11. package/sdk-core/client/Cargo.toml +3 -3
  12. package/sdk-core/client/src/lib.rs +154 -161
  13. package/sdk-core/client/src/metrics.rs +15 -8
  14. package/sdk-core/client/src/proxy.rs +1 -1
  15. package/sdk-core/client/src/raw.rs +176 -33
  16. package/sdk-core/client/src/retry.rs +102 -465
  17. package/sdk-core/client/src/worker_registry/mod.rs +2 -2
  18. package/sdk-core/client/src/workflow_handle/mod.rs +19 -1
  19. package/sdk-core/core/Cargo.toml +12 -14
  20. package/sdk-core/core/benches/workflow_replay.rs +1 -1
  21. package/sdk-core/core/src/abstractions.rs +2 -2
  22. package/sdk-core/core/src/core_tests/activity_tasks.rs +99 -46
  23. package/sdk-core/core/src/core_tests/child_workflows.rs +68 -9
  24. package/sdk-core/core/src/core_tests/determinism.rs +2 -2
  25. package/sdk-core/core/src/core_tests/local_activities.rs +20 -33
  26. package/sdk-core/core/src/core_tests/mod.rs +7 -8
  27. package/sdk-core/core/src/core_tests/queries.rs +79 -79
  28. package/sdk-core/core/src/core_tests/replay_flag.rs +5 -5
  29. package/sdk-core/core/src/core_tests/updates.rs +6 -6
  30. package/sdk-core/core/src/core_tests/workers.rs +19 -22
  31. package/sdk-core/core/src/core_tests/workflow_cancels.rs +3 -3
  32. package/sdk-core/core/src/core_tests/workflow_tasks.rs +154 -106
  33. package/sdk-core/core/src/ephemeral_server/mod.rs +66 -10
  34. package/sdk-core/core/src/internal_flags.rs +103 -12
  35. package/sdk-core/core/src/lib.rs +21 -13
  36. package/sdk-core/core/src/pollers/mod.rs +200 -6
  37. package/sdk-core/core/src/pollers/poll_buffer.rs +32 -8
  38. package/sdk-core/core/src/protosext/mod.rs +7 -7
  39. package/sdk-core/core/src/protosext/protocol_messages.rs +2 -2
  40. package/sdk-core/core/src/replay/mod.rs +8 -9
  41. package/sdk-core/core/src/retry_logic.rs +8 -6
  42. package/sdk-core/core/src/telemetry/log_export.rs +4 -4
  43. package/sdk-core/core/src/telemetry/metrics.rs +111 -25
  44. package/sdk-core/core/src/telemetry/mod.rs +11 -4
  45. package/sdk-core/core/src/telemetry/otel.rs +108 -144
  46. package/sdk-core/core/src/telemetry/prometheus_server.rs +1 -4
  47. package/sdk-core/core/src/test_help/mod.rs +27 -21
  48. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +7 -5
  49. package/sdk-core/core/src/worker/activities/local_activities.rs +9 -9
  50. package/sdk-core/core/src/worker/activities.rs +34 -46
  51. package/sdk-core/core/src/worker/client/mocks.rs +24 -2
  52. package/sdk-core/core/src/worker/client.rs +169 -33
  53. package/sdk-core/core/src/worker/mod.rs +132 -56
  54. package/sdk-core/core/src/worker/nexus.rs +410 -0
  55. package/sdk-core/core/src/worker/tuner/resource_based.rs +27 -5
  56. package/sdk-core/core/src/worker/tuner.rs +29 -2
  57. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +8 -3
  58. package/sdk-core/core/src/worker/workflow/history_update.rs +5 -8
  59. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +83 -87
  60. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +38 -38
  61. package/sdk-core/core/src/worker/workflow/machines/cancel_nexus_op_state_machine.rs +117 -0
  62. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +8 -18
  63. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +114 -108
  64. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +16 -31
  65. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -14
  66. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +8 -15
  67. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +34 -75
  68. package/sdk-core/core/src/worker/workflow/machines/mod.rs +26 -48
  69. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +10 -17
  70. package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +543 -0
  71. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +22 -31
  72. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +53 -51
  73. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +40 -45
  74. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  75. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +8 -10
  76. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +24 -30
  77. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +182 -116
  78. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +4 -8
  79. package/sdk-core/core/src/worker/workflow/managed_run.rs +75 -45
  80. package/sdk-core/core/src/worker/workflow/mod.rs +104 -55
  81. package/sdk-core/core/src/worker/workflow/run_cache.rs +23 -4
  82. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +4 -4
  83. package/sdk-core/core/src/worker/workflow/wft_poller.rs +3 -3
  84. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +32 -13
  85. package/sdk-core/core-api/Cargo.toml +2 -3
  86. package/sdk-core/core-api/src/errors.rs +22 -20
  87. package/sdk-core/core-api/src/lib.rs +24 -5
  88. package/sdk-core/core-api/src/telemetry/metrics.rs +27 -1
  89. package/sdk-core/core-api/src/telemetry.rs +37 -3
  90. package/sdk-core/core-api/src/worker.rs +36 -3
  91. package/sdk-core/docker/docker-compose-ci.yaml +25 -0
  92. package/sdk-core/etc/otel-collector-ci.yaml +36 -0
  93. package/sdk-core/etc/otel-collector-config.yaml +3 -3
  94. package/sdk-core/etc/prometheus.yaml +1 -1
  95. package/sdk-core/fsm/Cargo.toml +1 -1
  96. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
  97. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +3 -4
  98. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  99. package/sdk-core/fsm/rustfsm_trait/Cargo.toml +1 -1
  100. package/sdk-core/sdk/Cargo.toml +1 -2
  101. package/sdk-core/sdk/src/activity_context.rs +1 -1
  102. package/sdk-core/sdk/src/interceptors.rs +1 -1
  103. package/sdk-core/sdk/src/lib.rs +126 -54
  104. package/sdk-core/sdk/src/workflow_context/options.rs +184 -74
  105. package/sdk-core/sdk/src/workflow_context.rs +193 -79
  106. package/sdk-core/sdk/src/workflow_future.rs +151 -131
  107. package/sdk-core/sdk-core-protos/Cargo.toml +3 -4
  108. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -1
  109. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/account/v1/message.proto +46 -0
  110. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +254 -5
  111. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +108 -2
  112. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +94 -15
  113. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +102 -4
  114. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/nexus/v1/message.proto +84 -0
  115. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +25 -10
  116. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +14 -1
  117. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/resource/v1/message.proto +25 -0
  118. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/sink/v1/message.proto +41 -0
  119. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/usage/v1/message.proto +59 -0
  120. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +2 -0
  121. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +135 -0
  122. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/push-to-buf.yml +20 -0
  123. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-delete-release.yml +13 -0
  124. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-publish-release.yml +13 -0
  125. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +13 -21
  126. package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +2 -2
  127. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +1 -0
  128. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +3386 -1047
  129. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +3529 -1144
  130. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +39 -1
  131. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +6 -0
  132. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +39 -1
  133. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +252 -0
  134. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +1 -0
  135. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/common.proto +6 -0
  136. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/deployment.proto +96 -0
  137. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +2 -0
  138. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  139. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/nexus.proto +42 -0
  140. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -0
  141. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/workflow.proto +43 -2
  142. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/errordetails/v1/message.proto +13 -1
  143. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +14 -0
  144. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +70 -12
  145. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +12 -0
  146. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/query/v1/message.proto +9 -2
  147. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +46 -2
  148. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +206 -0
  149. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +482 -97
  150. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +230 -43
  151. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/core_interface.proto +6 -0
  152. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/nexus/nexus.proto +71 -0
  153. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +46 -2
  154. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +55 -9
  155. package/sdk-core/sdk-core-protos/src/history_builder.rs +5 -5
  156. package/sdk-core/sdk-core-protos/src/history_info.rs +5 -6
  157. package/sdk-core/sdk-core-protos/src/lib.rs +414 -34
  158. package/sdk-core/sdk-core-protos/src/task_token.rs +1 -1
  159. package/sdk-core/test-utils/Cargo.toml +3 -11
  160. package/sdk-core/test-utils/src/canned_histories.rs +1 -1
  161. package/sdk-core/test-utils/src/lib.rs +159 -85
  162. package/sdk-core/tests/fuzzy_workflow.rs +3 -3
  163. package/sdk-core/tests/heavy_tests.rs +3 -3
  164. package/sdk-core/tests/integ_tests/client_tests.rs +171 -20
  165. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +45 -39
  166. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +7 -6
  167. package/sdk-core/tests/integ_tests/metrics_tests.rs +492 -35
  168. package/sdk-core/tests/integ_tests/polling_tests.rs +7 -5
  169. package/sdk-core/tests/integ_tests/queries_tests.rs +14 -17
  170. package/sdk-core/tests/integ_tests/update_tests.rs +47 -44
  171. package/sdk-core/tests/integ_tests/visibility_tests.rs +4 -3
  172. package/sdk-core/tests/integ_tests/worker_tests.rs +5 -5
  173. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +15 -13
  174. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +28 -14
  175. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +7 -1
  176. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +57 -4
  177. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
  178. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +24 -18
  179. package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +506 -0
  180. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +1 -1
  181. package/sdk-core/tests/integ_tests/workflow_tests/priority.rs +104 -0
  182. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +34 -31
  183. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
  184. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -7
  185. package/sdk-core/tests/integ_tests/workflow_tests.rs +152 -116
  186. package/sdk-core/tests/main.rs +36 -6
  187. package/sdk-core/tests/runner.rs +30 -9
  188. package/src/conversions/slot_supplier_bridge.rs +4 -0
  189. package/src/conversions.rs +1 -0
  190. package/src/worker.rs +5 -7
  191. package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +0 -78
@@ -0,0 +1,104 @@
1
+ use std::time::Duration;
2
+ use temporal_client::{Priority, WorkflowClientTrait, WorkflowOptions};
3
+ use temporal_sdk::{ActContext, ActivityOptions, ChildWorkflowOptions, WfContext};
4
+ use temporal_sdk_core_protos::{
5
+ coresdk::AsJsonPayloadExt, temporal::api::history::v1::history_event::Attributes,
6
+ };
7
+ use temporal_sdk_core_test_utils::CoreWfStarter;
8
+
9
+ #[tokio::test]
10
+ async fn priority_values_sent_to_server() {
11
+ let mut starter = CoreWfStarter::new("priority-values-sent-to-server");
12
+ starter.workflow_options.priority = Some(Priority { priority_key: 1 });
13
+ let mut worker = starter.worker().await;
14
+ let child_type = "child-wf";
15
+
16
+ worker.register_wf(starter.get_task_queue(), move |ctx: WfContext| async move {
17
+ let child = ctx.child_workflow(ChildWorkflowOptions {
18
+ workflow_id: format!("{}-child", ctx.task_queue()),
19
+ workflow_type: child_type.to_owned(),
20
+ options: WorkflowOptions {
21
+ priority: Some(Priority { priority_key: 4 }),
22
+ ..Default::default()
23
+ },
24
+ ..Default::default()
25
+ });
26
+
27
+ let started = child
28
+ .start(&ctx)
29
+ .await
30
+ .into_started()
31
+ .expect("Child should start OK");
32
+ let activity = ctx.activity(ActivityOptions {
33
+ activity_type: "echo".to_owned(),
34
+ input: "hello".as_json_payload().unwrap(),
35
+ start_to_close_timeout: Some(Duration::from_secs(5)),
36
+ priority: Some(Priority { priority_key: 5 }),
37
+ ..Default::default()
38
+ });
39
+ started.result().await;
40
+ activity.await;
41
+ Ok(().into())
42
+ });
43
+ worker.register_wf(child_type.to_owned(), |_ctx: WfContext| async move {
44
+ Ok(().into())
45
+ });
46
+ worker.register_activity("echo", |_ctx: ActContext, echo_me: String| async move {
47
+ Ok(echo_me)
48
+ });
49
+
50
+ starter
51
+ .start_with_worker(starter.get_task_queue(), &mut worker)
52
+ .await;
53
+ worker.run_until_done().await.unwrap();
54
+
55
+ let client = starter.get_client().await;
56
+ let history = client
57
+ .get_workflow_execution_history(starter.get_task_queue().to_owned(), None, vec![])
58
+ .await
59
+ .unwrap()
60
+ .history
61
+ .unwrap();
62
+ let workflow_init_event = history
63
+ .events
64
+ .iter()
65
+ .find_map(|e| {
66
+ if let Attributes::WorkflowExecutionStartedEventAttributes(e) =
67
+ e.attributes.as_ref().unwrap()
68
+ {
69
+ Some(e)
70
+ } else {
71
+ None
72
+ }
73
+ })
74
+ .unwrap();
75
+ assert_eq!(workflow_init_event.priority.unwrap().priority_key, 1);
76
+ let child_init_event = history
77
+ .events
78
+ .iter()
79
+ .find_map(|e| {
80
+ if let Attributes::StartChildWorkflowExecutionInitiatedEventAttributes(e) =
81
+ e.attributes.as_ref().unwrap()
82
+ {
83
+ Some(e)
84
+ } else {
85
+ None
86
+ }
87
+ })
88
+ .unwrap();
89
+ assert_eq!(child_init_event.priority.unwrap().priority_key, 4);
90
+ let activity_sched_event = history
91
+ .events
92
+ .iter()
93
+ .find_map(|e| {
94
+ if let Attributes::ActivityTaskScheduledEventAttributes(e) =
95
+ e.attributes.as_ref().unwrap()
96
+ {
97
+ Some(e)
98
+ } else {
99
+ None
100
+ }
101
+ })
102
+ .unwrap();
103
+ assert_eq!(activity_sched_event.priority.unwrap().priority_key, 5);
104
+ }
@@ -2,21 +2,21 @@ use crate::integ_tests::workflow_tests::patches::changes_wf;
2
2
  use assert_matches::assert_matches;
3
3
  use parking_lot::Mutex;
4
4
  use std::{collections::HashSet, sync::Arc, time::Duration};
5
- use temporal_sdk::{interceptors::WorkerInterceptor, WfContext, Worker, WorkflowFunction};
5
+ use temporal_sdk::{WfContext, Worker, WorkflowFunction, interceptors::WorkerInterceptor};
6
6
  use temporal_sdk_core::replay::{HistoryFeeder, HistoryForReplay};
7
- use temporal_sdk_core_api::errors::{PollActivityError, PollWfError};
7
+ use temporal_sdk_core_api::errors::PollError;
8
8
  use temporal_sdk_core_protos::{
9
+ DEFAULT_WORKFLOW_TYPE, TestHistoryBuilder,
9
10
  coresdk::{
10
11
  workflow_activation::remove_from_cache::EvictionReason,
11
12
  workflow_commands::{ScheduleActivity, StartTimer},
12
13
  workflow_completion::WorkflowActivationCompletion,
13
14
  },
14
15
  temporal::api::enums::v1::EventType,
15
- TestHistoryBuilder, DEFAULT_WORKFLOW_TYPE,
16
16
  };
17
17
  use temporal_sdk_core_test_utils::{
18
- canned_histories, history_from_proto_binary, init_core_replay_preloaded, replay_sdk_worker,
19
- replay_sdk_worker_stream, WorkerTestHelpers,
18
+ WorkerTestHelpers, canned_histories, history_from_proto_binary, init_core_replay_preloaded,
19
+ replay_sdk_worker, replay_sdk_worker_stream,
20
20
  };
21
21
  use tokio::join;
22
22
 
@@ -39,21 +39,20 @@ async fn timer_workflow_replay() {
39
39
  let task = core.poll_workflow_activation().await.unwrap();
40
40
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
41
41
  task.run_id,
42
- vec![StartTimer {
43
- seq: 0,
44
- start_to_fire_timeout: Some(prost_dur!(from_secs(1))),
45
- }
46
- .into()],
42
+ vec![
43
+ StartTimer {
44
+ seq: 0,
45
+ start_to_fire_timeout: Some(prost_dur!(from_secs(1))),
46
+ }
47
+ .into(),
48
+ ],
47
49
  ))
48
50
  .await
49
51
  .unwrap();
50
52
  let task = core.poll_workflow_activation().await.unwrap();
51
53
  // Verify that an in-progress poll is interrupted by completion finishing processing history
52
54
  let act_poll_fut = async {
53
- assert_matches!(
54
- core.poll_activity_task().await,
55
- Err(PollActivityError::ShutDown)
56
- );
55
+ assert_matches!(core.poll_activity_task().await, Err(PollError::ShutDown));
57
56
  };
58
57
  let poll_fut = async {
59
58
  let evict_task = core
@@ -66,7 +65,7 @@ async fn timer_workflow_replay() {
66
65
  .unwrap();
67
66
  assert_matches!(
68
67
  core.poll_workflow_activation().await,
69
- Err(PollWfError::ShutDown)
68
+ Err(PollError::ShutDown)
70
69
  );
71
70
  };
72
71
  let complete_fut = async {
@@ -77,7 +76,7 @@ async fn timer_workflow_replay() {
77
76
  // Subsequent polls should still return shutdown
78
77
  assert_matches!(
79
78
  core.poll_workflow_activation().await,
80
- Err(PollWfError::ShutDown)
79
+ Err(PollError::ShutDown)
81
80
  );
82
81
 
83
82
  core.shutdown().await;
@@ -97,13 +96,15 @@ async fn workflow_nondeterministic_replay() {
97
96
  let task = core.poll_workflow_activation().await.unwrap();
98
97
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
99
98
  task.run_id,
100
- vec![ScheduleActivity {
101
- seq: 0,
102
- activity_id: "0".to_string(),
103
- activity_type: "fake_act".to_string(),
104
- ..Default::default()
105
- }
106
- .into()],
99
+ vec![
100
+ ScheduleActivity {
101
+ seq: 0,
102
+ activity_id: "0".to_string(),
103
+ activity_type: "fake_act".to_string(),
104
+ ..Default::default()
105
+ }
106
+ .into(),
107
+ ],
107
108
  ))
108
109
  .await
109
110
  .unwrap();
@@ -117,7 +118,7 @@ async fn workflow_nondeterministic_replay() {
117
118
  core.shutdown().await;
118
119
  assert_matches!(
119
120
  core.poll_workflow_activation().await,
120
- Err(PollWfError::ShutDown)
121
+ Err(PollError::ShutDown)
121
122
  );
122
123
  }
123
124
 
@@ -264,13 +265,15 @@ async fn replay_ends_with_empty_wft() {
264
265
  let task = core.poll_workflow_activation().await.unwrap();
265
266
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
266
267
  task.run_id,
267
- vec![ScheduleActivity {
268
- seq: 1,
269
- activity_id: "1".to_string(),
270
- activity_type: "say_hello".to_string(),
271
- ..Default::default()
272
- }
273
- .into()],
268
+ vec![
269
+ ScheduleActivity {
270
+ seq: 1,
271
+ activity_id: "1".to_string(),
272
+ activity_type: "say_hello".to_string(),
273
+ ..Default::default()
274
+ }
275
+ .into(),
276
+ ],
274
277
  ))
275
278
  .await
276
279
  .unwrap();
@@ -2,8 +2,8 @@ use crate::integ_tests::activity_functions::echo;
2
2
  use futures_util::StreamExt;
3
3
  use std::{
4
4
  sync::{
5
- atomic::{AtomicBool, AtomicU64, Ordering},
6
5
  Arc,
6
+ atomic::{AtomicBool, AtomicU64, Ordering},
7
7
  },
8
8
  time::Duration,
9
9
  };
@@ -6,8 +6,8 @@ use temporal_sdk_core_protos::coresdk::{
6
6
  workflow_completion::WorkflowActivationCompletion,
7
7
  };
8
8
  use temporal_sdk_core_test_utils::{
9
- drain_pollers_and_shutdown, init_core_and_create_wf, start_timer_cmd, CoreWfStarter,
10
- WorkerTestHelpers,
9
+ CoreWfStarter, WorkerTestHelpers, drain_pollers_and_shutdown, init_core_and_create_wf,
10
+ start_timer_cmd,
11
11
  };
12
12
 
13
13
  pub(crate) async fn timer_wf(command_sink: WfContext) -> WorkflowResult<()> {
@@ -35,16 +35,19 @@ async fn timer_workflow_manual() {
35
35
  let task = core.poll_workflow_activation().await.unwrap();
36
36
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
37
37
  task.run_id,
38
- vec![StartTimer {
39
- seq: 0,
40
- start_to_fire_timeout: Some(prost_dur!(from_secs(1))),
41
- }
42
- .into()],
38
+ vec![
39
+ StartTimer {
40
+ seq: 0,
41
+ start_to_fire_timeout: Some(prost_dur!(from_secs(1))),
42
+ }
43
+ .into(),
44
+ ],
43
45
  ))
44
46
  .await
45
47
  .unwrap();
46
48
  let task = core.poll_workflow_activation().await.unwrap();
47
49
  core.complete_execution(&task.run_id).await;
50
+ core.handle_eviction().await;
48
51
  drain_pollers_and_shutdown(&core).await;
49
52
  }
50
53
 
@@ -8,7 +8,9 @@ mod determinism;
8
8
  mod eager;
9
9
  mod local_activities;
10
10
  mod modify_wf_properties;
11
+ mod nexus;
11
12
  mod patches;
13
+ mod priority;
12
14
  mod replay;
13
15
  mod resets;
14
16
  mod signals;
@@ -18,32 +20,27 @@ mod upsert_search_attrs;
18
20
 
19
21
  use crate::integ_tests::{activity_functions::echo, metrics_tests};
20
22
  use assert_matches::assert_matches;
21
- use futures_channel::mpsc::UnboundedReceiver;
22
- use futures_util::{future, SinkExt, StreamExt};
23
23
  use std::{
24
24
  collections::{HashMap, HashSet},
25
- sync::{
26
- atomic::{AtomicUsize, Ordering},
27
- Arc,
28
- },
25
+ sync::atomic::{AtomicUsize, Ordering},
29
26
  time::Duration,
30
27
  };
31
- use temporal_client::{WorkflowClientTrait, WorkflowOptions};
32
- use temporal_sdk::{interceptors::WorkerInterceptor, ActivityOptions, WfContext, WorkflowResult};
33
- use temporal_sdk_core::{replay::HistoryForReplay, CoreRuntime};
34
- use temporal_sdk_core_api::{
35
- errors::{PollWfError, WorkflowErrorType},
36
- Worker,
28
+ use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowExecutionResult, WorkflowOptions};
29
+ use temporal_sdk::{
30
+ ActivityOptions, LocalActivityOptions, WfContext, WorkflowResult,
31
+ interceptors::WorkerInterceptor,
37
32
  };
33
+ use temporal_sdk_core::{CoreRuntime, replay::HistoryForReplay};
34
+ use temporal_sdk_core_api::errors::{PollError, WorkflowErrorType};
38
35
  use temporal_sdk_core_protos::{
39
36
  coresdk::{
37
+ ActivityTaskCompletion, AsJsonPayloadExt, IntoCompletion,
40
38
  activity_result::ActivityExecutionResult,
41
- workflow_activation::{workflow_activation_job, WorkflowActivation, WorkflowActivationJob},
39
+ workflow_activation::{WorkflowActivationJob, workflow_activation_job},
42
40
  workflow_commands::{
43
41
  ActivityCancellationType, FailWorkflowExecution, QueryResult, QuerySuccess, StartTimer,
44
42
  },
45
43
  workflow_completion::WorkflowActivationCompletion,
46
- ActivityTaskCompletion, AsJsonPayloadExt, IntoCompletion,
47
44
  },
48
45
  temporal::api::{
49
46
  enums::v1::EventType, failure::v1::Failure, history::v1::history_event,
@@ -51,68 +48,36 @@ use temporal_sdk_core_protos::{
51
48
  },
52
49
  };
53
50
  use temporal_sdk_core_test_utils::{
54
- drain_pollers_and_shutdown, history_from_proto_binary, init_core_and_create_wf,
55
- init_core_replay_preloaded, schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
51
+ CoreWfStarter, WorkerTestHelpers, drain_pollers_and_shutdown, history_from_proto_binary,
52
+ init_core_and_create_wf, init_core_replay_preloaded, schedule_activity_cmd,
56
53
  };
57
- use tokio::{join, time::sleep};
54
+ use tokio::{join, sync::Notify, time::sleep};
58
55
  use uuid::Uuid;
59
-
60
56
  // TODO: We should get expected histories for these tests and confirm that the history at the end
61
57
  // matches.
62
58
 
63
59
  #[tokio::test]
64
60
  async fn parallel_workflows_same_queue() {
65
- let mut starter = CoreWfStarter::new("parallel_workflows_same_queue");
66
- let core = starter.get_worker().await;
67
- let num_workflows = 25usize;
68
-
69
- let run_ids: Vec<_> = future::join_all(
70
- (0..num_workflows).map(|i| starter.start_wf_with_id(format!("wf-id-{i}"))),
71
- )
72
- .await;
73
-
74
- let mut send_chans = HashMap::new();
75
- async fn wf_task(
76
- worker: Arc<dyn Worker>,
77
- mut task_chan: UnboundedReceiver<WorkflowActivation>,
78
- ) {
79
- let task = task_chan.next().await.unwrap();
80
- assert_matches!(
81
- task.jobs.as_slice(),
82
- [WorkflowActivationJob {
83
- variant: Some(workflow_activation_job::Variant::InitializeWorkflow(_)),
84
- }]
85
- );
86
- worker
87
- .complete_timer(&task.run_id, 1, Duration::from_secs(1))
88
- .await;
89
- let task = task_chan.next().await.unwrap();
90
- worker.complete_execution(&task.run_id).await;
91
- }
92
-
93
- let handles: Vec<_> = run_ids
94
- .iter()
95
- .map(|run_id| {
96
- let (tx, rx) = futures_channel::mpsc::unbounded();
97
- send_chans.insert(run_id.clone(), tx);
98
- tokio::spawn(wf_task(core.clone(), rx))
99
- })
100
- .collect();
101
-
102
- for _ in 0..num_workflows * 2 {
103
- let task = core.poll_workflow_activation().await.unwrap();
104
- send_chans
105
- .get(&task.run_id)
106
- .unwrap()
107
- .send(task)
108
- .await
109
- .unwrap();
110
- }
61
+ let wf_name = "parallel_workflows_same_queue";
62
+ let mut starter = CoreWfStarter::new(wf_name);
63
+ starter.worker_config.no_remote_activities(true);
64
+ let mut core = starter.worker().await;
111
65
 
112
- for handle in handles {
113
- handle.await.unwrap()
66
+ core.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
67
+ ctx.timer(Duration::from_secs(1)).await;
68
+ Ok(().into())
69
+ });
70
+ for i in 0..25 {
71
+ core.submit_wf(
72
+ format!("{}-{}", wf_name, i),
73
+ wf_name,
74
+ vec![],
75
+ starter.workflow_options.clone(),
76
+ )
77
+ .await
78
+ .unwrap();
114
79
  }
115
- drain_pollers_and_shutdown(&core).await;
80
+ core.run_until_done().await.unwrap();
116
81
  }
117
82
 
118
83
  static RUN_CT: AtomicUsize = AtomicUsize::new(0);
@@ -180,14 +145,14 @@ async fn shutdown_aborts_actively_blocked_poll() {
180
145
  });
181
146
  assert_matches!(
182
147
  core.poll_workflow_activation().await.unwrap_err(),
183
- PollWfError::ShutDown
148
+ PollError::ShutDown
184
149
  );
185
150
  handle.await.unwrap();
186
151
  // Ensure double-shutdown doesn't explode
187
152
  core.shutdown().await;
188
153
  assert_matches!(
189
154
  core.poll_workflow_activation().await.unwrap_err(),
190
- PollWfError::ShutDown
155
+ PollError::ShutDown
191
156
  );
192
157
  }
193
158
 
@@ -230,26 +195,19 @@ async fn fail_wf_task(#[values(true, false)] replay: bool) {
230
195
 
231
196
  // The server will want to retry the task. This time we finish the workflow -- but we need
232
197
  // to poll a couple of times as there will be more than one required workflow activation.
233
- let task = core.poll_workflow_activation().await.unwrap();
234
- // The first poll response will tell us to evict
235
- assert_matches!(
236
- task.jobs.as_slice(),
237
- [WorkflowActivationJob {
238
- variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
239
- }]
240
- );
241
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
242
- .await
243
- .unwrap();
198
+ // The first poll response will tell us to evict.
199
+ core.handle_eviction().await;
244
200
 
245
201
  let task = core.poll_workflow_activation().await.unwrap();
246
202
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
247
203
  task.run_id,
248
- vec![StartTimer {
249
- seq: 0,
250
- start_to_fire_timeout: Some(prost_dur!(from_millis(200))),
251
- }
252
- .into()],
204
+ vec![
205
+ StartTimer {
206
+ seq: 0,
207
+ start_to_fire_timeout: Some(prost_dur!(from_millis(200))),
208
+ }
209
+ .into(),
210
+ ],
253
211
  ))
254
212
  .await
255
213
  .unwrap();
@@ -269,10 +227,12 @@ async fn fail_workflow_execution() {
269
227
  let task = core.poll_workflow_activation().await.unwrap();
270
228
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
271
229
  task.run_id,
272
- vec![FailWorkflowExecution {
273
- failure: Some(Failure::application_failure("I'm ded".to_string(), false)),
274
- }
275
- .into()],
230
+ vec![
231
+ FailWorkflowExecution {
232
+ failure: Some(Failure::application_failure("I'm ded".to_string(), false)),
233
+ }
234
+ .into(),
235
+ ],
276
236
  ))
277
237
  .await
278
238
  .unwrap();
@@ -369,11 +329,13 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
369
329
  // Task is completed with a timer
370
330
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
371
331
  res.run_id,
372
- vec![StartTimer {
373
- seq: 0,
374
- start_to_fire_timeout: Some(prost_dur!(from_millis(10))),
375
- }
376
- .into()],
332
+ vec![
333
+ StartTimer {
334
+ seq: 0,
335
+ start_to_fire_timeout: Some(prost_dur!(from_millis(10))),
336
+ }
337
+ .into(),
338
+ ],
377
339
  ))
378
340
  .await
379
341
  .unwrap();
@@ -408,18 +370,8 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
408
370
  // Send completion - not having seen a poll response with a signal in it yet (unhandled
409
371
  // command error will be logged as a warning and an eviction will be issued)
410
372
  core.complete_execution(&run_id).await;
411
-
412
373
  // We should be told to evict
413
- let res = core.poll_workflow_activation().await.unwrap();
414
- assert_matches!(
415
- res.jobs.as_slice(),
416
- [WorkflowActivationJob {
417
- variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
418
- }]
419
- );
420
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(res.run_id))
421
- .await
422
- .unwrap();
374
+ core.handle_eviction().await;
423
375
  // Loop to the top to handle wf from the beginning
424
376
  continue;
425
377
  }
@@ -515,16 +467,7 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
515
467
  .await
516
468
  .unwrap();
517
469
  // Now poll again, it will be an eviction b/c non-sticky mode.
518
- let wf_task = core.poll_workflow_activation().await.unwrap();
519
- assert_matches!(
520
- wf_task.jobs.as_slice(),
521
- [WorkflowActivationJob {
522
- variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
523
- }]
524
- );
525
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
526
- .await
527
- .unwrap();
470
+ core.handle_eviction().await;
528
471
  // Start from the beginning
529
472
  poll_sched_act().await;
530
473
  let wf_task = core.poll_workflow_activation().await.unwrap();
@@ -753,7 +696,7 @@ async fn build_id_correct_in_wf_info() {
753
696
  async fn nondeterminism_errors_fail_workflow_when_configured_to(
754
697
  #[values(true, false)] whole_worker: bool,
755
698
  ) {
756
- let (telemopts, addr, _aborter) = metrics_tests::prom_metrics(false, false);
699
+ let (telemopts, addr, _aborter) = metrics_tests::prom_metrics(None);
757
700
  let rt = CoreRuntime::new_assume_tokio(telemopts).unwrap();
758
701
  let wf_name = "nondeterminism_errors_fail_workflow_when_configured_to";
759
702
  let mut starter = CoreWfStarter::new_with_runtime(wf_name, rt);
@@ -836,3 +779,96 @@ async fn nondeterminism_errors_fail_workflow_when_configured_to(
836
779
  );
837
780
  assert!(body.contains(&match_this));
838
781
  }
782
+
783
+ #[tokio::test]
784
+ async fn history_out_of_order_on_restart() {
785
+ let wf_name = "history_out_of_order_on_restart";
786
+ let mut starter = CoreWfStarter::new(wf_name);
787
+ starter
788
+ .worker_config
789
+ .workflow_failure_errors([WorkflowErrorType::Nondeterminism]);
790
+ let mut worker = starter.worker().await;
791
+ let mut starter2 = starter.clone_no_worker();
792
+ let mut worker2 = starter2.worker().await;
793
+
794
+ static HIT_SLEEP: Notify = Notify::const_new();
795
+
796
+ worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
797
+ ctx.local_activity(LocalActivityOptions {
798
+ activity_type: "echo".to_owned(),
799
+ input: "hi".as_json_payload().unwrap(),
800
+ start_to_close_timeout: Some(Duration::from_secs(5)),
801
+ ..Default::default()
802
+ })
803
+ .await;
804
+ ctx.activity(ActivityOptions {
805
+ activity_type: "echo".to_owned(),
806
+ input: "hi".as_json_payload().unwrap(),
807
+ start_to_close_timeout: Some(Duration::from_secs(5)),
808
+ ..Default::default()
809
+ })
810
+ .await;
811
+ // Interrupt this sleep on first go
812
+ HIT_SLEEP.notify_one();
813
+ ctx.timer(Duration::from_secs(5)).await;
814
+ Ok(().into())
815
+ });
816
+ worker.register_activity("echo", echo);
817
+
818
+ worker2.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
819
+ ctx.local_activity(LocalActivityOptions {
820
+ activity_type: "echo".to_owned(),
821
+ input: "hi".as_json_payload().unwrap(),
822
+ start_to_close_timeout: Some(Duration::from_secs(5)),
823
+ ..Default::default()
824
+ })
825
+ .await;
826
+ // Timer is added after restarting workflow
827
+ ctx.timer(Duration::from_secs(1)).await;
828
+ ctx.activity(ActivityOptions {
829
+ activity_type: "echo".to_owned(),
830
+ input: "hi".as_json_payload().unwrap(),
831
+ start_to_close_timeout: Some(Duration::from_secs(5)),
832
+ ..Default::default()
833
+ })
834
+ .await;
835
+ ctx.timer(Duration::from_secs(2)).await;
836
+ Ok(().into())
837
+ });
838
+ worker2.register_activity("echo", echo);
839
+ worker
840
+ .submit_wf(
841
+ wf_name.to_owned(),
842
+ wf_name.to_owned(),
843
+ vec![],
844
+ WorkflowOptions {
845
+ execution_timeout: Some(Duration::from_secs(20)),
846
+ ..Default::default()
847
+ },
848
+ )
849
+ .await
850
+ .unwrap();
851
+
852
+ let w1 = async {
853
+ worker.run_until_done().await.unwrap();
854
+ };
855
+ let w2 = async {
856
+ // wait to hit sleep
857
+ HIT_SLEEP.notified().await;
858
+ starter.shutdown().await;
859
+ // start new worker
860
+ worker2.expect_workflow_completion(wf_name, None);
861
+ worker2.run_until_done().await.unwrap();
862
+ };
863
+ join!(w1, w2);
864
+ // The workflow should fail with the nondeterminism error
865
+ let handle = starter
866
+ .get_client()
867
+ .await
868
+ .get_untyped_workflow_handle(wf_name, "");
869
+ let res = handle
870
+ .get_workflow_result(Default::default())
871
+ .await
872
+ .unwrap();
873
+ assert_matches!(res, WorkflowExecutionResult::Failed(_));
874
+ }