@temporalio/core-bridge 1.14.2-canary-release-testing.0 → 1.16.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.
Files changed (233) hide show
  1. package/Cargo.lock +794 -650
  2. package/bridge-macros/src/derive_tryintojs.rs +40 -0
  3. package/lib/native.d.ts +24 -3
  4. package/package.json +4 -4
  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/.github/workflows/per-pr.yml +6 -6
  11. package/sdk-core/AGENTS.md +42 -31
  12. package/sdk-core/Cargo.toml +4 -1
  13. package/sdk-core/README.md +19 -13
  14. package/sdk-core/crates/client/Cargo.toml +4 -0
  15. package/sdk-core/crates/client/README.md +139 -0
  16. package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
  17. package/sdk-core/crates/client/src/callback_based.rs +7 -0
  18. package/sdk-core/crates/client/src/errors.rs +294 -0
  19. package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +370 -159
  20. package/sdk-core/crates/client/src/lib.rs +920 -1326
  21. package/sdk-core/crates/client/src/metrics.rs +24 -33
  22. package/sdk-core/crates/client/src/options_structs.rs +457 -0
  23. package/sdk-core/crates/client/src/replaceable.rs +5 -4
  24. package/sdk-core/crates/client/src/request_extensions.rs +8 -9
  25. package/sdk-core/crates/client/src/retry.rs +99 -54
  26. package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +104 -29
  27. package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
  28. package/sdk-core/crates/common/Cargo.toml +62 -3
  29. package/sdk-core/crates/common/build.rs +742 -12
  30. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
  31. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/create-release.yml +0 -5
  32. package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
  33. package/sdk-core/crates/common/protos/api_upstream/README.md +8 -0
  34. package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
  35. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +3329 -2647
  36. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +2734 -708
  37. package/sdk-core/crates/common/protos/api_upstream/temporal/api/activity/v1/message.proto +155 -3
  38. package/sdk-core/crates/common/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
  39. package/sdk-core/crates/common/protos/api_upstream/temporal/api/common/v1/message.proto +8 -1
  40. package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +27 -1
  41. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/activity.proto +81 -0
  42. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/event_type.proto +4 -0
  43. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +4 -0
  44. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +15 -0
  45. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +63 -15
  46. package/sdk-core/crates/common/protos/api_upstream/temporal/api/errordetails/v1/message.proto +8 -0
  47. package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
  48. package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +111 -17
  49. package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +21 -0
  50. package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +20 -1
  51. package/sdk-core/crates/common/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +4 -0
  52. package/sdk-core/crates/common/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
  53. package/sdk-core/crates/common/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -0
  54. package/sdk-core/crates/common/protos/api_upstream/temporal/api/worker/v1/message.proto +4 -7
  55. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflow/v1/message.proto +80 -22
  56. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +347 -23
  57. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +242 -43
  58. package/sdk-core/crates/common/protos/local/temporal/sdk/core/core_interface.proto +15 -0
  59. package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +9 -2
  60. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +8 -0
  61. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +22 -5
  62. package/sdk-core/crates/common/src/activity_definition.rs +20 -0
  63. package/sdk-core/crates/common/src/data_converters.rs +770 -0
  64. package/sdk-core/crates/common/src/envconfig.rs +5 -0
  65. package/sdk-core/crates/common/src/lib.rs +15 -211
  66. package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
  67. package/sdk-core/crates/common/src/priority.rs +110 -0
  68. package/sdk-core/crates/common/src/protos/canned_histories.rs +19 -0
  69. package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
  70. package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
  71. package/sdk-core/crates/common/src/protos/mod.rs +134 -27
  72. package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
  73. package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
  74. package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +11 -16
  75. package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
  76. package/sdk-core/crates/common/src/telemetry/metrics.rs +272 -225
  77. package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
  78. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
  79. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
  80. package/sdk-core/crates/common/src/telemetry.rs +278 -19
  81. package/sdk-core/crates/common/src/worker.rs +68 -636
  82. package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
  83. package/sdk-core/crates/macros/Cargo.toml +5 -1
  84. package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
  85. package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
  86. package/sdk-core/crates/macros/src/lib.rs +138 -512
  87. package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
  88. package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
  89. package/sdk-core/crates/sdk/Cargo.toml +19 -6
  90. package/sdk-core/crates/sdk/README.md +415 -0
  91. package/sdk-core/crates/sdk/src/activities.rs +417 -0
  92. package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
  93. package/sdk-core/crates/sdk/src/lib.rs +759 -442
  94. package/sdk-core/crates/sdk/src/workflow_context/options.rs +64 -35
  95. package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
  96. package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
  97. package/sdk-core/crates/sdk/src/workflows.rs +711 -0
  98. package/sdk-core/crates/sdk-core/Cargo.toml +59 -65
  99. package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +45 -54
  100. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
  101. package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
  102. package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
  103. package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +22 -21
  104. package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
  105. package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
  106. package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
  107. package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +647 -27
  108. package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +46 -41
  109. package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +13 -16
  110. package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
  111. package/sdk-core/crates/sdk-core/src/lib.rs +60 -123
  112. package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
  113. package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +411 -32
  114. package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
  115. package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
  116. package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +183 -198
  117. package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -281
  118. package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +35 -16
  119. package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
  120. package/sdk-core/crates/sdk-core/src/worker/activities/activity_heartbeat_manager.rs +1 -0
  121. package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
  122. package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
  123. package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +11 -5
  124. package/sdk-core/crates/sdk-core/src/worker/client.rs +104 -86
  125. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +10 -14
  126. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1175 -241
  127. package/sdk-core/crates/sdk-core/src/worker/nexus.rs +150 -23
  128. package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
  129. package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
  130. package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +25 -27
  131. package/sdk-core/crates/sdk-core/src/worker/tuner.rs +64 -44
  132. package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
  133. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/patch_state_machine.rs +5 -8
  134. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
  135. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +28 -4
  136. package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +20 -41
  137. package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +50 -9
  138. package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
  139. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
  140. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
  141. package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
  142. package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
  143. package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
  144. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
  145. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
  146. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
  147. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
  148. package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
  149. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
  150. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
  151. package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
  152. package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
  153. package/sdk-core/crates/sdk-core/tests/common/mod.rs +281 -236
  154. package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
  155. package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +9 -14
  156. package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -66
  157. package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +306 -268
  158. package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
  159. package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
  160. package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
  161. package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +37 -38
  162. package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +49 -40
  163. package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +447 -300
  164. package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
  165. package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +157 -157
  166. package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
  167. package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -463
  168. package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
  169. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +389 -265
  170. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +250 -185
  171. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -49
  172. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
  173. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +437 -327
  174. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -58
  175. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -30
  176. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -251
  177. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
  178. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +110 -46
  179. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -149
  180. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -32
  181. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1040
  182. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -43
  183. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +402 -245
  184. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +343 -207
  185. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
  186. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
  187. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +155 -140
  188. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -113
  189. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -44
  190. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -48
  191. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -56
  192. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +365 -242
  193. package/sdk-core/crates/sdk-core/tests/main.rs +22 -16
  194. package/sdk-core/crates/sdk-core/tests/manual_tests.rs +233 -187
  195. package/sdk-core/crates/sdk-core/tests/runner.rs +4 -6
  196. package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +73 -27
  197. package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
  198. package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
  199. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
  200. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
  201. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
  202. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
  203. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
  204. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
  205. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
  206. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
  207. package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +8 -1
  208. package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +37 -26
  209. package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +180 -87
  210. package/sdk-core/crates/sdk-core-c-bridge/src/lib.rs +89 -5
  211. package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +10 -16
  212. package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +59 -67
  213. package/sdk-core/crates/sdk-core-c-bridge/src/testing.rs +10 -10
  214. package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +57 -22
  215. package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +108 -12
  216. package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +9 -52
  217. package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +74 -91
  218. package/sdk-core/rustfmt.toml +2 -1
  219. package/src/client.rs +206 -289
  220. package/src/helpers/try_into_js.rs +88 -2
  221. package/src/metrics.rs +277 -35
  222. package/src/runtime.rs +94 -45
  223. package/src/testing.rs +9 -16
  224. package/src/worker.rs +86 -68
  225. package/ts/native.ts +39 -3
  226. package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
  227. package/sdk-core/crates/common/src/errors.rs +0 -85
  228. package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
  229. package/sdk-core/crates/macros/LICENSE.txt +0 -21
  230. package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
  231. package/sdk-core/crates/sdk/src/app_data.rs +0 -37
  232. package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
  233. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
@@ -1,12 +1,17 @@
1
- use crate::common::{CoreWfStarter, WorkflowHandleExt, mock_sdk, mock_sdk_cfg};
1
+ use crate::common::{
2
+ CoreWfStarter, WorkflowHandleExt, activity_functions::StdActivities, mock_sdk, mock_sdk_cfg,
3
+ };
2
4
  use std::{
3
- sync::atomic::{AtomicBool, AtomicUsize, Ordering},
5
+ sync::{
6
+ Arc,
7
+ atomic::{AtomicBool, AtomicUsize, Ordering},
8
+ },
4
9
  time::Duration,
5
10
  };
6
- use temporalio_client::WorkflowOptions;
11
+ use temporalio_client::WorkflowStartOptions;
7
12
  use temporalio_common::{
8
13
  protos::{
9
- DEFAULT_ACTIVITY_TYPE, TestHistoryBuilder, canned_histories,
14
+ TestHistoryBuilder, canned_histories,
10
15
  coresdk::AsJsonPayloadExt,
11
16
  temporal::api::{
12
17
  enums::v1::{EventType, WorkflowTaskFailedCause},
@@ -15,87 +20,121 @@ use temporalio_common::{
15
20
  },
16
21
  worker::WorkerTaskTypes,
17
22
  };
23
+ use temporalio_macros::{workflow, workflow_methods};
18
24
  use temporalio_sdk::{
19
- ActContext, ActivityOptions, ChildWorkflowOptions, LocalActivityOptions, WfContext,
20
- WorkflowResult,
25
+ ActivityOptions, ChildWorkflowOptions, LocalActivityOptions, WorkflowContext, WorkflowResult,
21
26
  };
22
27
  use temporalio_sdk_core::{
23
28
  replay::DEFAULT_WORKFLOW_TYPE,
24
29
  test_help::{CoreInternalFlags, MockPollCfg, ResponseType, mock_worker_client},
25
30
  };
26
31
 
27
- static RUN_CT: AtomicUsize = AtomicUsize::new(1);
32
+ #[workflow]
33
+ pub(crate) struct TimerWfNondeterministic {
34
+ run_ct: Arc<AtomicUsize>,
35
+ }
28
36
 
29
- pub(crate) async fn timer_wf_nondeterministic(ctx: WfContext) -> WorkflowResult<()> {
30
- let run_ct = RUN_CT.fetch_add(1, Ordering::Relaxed);
37
+ #[workflow_methods(factory_only)]
38
+ impl TimerWfNondeterministic {
39
+ #[run]
40
+ pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
41
+ let run_ct = ctx.state(|wf| wf.run_ct.fetch_add(1, Ordering::Relaxed));
31
42
 
32
- match run_ct {
33
- 1 | 3 => {
34
- // If we have not run yet or are on the third attempt, schedule a timer
35
- ctx.timer(Duration::from_secs(1)).await;
36
- if run_ct == 1 {
37
- // on first attempt we need to blow up after the timer fires so we will replay
38
- panic!("dying on purpose");
43
+ match run_ct {
44
+ 1 | 3 => {
45
+ ctx.timer(Duration::from_secs(1)).await;
46
+ if run_ct == 1 {
47
+ panic!("dying on purpose");
48
+ }
39
49
  }
50
+ 2 => {
51
+ ctx.start_activity(StdActivities::default, (), ActivityOptions::default())
52
+ .await
53
+ .map_err(|e| anyhow::anyhow!("{e}"))?;
54
+ }
55
+ _ => panic!("Ran too many times"),
40
56
  }
41
- 2 => {
42
- // On the second attempt we should cause a nondeterminism error
43
- ctx.activity(ActivityOptions {
44
- activity_type: "whatever".to_string(),
45
- ..Default::default()
46
- })
47
- .await;
48
- }
49
- _ => panic!("Ran too many times"),
57
+ Ok(())
50
58
  }
51
- Ok(().into())
52
59
  }
53
60
 
54
61
  #[tokio::test]
55
62
  async fn test_determinism_error_then_recovers() {
56
63
  let wf_name = "test_determinism_error_then_recovers";
57
64
  let mut starter = CoreWfStarter::new(wf_name);
58
- starter
59
- .worker_config
60
- .task_types(WorkerTaskTypes::workflow_only());
65
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
61
66
  let mut worker = starter.worker().await;
62
67
 
63
- worker.register_wf(wf_name.to_owned(), timer_wf_nondeterministic);
64
- starter.start_with_worker(wf_name, &mut worker).await;
68
+ let run_ct = Arc::new(AtomicUsize::new(1));
69
+ let run_ct_clone = run_ct.clone();
70
+ worker.register_workflow_with_factory(move || TimerWfNondeterministic {
71
+ run_ct: run_ct_clone.clone(),
72
+ });
73
+ let task_queue = starter.get_task_queue().to_owned();
74
+ worker
75
+ .submit_workflow(
76
+ TimerWfNondeterministic::run,
77
+ (),
78
+ WorkflowStartOptions::new(task_queue, starter.get_task_queue().to_owned()).build(),
79
+ )
80
+ .await
81
+ .unwrap();
65
82
  worker.run_until_done().await.unwrap();
66
- // 4 because we still add on the 3rd and final attempt
67
- assert_eq!(RUN_CT.load(Ordering::Relaxed), 4);
83
+ assert_eq!(run_ct.load(Ordering::Relaxed), 4);
84
+ }
85
+
86
+ #[workflow]
87
+ struct TaskFailReplayWf {
88
+ did_fail: Arc<AtomicBool>,
89
+ }
90
+
91
+ #[workflow_methods(factory_only)]
92
+ impl TaskFailReplayWf {
93
+ #[run]
94
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
95
+ if ctx.state(|wf| wf.did_fail.load(Ordering::Relaxed)) {
96
+ assert!(ctx.is_replaying());
97
+ }
98
+ let _ = ctx
99
+ .start_activity(
100
+ StdActivities::echo,
101
+ "hi!".to_string(),
102
+ ActivityOptions {
103
+ start_to_close_timeout: Some(Duration::from_secs(2)),
104
+ ..Default::default()
105
+ },
106
+ )
107
+ .await;
108
+ if !ctx.state(|wf| wf.did_fail.load(Ordering::Relaxed)) {
109
+ ctx.state(|wf| wf.did_fail.store(true, Ordering::Relaxed));
110
+ panic!("Die on purpose");
111
+ }
112
+ Ok(())
113
+ }
68
114
  }
69
115
 
70
116
  #[tokio::test]
71
117
  async fn task_fail_causes_replay_unset_too_soon() {
72
118
  let wf_name = "task_fail_causes_replay_unset_too_soon";
73
119
  let mut starter = CoreWfStarter::new(wf_name);
120
+ starter.sdk_config.register_activities(StdActivities);
74
121
  let mut worker = starter.worker().await;
75
122
 
76
- static DID_FAIL: AtomicBool = AtomicBool::new(false);
77
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| async move {
78
- if DID_FAIL.load(Ordering::Relaxed) {
79
- assert!(ctx.is_replaying());
80
- }
81
- ctx.activity(ActivityOptions {
82
- activity_type: "echo".to_string(),
83
- input: "hi!".as_json_payload().expect("serializes fine"),
84
- start_to_close_timeout: Some(Duration::from_secs(2)),
85
- ..Default::default()
86
- })
87
- .await;
88
- if !DID_FAIL.load(Ordering::Relaxed) {
89
- DID_FAIL.store(true, Ordering::Relaxed);
90
- panic!("Die on purpose");
91
- }
92
- Ok(().into())
93
- });
94
- worker.register_activity("echo", |_ctx: ActContext, echo_me: String| async move {
95
- Ok(echo_me)
123
+ let did_fail = Arc::new(AtomicBool::new(false));
124
+ let did_fail_clone = did_fail.clone();
125
+ worker.register_workflow_with_factory(move || TaskFailReplayWf {
126
+ did_fail: did_fail_clone.clone(),
96
127
  });
97
128
 
98
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
129
+ let task_queue = starter.get_task_queue().to_owned();
130
+ let handle = worker
131
+ .submit_workflow(
132
+ TaskFailReplayWf::run,
133
+ (),
134
+ WorkflowStartOptions::new(task_queue, starter.get_task_queue().to_owned()).build(),
135
+ )
136
+ .await
137
+ .unwrap();
99
138
 
100
139
  worker.run_until_done().await.unwrap();
101
140
  handle
@@ -104,17 +143,27 @@ async fn task_fail_causes_replay_unset_too_soon() {
104
143
  .unwrap();
105
144
  }
106
145
 
107
- async fn timer_wf_fails_once(ctx: WfContext) -> WorkflowResult<()> {
108
- static DID_FAIL: AtomicBool = AtomicBool::new(false);
146
+ #[workflow]
147
+ struct TimerWfFailsOnce {
148
+ did_fail: Arc<AtomicBool>,
149
+ }
109
150
 
110
- ctx.timer(Duration::from_secs(1)).await;
111
- if DID_FAIL
112
- .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
113
- .is_ok()
114
- {
115
- panic!("Ahh");
151
+ #[workflow_methods(factory_only)]
152
+ impl TimerWfFailsOnce {
153
+ #[run(name = DEFAULT_WORKFLOW_TYPE)]
154
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
155
+ ctx.timer(Duration::from_secs(1)).await;
156
+ if ctx
157
+ .state(|wf| {
158
+ wf.did_fail
159
+ .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
160
+ })
161
+ .is_ok()
162
+ {
163
+ panic!("Ahh");
164
+ }
165
+ Ok(())
116
166
  }
117
- Ok(().into())
118
167
  }
119
168
 
120
169
  /// Verifies that workflow panics (which in this case the Rust SDK turns into workflow activation
@@ -137,19 +186,39 @@ async fn test_panic_wf_task_rejected_properly() {
137
186
  });
138
187
  let mut worker = mock_sdk(mh);
139
188
 
140
- worker.register_wf(wf_type.to_owned(), timer_wf_fails_once);
189
+ let did_fail = Arc::new(AtomicBool::new(false));
190
+ worker.register_workflow_with_factory(move || TimerWfFailsOnce {
191
+ did_fail: did_fail.clone(),
192
+ });
193
+ let task_queue = "fake_tq".to_owned();
141
194
  worker
142
195
  .submit_wf(
143
- wf_id.to_owned(),
144
196
  wf_type.to_owned(),
145
197
  vec![],
146
- WorkflowOptions::default(),
198
+ WorkflowStartOptions::new(task_queue, wf_id.to_owned()).build(),
147
199
  )
148
200
  .await
149
201
  .unwrap();
150
202
  worker.run_until_done().await.unwrap();
151
203
  }
152
204
 
205
+ #[workflow]
206
+ struct NondeterministicTimerWf {
207
+ started_count: Arc<AtomicUsize>,
208
+ }
209
+
210
+ #[workflow_methods(factory_only)]
211
+ impl NondeterministicTimerWf {
212
+ #[run(name = DEFAULT_WORKFLOW_TYPE)]
213
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
214
+ if ctx.state(|wf| wf.started_count.fetch_add(1, Ordering::Relaxed)) == 0 {
215
+ ctx.timer(Duration::from_secs(1)).await;
216
+ }
217
+ ctx.timer(Duration::from_secs(1)).await;
218
+ Ok(())
219
+ }
220
+ }
221
+
153
222
  /// Verifies nondeterministic behavior in workflows results in automatic WFT failure with the
154
223
  /// appropriate nondeterminism cause.
155
224
  #[rstest::rstest]
@@ -164,11 +233,9 @@ async fn test_wf_task_rejected_properly_due_to_nondeterminism(#[case] use_cache:
164
233
  let mut mh = MockPollCfg::from_resp_batches(
165
234
  wf_id,
166
235
  t,
167
- // Two polls are needed, since the first will fail
168
236
  [ResponseType::AllHistory, ResponseType::AllHistory],
169
237
  mock,
170
238
  );
171
- // We should see one wft failure which has nondeterminism cause
172
239
  mh.num_expected_fails = 1;
173
240
  mh.expect_fail_wft_matcher =
174
241
  Box::new(|_, cause, _| matches!(cause, WorkflowTaskFailedCause::NonDeterministicError));
@@ -178,32 +245,73 @@ async fn test_wf_task_rejected_properly_due_to_nondeterminism(#[case] use_cache:
178
245
  }
179
246
  });
180
247
 
181
- let started_count: &'static _ = Box::leak(Box::new(AtomicUsize::new(0)));
182
- worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
183
- // The workflow is replaying all of history, so the when it schedules an extra timer it
184
- // should not have, it causes a nondeterminism error.
185
- if started_count.fetch_add(1, Ordering::Relaxed) == 0 {
186
- ctx.timer(Duration::from_secs(1)).await;
187
- }
188
- ctx.timer(Duration::from_secs(1)).await;
189
- Ok(().into())
248
+ let started_count = Arc::new(AtomicUsize::new(0));
249
+ let count_clone = started_count.clone();
250
+ worker.register_workflow_with_factory(move || NondeterministicTimerWf {
251
+ started_count: count_clone.clone(),
190
252
  });
191
253
 
254
+ let task_queue = "fake_tq".to_owned();
192
255
  worker
193
256
  .submit_wf(
194
- wf_id.to_owned(),
195
257
  wf_type.to_owned(),
196
258
  vec![],
197
- WorkflowOptions::default(),
259
+ WorkflowStartOptions::new(task_queue, wf_id.to_owned()).build(),
198
260
  )
199
261
  .await
200
262
  .unwrap();
201
263
  worker.run_until_done().await.unwrap();
202
- // Started count is two since we start, restart once due to error, then we unblock the real
203
- // timer and proceed without restarting
204
264
  assert_eq!(2, started_count.load(Ordering::Relaxed));
205
265
  }
206
266
 
267
+ #[workflow]
268
+ #[derive(Default)]
269
+ struct ActivityIdOrTypeChangeWf;
270
+
271
+ #[workflow_methods]
272
+ impl ActivityIdOrTypeChangeWf {
273
+ #[run(name = DEFAULT_WORKFLOW_TYPE)]
274
+ async fn run(
275
+ ctx: &mut WorkflowContext<Self>,
276
+ (id_change, local_act): (bool, bool),
277
+ ) -> WorkflowResult<()> {
278
+ if local_act {
279
+ if id_change {
280
+ ctx.start_local_activity(
281
+ StdActivities::default,
282
+ (),
283
+ LocalActivityOptions {
284
+ activity_id: Some("I'm bad and wrong!".to_string()),
285
+ ..Default::default()
286
+ },
287
+ )
288
+ .await
289
+ .map_err(|e| anyhow::anyhow!("{e}"))?;
290
+ } else {
291
+ ctx.start_local_activity(StdActivities::no_op, (), Default::default())
292
+ .await
293
+ .map_err(|e| anyhow::anyhow!("{e}"))?;
294
+ }
295
+ } else if id_change {
296
+ ctx.start_activity(
297
+ StdActivities::default,
298
+ (),
299
+ ActivityOptions {
300
+ activity_id: Some("I'm bad and wrong!".to_string()),
301
+ ..Default::default()
302
+ },
303
+ )
304
+ .await
305
+ .map_err(|e| anyhow::anyhow!("{e}"))?;
306
+ } else {
307
+ ctx.start_activity(StdActivities::no_op, (), ActivityOptions::default())
308
+ .await
309
+ .map_err(|e| anyhow::anyhow!("{e}"))?;
310
+ }
311
+ Ok(())
312
+ }
313
+ }
314
+
207
315
  #[rstest::rstest]
208
316
  #[tokio::test]
209
317
  async fn activity_id_or_type_change_is_nondeterministic(
@@ -219,15 +327,14 @@ async fn activity_id_or_type_change_is_nondeterministic(
219
327
  canned_histories::single_activity("1")
220
328
  };
221
329
  t.set_flags_first_wft(&[CoreInternalFlags::IdAndTypeDeterminismChecks as u32], &[]);
330
+ t.set_wf_input((id_change, local_act).as_json_payload().unwrap());
222
331
  let mock = mock_worker_client();
223
332
  let mut mh = MockPollCfg::from_resp_batches(
224
333
  wf_id,
225
334
  t,
226
- // Two polls are needed, since the first will fail
227
335
  [ResponseType::AllHistory, ResponseType::AllHistory],
228
336
  mock,
229
337
  );
230
- // We should see one wft failure which has nondeterminism cause
231
338
  mh.num_expected_fails = 1;
232
339
  mh.expect_fail_wft_matcher = Box::new(move |_, cause, f| {
233
340
  let should_contain = if id_change {
@@ -246,52 +353,47 @@ async fn activity_id_or_type_change_is_nondeterministic(
246
353
  cfg.max_cached_workflows = 2;
247
354
  }
248
355
  });
356
+ worker.register_workflow::<ActivityIdOrTypeChangeWf>();
249
357
 
250
- worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
251
- if local_act {
252
- ctx.local_activity(if id_change {
253
- LocalActivityOptions {
254
- activity_id: Some("I'm bad and wrong!".to_string()),
255
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
256
- ..Default::default()
257
- }
258
- } else {
259
- LocalActivityOptions {
260
- activity_type: "not the default act type".to_string(),
261
- ..Default::default()
262
- }
263
- })
264
- .await;
265
- } else {
266
- ctx.activity(if id_change {
267
- ActivityOptions {
268
- activity_id: Some("I'm bad and wrong!".to_string()),
269
- activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
270
- ..Default::default()
271
- }
272
- } else {
273
- ActivityOptions {
274
- activity_type: "not the default act type".to_string(),
275
- ..Default::default()
276
- }
277
- })
278
- .await;
279
- }
280
- Ok(().into())
281
- });
282
-
358
+ let task_queue = "fake_tq".to_owned();
283
359
  worker
284
360
  .submit_wf(
285
- wf_id.to_owned(),
286
361
  wf_type.to_owned(),
287
- vec![],
288
- WorkflowOptions::default(),
362
+ vec![(id_change, local_act).as_json_payload().unwrap()],
363
+ WorkflowStartOptions::new(task_queue, wf_id.to_owned()).build(),
289
364
  )
290
365
  .await
291
366
  .unwrap();
292
367
  worker.run_until_done().await.unwrap();
293
368
  }
294
369
 
370
+ #[workflow]
371
+ #[derive(Default)]
372
+ struct ChildWfIdOrTypeChangeWf;
373
+
374
+ #[workflow_methods]
375
+ impl ChildWfIdOrTypeChangeWf {
376
+ #[run(name = DEFAULT_WORKFLOW_TYPE)]
377
+ async fn run(ctx: &mut WorkflowContext<Self>, id_change: bool) -> WorkflowResult<()> {
378
+ ctx.child_workflow(if id_change {
379
+ ChildWorkflowOptions {
380
+ workflow_id: "I'm bad and wrong!".to_string(),
381
+ workflow_type: "child".to_string(),
382
+ ..Default::default()
383
+ }
384
+ } else {
385
+ ChildWorkflowOptions {
386
+ workflow_id: "1".to_string(),
387
+ workflow_type: "not the child wf type".to_string(),
388
+ ..Default::default()
389
+ }
390
+ })
391
+ .start()
392
+ .await;
393
+ Ok(())
394
+ }
395
+ }
396
+
295
397
  #[rstest::rstest]
296
398
  #[tokio::test]
297
399
  async fn child_wf_id_or_type_change_is_nondeterministic(
@@ -302,15 +404,14 @@ async fn child_wf_id_or_type_change_is_nondeterministic(
302
404
  let wf_type = DEFAULT_WORKFLOW_TYPE;
303
405
  let mut t = canned_histories::single_child_workflow("1");
304
406
  t.set_flags_first_wft(&[CoreInternalFlags::IdAndTypeDeterminismChecks as u32], &[]);
407
+ t.set_wf_input(id_change.as_json_payload().unwrap());
305
408
  let mock = mock_worker_client();
306
409
  let mut mh = MockPollCfg::from_resp_batches(
307
410
  wf_id,
308
411
  t,
309
- // Two polls are needed, since the first will fail
310
412
  [ResponseType::AllHistory, ResponseType::AllHistory],
311
413
  mock,
312
414
  );
313
- // We should see one wft failure which has nondeterminism cause
314
415
  mh.num_expected_fails = 1;
315
416
  mh.expect_fail_wft_matcher = Box::new(move |_, cause, f| {
316
417
  let should_contain = if id_change {
@@ -330,37 +431,34 @@ async fn child_wf_id_or_type_change_is_nondeterministic(
330
431
  }
331
432
  });
332
433
 
333
- worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
334
- ctx.child_workflow(if id_change {
335
- ChildWorkflowOptions {
336
- workflow_id: "I'm bad and wrong!".to_string(),
337
- workflow_type: DEFAULT_ACTIVITY_TYPE.to_string(),
338
- ..Default::default()
339
- }
340
- } else {
341
- ChildWorkflowOptions {
342
- workflow_id: "1".to_string(),
343
- workflow_type: "not the child wf type".to_string(),
344
- ..Default::default()
345
- }
346
- })
347
- .start(&ctx)
348
- .await;
349
- Ok(().into())
350
- });
434
+ worker.register_workflow::<ChildWfIdOrTypeChangeWf>();
351
435
 
436
+ let task_queue = "fake_tq".to_owned();
352
437
  worker
353
438
  .submit_wf(
354
- wf_id.to_owned(),
355
439
  wf_type.to_owned(),
356
- vec![],
357
- WorkflowOptions::default(),
440
+ vec![id_change.as_json_payload().unwrap()],
441
+ WorkflowStartOptions::new(task_queue, wf_id.to_owned()).build(),
358
442
  )
359
443
  .await
360
444
  .unwrap();
361
445
  worker.run_until_done().await.unwrap();
362
446
  }
363
447
 
448
+ #[workflow]
449
+ #[derive(Default)]
450
+ struct ReproChannelMissingWf;
451
+
452
+ #[workflow_methods]
453
+ impl ReproChannelMissingWf {
454
+ #[run(name = DEFAULT_WORKFLOW_TYPE)]
455
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
456
+ ctx.patched("wrongid");
457
+ ctx.timer(Duration::from_secs(1)).await;
458
+ Ok(())
459
+ }
460
+ }
461
+
364
462
  /// Repros a situation where if, upon completing a task there is some internal error which causes
365
463
  /// us to want to auto-fail the workflow task while there is also an outstanding eviction, the wf
366
464
  /// would get evicted but then try to send some info down the completion channel afterward, causing
@@ -386,18 +484,14 @@ async fn repro_channel_missing_because_nondeterminism() {
386
484
  cfg.ignore_evicts_on_shutdown = false;
387
485
  });
388
486
 
389
- worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
390
- ctx.patched("wrongid");
391
- ctx.timer(Duration::from_secs(1)).await;
392
- Ok(().into())
393
- });
487
+ worker.register_workflow::<ReproChannelMissingWf>();
394
488
 
489
+ let task_queue = "fake_tq".to_owned();
395
490
  worker
396
491
  .submit_wf(
397
- wf_id.to_owned(),
398
492
  wf_type.to_owned(),
399
493
  vec![],
400
- WorkflowOptions::default(),
494
+ WorkflowStartOptions::new(task_queue, wf_id.to_owned()).build(),
401
495
  )
402
496
  .await
403
497
  .unwrap();