@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,24 +1,28 @@
1
1
  use crate::common::{
2
- CoreWfStarter, WorkflowHandleExt, init_core_and_create_wf, init_core_replay_preloaded,
2
+ CoreWfStarter, WorkflowHandleExt, activity_functions::StdActivities, init_core_and_create_wf,
3
+ init_core_replay_preloaded,
3
4
  };
4
5
  use anyhow::anyhow;
5
6
  use assert_matches::assert_matches;
6
- use futures_util::{StreamExt, future, future::join_all};
7
+ use futures_util::{future, future::join_all};
7
8
  use std::{
8
9
  sync::{
9
- Arc, LazyLock,
10
+ LazyLock,
10
11
  atomic::{AtomicBool, AtomicUsize, Ordering},
11
12
  },
12
13
  time::Duration,
13
14
  };
14
15
  use temporalio_client::{
15
- Client, NamespacedClient, RetryClient, WorkflowClientTrait, WorkflowService,
16
+ Client, NamespacedClient, UntypedSignal, UntypedUpdate, UntypedWorkflow,
17
+ WorkflowExecuteUpdateOptions, WorkflowExecutionInfo, WorkflowSignalOptions,
18
+ WorkflowStartOptions, grpc::WorkflowService,
16
19
  };
17
20
  use temporalio_common::{
18
- Worker, prost_dur,
21
+ data_converters::RawValue,
22
+ prost_dur,
19
23
  protos::{
20
24
  coresdk::{
21
- ActivityTaskCompletion, AsJsonPayloadExt, IntoPayloadsExt,
25
+ ActivityTaskCompletion,
22
26
  activity_result::ActivityExecutionResult,
23
27
  workflow_activation::{
24
28
  WorkflowActivationJob, remove_from_cache::EvictionReason, workflow_activation_job,
@@ -30,16 +34,21 @@ use temporalio_common::{
30
34
  },
31
35
  temporal::api::{
32
36
  common::v1::WorkflowExecution,
33
- enums::v1::{EventType, ResetReapplyType, UpdateWorkflowExecutionLifecycleStage},
34
- update::{self, v1::WaitPolicy},
35
- workflowservice::v1::ResetWorkflowExecutionRequest,
37
+ enums::v1::{EventType, ResetReapplyType},
38
+ workflowservice::v1::{ResetStickyTaskQueueRequest, ResetWorkflowExecutionRequest},
36
39
  },
37
40
  test_utils::start_timer_cmd,
38
41
  },
39
42
  worker::WorkerTaskTypes,
40
43
  };
41
- use temporalio_sdk::{ActContext, ActivityOptions, LocalActivityOptions, UpdateContext, WfContext};
44
+ use temporalio_macros::{activities, workflow, workflow_methods};
45
+ use temporalio_sdk::{
46
+ ActivityOptions, LocalActivityOptions, SyncWorkflowContext, WorkflowContext,
47
+ WorkflowContextView, WorkflowResult,
48
+ activities::{ActivityContext, ActivityError},
49
+ };
42
50
  use temporalio_sdk_core::{
51
+ Worker,
43
52
  replay::HistoryForReplay,
44
53
  test_help::{WorkerTestHelpers, drain_pollers_and_shutdown},
45
54
  };
@@ -73,18 +82,18 @@ async fn update_workflow(#[values(FailUpdate::Yes, FailUpdate::No)] will_fail: F
73
82
  will_fail,
74
83
  CompleteWorkflow::Yes,
75
84
  core.as_ref(),
76
- client.as_ref(),
85
+ &client,
77
86
  )
78
87
  .await;
79
88
 
80
89
  // Make sure replay works
81
- let history = client
82
- .get_workflow_execution_history(workflow_id.to_string(), None, vec![])
90
+ let events = client
91
+ .get_workflow_handle::<UntypedWorkflow>(workflow_id)
92
+ .fetch_history(Default::default())
83
93
  .await
84
94
  .unwrap()
85
- .history
86
- .unwrap();
87
- let with_id = HistoryForReplay::new(history, workflow_id.to_string());
95
+ .into_events();
96
+ let with_id = HistoryForReplay::new(events, workflow_id.to_string());
88
97
  let replay_worker = init_core_replay_preloaded(workflow_id, [with_id]);
89
98
  // Init workflow comes by itself
90
99
  let act = replay_worker.poll_workflow_activation().await.unwrap();
@@ -92,7 +101,7 @@ async fn update_workflow(#[values(FailUpdate::Yes, FailUpdate::No)] will_fail: F
92
101
  .complete_workflow_activation(WorkflowActivationCompletion::empty(act.run_id))
93
102
  .await
94
103
  .unwrap();
95
- handle_update(will_fail, CompleteWorkflow::Yes, replay_worker.as_ref(), 0).await;
104
+ handle_update(will_fail, CompleteWorkflow::Yes, &replay_worker, 0).await;
96
105
  }
97
106
 
98
107
  #[tokio::test]
@@ -107,7 +116,7 @@ async fn reapplied_updates_due_to_reset() {
107
116
  FailUpdate::No,
108
117
  CompleteWorkflow::Yes,
109
118
  core.as_ref(),
110
- client.as_ref(),
119
+ &client,
111
120
  )
112
121
  .await;
113
122
 
@@ -116,12 +125,12 @@ async fn reapplied_updates_due_to_reset() {
116
125
 
117
126
  let mut client_mut = client.clone();
118
127
  let reset_response = WorkflowService::reset_workflow_execution(
119
- Arc::make_mut(&mut client_mut),
128
+ &mut client_mut,
120
129
  #[allow(deprecated)]
121
130
  ResetWorkflowExecutionRequest {
122
131
  namespace: client.namespace(),
123
132
  workflow_execution: Some(WorkflowExecution {
124
- workflow_id: workflow_id.into(),
133
+ workflow_id: workflow_id.to_string(),
125
134
  run_id: pre_reset_run_id.clone(),
126
135
  }),
127
136
  workflow_task_finish_event_id,
@@ -147,32 +156,31 @@ async fn reapplied_updates_due_to_reset() {
147
156
  FailUpdate::No,
148
157
  CompleteWorkflow::Yes,
149
158
  core.as_ref(),
150
- client.as_ref(),
159
+ &client,
151
160
  )
152
161
  .await;
153
162
 
154
163
  assert_eq!(post_reset_run_id, reset_response.run_id);
155
164
 
156
165
  // Make sure replay works
157
- let history = client
158
- .get_workflow_execution_history(workflow_id.to_string(), Some(post_reset_run_id), vec![])
159
- .await
160
- .unwrap()
161
- .history
162
- .unwrap();
163
- let with_id = HistoryForReplay::new(history, workflow_id.to_string());
166
+ let events = WorkflowExecutionInfo {
167
+ namespace: client.namespace(),
168
+ workflow_id: workflow_id.to_string(),
169
+ run_id: Some(post_reset_run_id.clone()),
170
+ first_execution_run_id: None,
171
+ }
172
+ .bind_untyped(client.clone())
173
+ .fetch_history(Default::default())
174
+ .await
175
+ .unwrap()
176
+ .into_events();
177
+ let with_id = HistoryForReplay::new(events, workflow_id.to_string());
164
178
 
165
179
  let replay_worker = init_core_replay_preloaded(workflow_id, [with_id]);
166
180
  // We now recapitulate the actions that the worker took on first execution above, pretending
167
181
  // that we always followed the post-reset history.
168
182
  // First, we handled the post-reset reapplied update and did not complete the workflow.
169
- handle_update(
170
- FailUpdate::No,
171
- CompleteWorkflow::No,
172
- replay_worker.as_ref(),
173
- 2,
174
- )
175
- .await;
183
+ handle_update(FailUpdate::No, CompleteWorkflow::No, &replay_worker, 2).await;
176
184
  // Then the timer fires
177
185
  let act = replay_worker.poll_workflow_activation().await.unwrap();
178
186
  replay_worker
@@ -180,13 +188,7 @@ async fn reapplied_updates_due_to_reset() {
180
188
  .await
181
189
  .unwrap();
182
190
  // Then the client sent a second update; we handled it and completed the workflow.
183
- handle_update(
184
- FailUpdate::No,
185
- CompleteWorkflow::Yes,
186
- replay_worker.as_ref(),
187
- 0,
188
- )
189
- .await;
191
+ handle_update(FailUpdate::No, CompleteWorkflow::Yes, &replay_worker, 0).await;
190
192
 
191
193
  drain_pollers_and_shutdown(&replay_worker).await;
192
194
  }
@@ -197,8 +199,8 @@ async fn send_and_handle_update(
197
199
  update_id: &str,
198
200
  fail_update: FailUpdate,
199
201
  complete_workflow: CompleteWorkflow,
200
- core: &dyn Worker,
201
- client: &RetryClient<Client>,
202
+ core: &Worker,
203
+ client: &Client,
202
204
  ) -> String {
203
205
  // Complete first task with no commands
204
206
  let act = core.poll_workflow_activation().await.unwrap();
@@ -206,30 +208,32 @@ async fn send_and_handle_update(
206
208
  .await
207
209
  .unwrap();
208
210
 
211
+ let handle = WorkflowExecutionInfo {
212
+ namespace: client.namespace(),
213
+ workflow_id: workflow_id.to_string(),
214
+ run_id: Some(act.run_id.clone()),
215
+ first_execution_run_id: None,
216
+ }
217
+ .bind_untyped(client.clone());
218
+
209
219
  // Send the update to the server
210
220
  let update_task = async {
211
- client
212
- .update_workflow_execution(
213
- workflow_id.to_string(),
214
- act.run_id.to_string(),
215
- update_id.to_string(),
216
- WaitPolicy {
217
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
218
- },
219
- Some("hi".into()),
221
+ handle
222
+ .execute_update(
223
+ UntypedUpdate::new(update_id),
224
+ RawValue::from_value(&"hi", client.data_converter().payload_converter()),
225
+ WorkflowExecuteUpdateOptions::default(),
220
226
  )
221
227
  .await
222
- .unwrap()
223
228
  };
224
229
 
225
230
  // Accept update, complete update and complete workflow
226
231
  let processing_task = handle_update(fail_update, complete_workflow, core, 0);
227
232
  let (ur, _) = join!(update_task, processing_task);
228
233
 
229
- let v = ur.outcome.unwrap().value.unwrap();
230
234
  match fail_update {
231
- FailUpdate::Yes => assert_matches!(v, update::v1::outcome::Value::Failure(_)),
232
- FailUpdate::No => assert_matches!(v, update::v1::outcome::Value::Success(_)),
235
+ FailUpdate::Yes => assert!(ur.is_err()),
236
+ FailUpdate::No => assert!(ur.is_ok()),
233
237
  }
234
238
  act.run_id
235
239
  }
@@ -241,7 +245,7 @@ async fn send_and_handle_update(
241
245
  async fn handle_update(
242
246
  fail_update: FailUpdate,
243
247
  complete_workflow: CompleteWorkflow,
244
- core: &dyn Worker,
248
+ core: &Worker,
245
249
  update_job_index: usize,
246
250
  ) {
247
251
  let act = core.poll_workflow_activation().await.unwrap();
@@ -313,20 +317,24 @@ async fn update_rejection() {
313
317
  .await
314
318
  .unwrap();
315
319
 
320
+ let handle = WorkflowExecutionInfo {
321
+ namespace: client.namespace(),
322
+ workflow_id: workflow_id.clone(),
323
+ run_id: Some(res.run_id.clone()),
324
+ first_execution_run_id: None,
325
+ }
326
+ .bind_untyped(client.clone());
327
+
316
328
  // Send the update to the server
317
329
  let update_task = async {
318
- client
319
- .update_workflow_execution(
320
- workflow_id.to_string(),
321
- res.run_id.to_string(),
322
- update_id.to_string(),
323
- WaitPolicy {
324
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
325
- },
326
- Some("hi".into()),
330
+ // rejected
331
+ let _ = handle
332
+ .execute_update(
333
+ UntypedUpdate::new(update_id),
334
+ RawValue::from_value(&"hi", client.data_converter().payload_converter()),
335
+ WorkflowExecuteUpdateOptions::default(),
327
336
  )
328
- .await
329
- .unwrap();
337
+ .await;
330
338
  };
331
339
 
332
340
  let processing_task = async {
@@ -355,13 +363,13 @@ async fn update_rejection() {
355
363
  core.complete_execution(&res.run_id).await;
356
364
  };
357
365
  join!(update_task, processing_task);
358
- let history = client
359
- .get_workflow_execution_history(workflow_id, None, vec![])
366
+ let events = client
367
+ .get_workflow_handle::<UntypedWorkflow>(&workflow_id)
368
+ .fetch_history(Default::default())
360
369
  .await
361
370
  .unwrap()
362
- .history
363
- .unwrap();
364
- let has_update_event = history.events.iter().any(|e| {
371
+ .into_events();
372
+ let has_update_event = events.iter().any(|e| {
365
373
  matches!(
366
374
  e.event_type(),
367
375
  EventType::WorkflowExecutionUpdateAccepted | EventType::WorkflowExecutionUpdateRejected
@@ -388,17 +396,21 @@ async fn update_insta_complete(#[values(true, false)] accept_first: bool) {
388
396
  .await
389
397
  .unwrap();
390
398
 
399
+ let handle = WorkflowExecutionInfo {
400
+ namespace: client.namespace(),
401
+ workflow_id,
402
+ run_id: Some(res.run_id.clone()),
403
+ first_execution_run_id: None,
404
+ }
405
+ .bind_untyped(client.clone());
406
+
391
407
  // Send the update to the server
392
408
  let (update_task, stop_wait_update) = future::abortable(async {
393
- client
394
- .update_workflow_execution(
395
- workflow_id.to_string(),
396
- res.run_id.to_string(),
397
- update_id.to_string(),
398
- WaitPolicy {
399
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
400
- },
401
- Some("hi".into()),
409
+ handle
410
+ .execute_update(
411
+ UntypedUpdate::new(update_id),
412
+ RawValue::from_value(&"hi", client.data_converter().payload_converter()),
413
+ WorkflowExecuteUpdateOptions::default(),
402
414
  )
403
415
  .await
404
416
  .unwrap();
@@ -477,17 +489,21 @@ async fn update_complete_after_accept_without_new_task() {
477
489
  .await
478
490
  .unwrap();
479
491
 
492
+ let handle = WorkflowExecutionInfo {
493
+ namespace: client.namespace(),
494
+ workflow_id,
495
+ run_id: Some(res.run_id.clone()),
496
+ first_execution_run_id: None,
497
+ }
498
+ .bind_untyped(client.clone());
499
+
480
500
  // Send the update to the server
481
501
  let update_task = async {
482
- client
483
- .update_workflow_execution(
484
- workflow_id.to_string(),
485
- res.run_id.to_string(),
486
- update_id.to_string(),
487
- WaitPolicy {
488
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
489
- },
490
- Some("hi".into()),
502
+ handle
503
+ .execute_update(
504
+ UntypedUpdate::new(update_id),
505
+ RawValue::from_value(&"hi", client.data_converter().payload_converter()),
506
+ WorkflowExecuteUpdateOptions::default(),
491
507
  )
492
508
  .await
493
509
  .unwrap();
@@ -565,30 +581,26 @@ async fn update_speculative_wft() {
565
581
 
566
582
  let update_id = "some_update";
567
583
 
584
+ let handle = client.get_workflow_handle::<UntypedWorkflow>(workflow_id);
585
+
568
586
  // Send update after the timer has fired
569
587
  let barr = Barrier::new(2);
570
588
  let sender_task = async {
571
589
  barr.wait().await;
572
- client
573
- .update_workflow_execution(
574
- workflow_id.to_string(),
575
- "".to_string(),
576
- update_id.to_string(),
577
- WaitPolicy {
578
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
579
- },
580
- Some("hi".into()),
590
+ // rejected
591
+ let _ = handle
592
+ .execute_update(
593
+ UntypedUpdate::new(update_id),
594
+ RawValue::from_value(&"hi", client.data_converter().payload_converter()),
595
+ WorkflowExecuteUpdateOptions::default(),
581
596
  )
582
- .await
583
- .unwrap();
597
+ .await;
584
598
  barr.wait().await;
585
- client
586
- .signal_workflow_execution(
587
- workflow_id.to_string(),
588
- "".to_string(),
589
- "hi".into(),
590
- None,
591
- None,
599
+ handle
600
+ .signal(
601
+ UntypedSignal::new("hi"),
602
+ RawValue::empty(),
603
+ WorkflowSignalOptions::default(),
592
604
  )
593
605
  .await
594
606
  .unwrap();
@@ -649,63 +661,70 @@ async fn update_with_local_acts() {
649
661
  let mut starter = CoreWfStarter::new(wf_name);
650
662
  // Short task timeout to get activities to heartbeat without taking ages
651
663
  starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
664
+ starter.sdk_config.register_activities(StdActivities);
652
665
  let mut worker = starter.worker().await;
653
- let client = starter.get_client().await;
654
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| async move {
655
- ctx.update_handler(
656
- "update",
657
- |_: &_, _: ()| Ok(()),
658
- move |ctx: UpdateContext, _: ()| async move {
659
- ctx.wf_ctx
660
- .local_activity(LocalActivityOptions {
661
- activity_type: "echo_activity".to_string(),
662
- input: "hi!".as_json_payload().expect("serializes fine"),
663
- ..Default::default()
664
- })
665
- .await;
666
- Ok("hi")
667
- },
668
- );
669
- let mut sig = ctx.make_signal_channel("done");
670
- sig.next().await;
671
- Ok(().into())
672
- });
673
- worker.register_activity(
674
- "echo_activity",
675
- |_ctx: ActContext, echo_me: String| async move {
676
- // Sleep so we'll heartbeat
677
- tokio::time::sleep(Duration::from_secs(3)).await;
678
- Ok(echo_me)
679
- },
680
- );
681
666
 
682
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
683
- let wf_id = starter.get_task_queue().to_string();
667
+ #[workflow]
668
+ #[derive(Default)]
669
+ struct UpdateWithLocalActsWf {
670
+ done: bool,
671
+ }
672
+
673
+ #[workflow_methods]
674
+ impl UpdateWithLocalActsWf {
675
+ #[run]
676
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
677
+ ctx.wait_condition(|s| s.done).await;
678
+ Ok(())
679
+ }
680
+
681
+ #[signal]
682
+ fn done_signal(&mut self, _ctx: &mut SyncWorkflowContext<Self>, _: ()) {
683
+ self.done = true;
684
+ }
685
+
686
+ #[update]
687
+ async fn do_update(
688
+ ctx: &mut WorkflowContext<Self>,
689
+ _: (),
690
+ ) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
691
+ ctx.start_local_activity(
692
+ StdActivities::delay,
693
+ Duration::from_secs(3),
694
+ LocalActivityOptions::default(),
695
+ )
696
+ .await?;
697
+ Ok("hi".to_string())
698
+ }
699
+ }
700
+
701
+ worker.register_workflow::<UpdateWithLocalActsWf>();
702
+ let task_queue = starter.get_task_queue().to_owned();
703
+ let handle = worker
704
+ .submit_workflow(
705
+ UpdateWithLocalActsWf::run,
706
+ (),
707
+ WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
708
+ )
709
+ .await
710
+ .unwrap();
684
711
  let update = async {
685
- // make sure update has a chance to get registered
686
- tokio::time::sleep(Duration::from_millis(100)).await;
687
712
  // do a handful at once
688
713
  let updates = (1..=5).map(|_| {
689
- client.update_workflow_execution(
690
- wf_id.clone(),
691
- "".to_string(),
692
- "update".to_string(),
693
- WaitPolicy {
694
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
695
- },
696
- [().as_json_payload().unwrap()].into_payloads(),
714
+ handle.execute_update(
715
+ UpdateWithLocalActsWf::do_update,
716
+ (),
717
+ WorkflowExecuteUpdateOptions::default(),
697
718
  )
698
719
  });
699
720
  for res in join_all(updates).await {
700
- assert!(res.unwrap().outcome.unwrap().is_success());
721
+ assert!(res.unwrap() == "hi");
701
722
  }
702
- client
703
- .signal_workflow_execution(
704
- wf_id.clone(),
705
- "".to_string(),
706
- "done".to_string(),
707
- None,
708
- None,
723
+ handle
724
+ .signal(
725
+ UpdateWithLocalActsWf::done_signal,
726
+ (),
727
+ WorkflowSignalOptions::default(),
709
728
  )
710
729
  .await
711
730
  .unwrap();
@@ -724,37 +743,57 @@ async fn update_with_local_acts() {
724
743
  async fn update_rejection_sdk() {
725
744
  let wf_name = "update_rejection_sdk";
726
745
  let mut starter = CoreWfStarter::new(wf_name);
727
- starter
728
- .worker_config
729
- .task_types(WorkerTaskTypes::workflow_only());
746
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
730
747
  let mut worker = starter.worker().await;
731
- let client = starter.get_client().await;
732
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
733
- ctx.update_handler(
734
- "update",
735
- |_: &_, _: ()| Err(anyhow!("ahhhhh noooo")),
736
- move |_: UpdateContext, _: ()| async { Ok("hi") },
737
- );
738
- ctx.timer(Duration::from_secs(1)).await;
739
- Ok(().into())
740
- });
748
+ #[workflow]
749
+ #[derive(Default)]
750
+ struct UpdateRejectionSdkWf;
751
+
752
+ #[workflow_methods]
753
+ impl UpdateRejectionSdkWf {
754
+ #[run]
755
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
756
+ ctx.timer(Duration::from_secs(1)).await;
757
+ Ok(())
758
+ }
759
+
760
+ #[update_validator(do_update)]
761
+ fn validate_do_update(
762
+ &self,
763
+ _ctx: &WorkflowContextView,
764
+ _: &(),
765
+ ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
766
+ Err("ahhhhh noooo".into())
767
+ }
768
+
769
+ #[update]
770
+ async fn do_update(
771
+ _ctx: &mut WorkflowContext<Self>,
772
+ _: (),
773
+ ) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
774
+ Ok("hi".to_string())
775
+ }
776
+ }
741
777
 
742
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
743
- let wf_id = starter.get_task_queue().to_string();
778
+ worker.register_workflow::<UpdateRejectionSdkWf>();
779
+ let task_queue = starter.get_task_queue().to_owned();
780
+ let handle = worker
781
+ .submit_workflow(
782
+ UpdateRejectionSdkWf::run,
783
+ (),
784
+ WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
785
+ )
786
+ .await
787
+ .unwrap();
744
788
  let update = async {
745
- let res = client
746
- .update_workflow_execution(
747
- wf_id.clone(),
748
- "".to_string(),
749
- "update".to_string(),
750
- WaitPolicy {
751
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
752
- },
753
- [().as_json_payload().unwrap()].into_payloads(),
789
+ let res = handle
790
+ .execute_update(
791
+ UpdateRejectionSdkWf::do_update,
792
+ (),
793
+ WorkflowExecuteUpdateOptions::default(),
754
794
  )
755
- .await
756
- .unwrap();
757
- assert!(!res.outcome.unwrap().is_success());
795
+ .await;
796
+ assert!(res.is_err());
758
797
  };
759
798
  let run = async {
760
799
  worker.run_until_done().await.unwrap();
@@ -770,37 +809,48 @@ async fn update_rejection_sdk() {
770
809
  async fn update_fail_sdk() {
771
810
  let wf_name = "update_fail_sdk";
772
811
  let mut starter = CoreWfStarter::new(wf_name);
773
- starter
774
- .worker_config
775
- .task_types(WorkerTaskTypes::workflow_only());
812
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
776
813
  let mut worker = starter.worker().await;
777
- let client = starter.get_client().await;
778
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
779
- ctx.update_handler(
780
- "update",
781
- |_: &_, _: ()| Ok(()),
782
- move |_: UpdateContext, _: ()| async { Err::<(), _>(anyhow!("nooooo")) },
783
- );
784
- ctx.timer(Duration::from_secs(1)).await;
785
- Ok(().into())
786
- });
814
+ #[workflow]
815
+ #[derive(Default)]
816
+ struct UpdateFailSdkWf;
817
+
818
+ #[workflow_methods]
819
+ impl UpdateFailSdkWf {
820
+ #[run]
821
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
822
+ ctx.timer(Duration::from_secs(1)).await;
823
+ Ok(())
824
+ }
825
+
826
+ #[update]
827
+ async fn do_update(
828
+ _ctx: &mut WorkflowContext<Self>,
829
+ _: (),
830
+ ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
831
+ Err("nooooo".into())
832
+ }
833
+ }
787
834
 
788
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
789
- let wf_id = starter.get_task_queue().to_string();
835
+ worker.register_workflow::<UpdateFailSdkWf>();
836
+ let task_queue = starter.get_task_queue().to_owned();
837
+ let handle = worker
838
+ .submit_workflow(
839
+ UpdateFailSdkWf::run,
840
+ (),
841
+ WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
842
+ )
843
+ .await
844
+ .unwrap();
790
845
  let update = async {
791
- let res = client
792
- .update_workflow_execution(
793
- wf_id.clone(),
794
- "".to_string(),
795
- "update".to_string(),
796
- WaitPolicy {
797
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
798
- },
799
- [().as_json_payload().unwrap()].into_payloads(),
846
+ let res = handle
847
+ .execute_update(
848
+ UpdateFailSdkWf::do_update,
849
+ (),
850
+ WorkflowExecuteUpdateOptions::default(),
800
851
  )
801
- .await
802
- .unwrap();
803
- assert!(!res.outcome.unwrap().is_success());
852
+ .await;
853
+ assert!(res.is_err());
804
854
  };
805
855
  let run = async {
806
856
  worker.run_until_done().await.unwrap();
@@ -816,41 +866,53 @@ async fn update_fail_sdk() {
816
866
  async fn update_timer_sequence() {
817
867
  let wf_name = "update_timer_sequence";
818
868
  let mut starter = CoreWfStarter::new(wf_name);
819
- starter
820
- .worker_config
821
- .task_types(WorkerTaskTypes::workflow_only());
869
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
822
870
  let mut worker = starter.worker().await;
823
- let client = starter.get_client().await;
824
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
825
- ctx.update_handler(
826
- "update",
827
- |_: &_, _: ()| Ok(()),
828
- move |ctx: UpdateContext, _: ()| async move {
829
- ctx.wf_ctx.timer(Duration::from_millis(1)).await;
830
- ctx.wf_ctx.timer(Duration::from_millis(1)).await;
831
- Ok("done")
832
- },
833
- );
834
- ctx.timer(Duration::from_secs(2)).await;
835
- Ok(().into())
836
- });
871
+ #[workflow]
872
+ #[derive(Default)]
873
+ struct UpdateTimerSequenceWf {
874
+ done: bool,
875
+ }
876
+
877
+ #[workflow_methods]
878
+ impl UpdateTimerSequenceWf {
879
+ #[run]
880
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
881
+ ctx.wait_condition(|s| s.done).await;
882
+ Ok(())
883
+ }
837
884
 
838
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
839
- let wf_id = starter.get_task_queue().to_string();
885
+ #[update]
886
+ async fn do_update(
887
+ ctx: &mut WorkflowContext<Self>,
888
+ _: (),
889
+ ) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
890
+ ctx.timer(Duration::from_millis(1)).await;
891
+ ctx.timer(Duration::from_millis(1)).await;
892
+ ctx.state_mut(|s| s.done = true);
893
+ Ok("done".to_string())
894
+ }
895
+ }
896
+
897
+ worker.register_workflow::<UpdateTimerSequenceWf>();
898
+ let task_queue = starter.get_task_queue().to_owned();
899
+ let handle = worker
900
+ .submit_workflow(
901
+ UpdateTimerSequenceWf::run,
902
+ (),
903
+ WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
904
+ )
905
+ .await
906
+ .unwrap();
840
907
  let update = async {
841
- let res = client
842
- .update_workflow_execution(
843
- wf_id.clone(),
844
- "".to_string(),
845
- "update".to_string(),
846
- WaitPolicy {
847
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
848
- },
849
- [().as_json_payload().unwrap()].into_payloads(),
908
+ let res = handle
909
+ .execute_update(
910
+ UpdateTimerSequenceWf::do_update,
911
+ (),
912
+ WorkflowExecuteUpdateOptions::default(),
850
913
  )
851
- .await
852
- .unwrap();
853
- assert!(res.outcome.unwrap().is_success());
914
+ .await;
915
+ assert!(res.unwrap() == "done");
854
916
  };
855
917
  let run = async {
856
918
  worker.run_until_done().await.unwrap();
@@ -866,44 +928,62 @@ async fn update_timer_sequence() {
866
928
  async fn task_failure_during_validation() {
867
929
  let wf_name = "task_failure_during_validation";
868
930
  let mut starter = CoreWfStarter::new(wf_name);
869
- starter
870
- .worker_config
871
- .task_types(WorkerTaskTypes::workflow_only());
931
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
872
932
  starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
873
933
  let mut worker = starter.worker().await;
874
- let client = starter.get_client().await;
875
- static FAILCT: AtomicUsize = AtomicUsize::new(0);
876
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
877
- ctx.update_handler(
878
- "update",
879
- |_: &_, _: ()| {
880
- if FAILCT.fetch_add(1, Ordering::Relaxed) < 2 {
881
- panic!("ahhhhhh");
882
- }
883
- Ok(())
884
- },
885
- move |_: UpdateContext, _: ()| async move { Ok("done") },
886
- );
887
- ctx.timer(Duration::from_secs(1)).await;
888
- Ok(().into())
889
- });
934
+ #[workflow]
935
+ #[derive(Default)]
936
+ struct TaskFailureDuringValidationWf;
937
+
938
+ #[workflow_methods]
939
+ impl TaskFailureDuringValidationWf {
940
+ #[run]
941
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
942
+ ctx.timer(Duration::from_secs(1)).await;
943
+ Ok(())
944
+ }
945
+
946
+ #[update_validator(do_update)]
947
+ fn validate_do_update(
948
+ &self,
949
+ _ctx: &WorkflowContextView,
950
+ _: &(),
951
+ ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
952
+ static FAILCT: AtomicUsize = AtomicUsize::new(0);
953
+ if FAILCT.fetch_add(1, Ordering::Relaxed) < 2 {
954
+ panic!("ahhhhhh");
955
+ }
956
+ Ok(())
957
+ }
958
+
959
+ #[update]
960
+ async fn do_update(
961
+ _ctx: &mut WorkflowContext<Self>,
962
+ _: (),
963
+ ) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
964
+ Ok("done".to_string())
965
+ }
966
+ }
890
967
 
891
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
892
- let wf_id = starter.get_task_queue().to_string();
968
+ worker.register_workflow::<TaskFailureDuringValidationWf>();
969
+ let task_queue = starter.get_task_queue().to_owned();
970
+ let handle = worker
971
+ .submit_workflow(
972
+ TaskFailureDuringValidationWf::run,
973
+ (),
974
+ WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
975
+ )
976
+ .await
977
+ .unwrap();
893
978
  let update = async {
894
- let res = client
895
- .update_workflow_execution(
896
- wf_id.clone(),
897
- "".to_string(),
898
- "update".to_string(),
899
- WaitPolicy {
900
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
901
- },
902
- [().as_json_payload().unwrap()].into_payloads(),
979
+ let res = handle
980
+ .execute_update(
981
+ TaskFailureDuringValidationWf::do_update,
982
+ (),
983
+ WorkflowExecuteUpdateOptions::default(),
903
984
  )
904
- .await
905
- .unwrap();
906
- assert!(res.outcome.unwrap().is_success());
985
+ .await;
986
+ assert!(res.unwrap() == "done");
907
987
  };
908
988
  let run = async {
909
989
  worker.run_until_done().await.unwrap();
@@ -929,42 +1009,53 @@ async fn task_failure_during_validation() {
929
1009
  async fn task_failure_after_update() {
930
1010
  let wf_name = "task_failure_after_update";
931
1011
  let mut starter = CoreWfStarter::new(wf_name);
932
- starter
933
- .worker_config
934
- .task_types(WorkerTaskTypes::workflow_only());
1012
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
935
1013
  starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
936
1014
  let mut worker = starter.worker().await;
937
- let client = starter.get_client().await;
938
- static FAILCT: AtomicUsize = AtomicUsize::new(0);
939
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
940
- ctx.update_handler(
941
- "update",
942
- |_: &_, _: ()| Ok(()),
943
- move |_: UpdateContext, _: ()| async move { Ok("done") },
944
- );
945
- ctx.timer(Duration::from_millis(1)).await;
946
- if FAILCT.fetch_add(1, Ordering::Relaxed) < 1 {
947
- panic!("ahhhhhh");
1015
+ #[workflow]
1016
+ #[derive(Default)]
1017
+ struct TaskFailureAfterUpdateWf;
1018
+
1019
+ #[workflow_methods]
1020
+ impl TaskFailureAfterUpdateWf {
1021
+ #[run]
1022
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
1023
+ static FAILCT: AtomicUsize = AtomicUsize::new(0);
1024
+ ctx.timer(Duration::from_millis(1)).await;
1025
+ if FAILCT.fetch_add(1, Ordering::Relaxed) < 1 {
1026
+ panic!("ahhhhhh");
1027
+ }
1028
+ Ok(())
948
1029
  }
949
- Ok(().into())
950
- });
951
1030
 
952
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
953
- let wf_id = starter.get_task_queue().to_string();
1031
+ #[update]
1032
+ async fn do_update(
1033
+ _ctx: &mut WorkflowContext<Self>,
1034
+ _: (),
1035
+ ) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
1036
+ Ok("done".to_string())
1037
+ }
1038
+ }
1039
+
1040
+ worker.register_workflow::<TaskFailureAfterUpdateWf>();
1041
+ let task_queue = starter.get_task_queue().to_owned();
1042
+ let handle = worker
1043
+ .submit_workflow(
1044
+ TaskFailureAfterUpdateWf::run,
1045
+ (),
1046
+ WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
1047
+ )
1048
+ .await
1049
+ .unwrap();
954
1050
  let update = async {
955
- let res = client
956
- .update_workflow_execution(
957
- wf_id.clone(),
958
- "".to_string(),
959
- "update".to_string(),
960
- WaitPolicy {
961
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
962
- },
963
- [().as_json_payload().unwrap()].into_payloads(),
1051
+ let res = handle
1052
+ .execute_update(
1053
+ TaskFailureAfterUpdateWf::do_update,
1054
+ (),
1055
+ WorkflowExecuteUpdateOptions::default(),
964
1056
  )
965
- .await
966
- .unwrap();
967
- assert!(res.outcome.unwrap().is_success());
1057
+ .await;
1058
+ assert!(res.unwrap() == "done");
968
1059
  };
969
1060
  let run = async {
970
1061
  worker.run_until_done().await.unwrap();
@@ -976,68 +1067,94 @@ async fn task_failure_after_update() {
976
1067
  .unwrap();
977
1068
  }
978
1069
 
1070
+ static BARR: LazyLock<Barrier> = LazyLock::new(|| Barrier::new(2));
1071
+ static ACT_RAN: AtomicBool = AtomicBool::new(false);
979
1072
  #[tokio::test]
980
1073
  async fn worker_restarted_in_middle_of_update() {
981
1074
  let wf_name = "worker_restarted_in_middle_of_update";
982
1075
  let mut starter = CoreWfStarter::new(wf_name);
1076
+
1077
+ struct BlockingActivities;
1078
+ #[activities]
1079
+ impl BlockingActivities {
1080
+ #[activity]
1081
+ async fn blocks(_ctx: ActivityContext, echo_me: String) -> Result<String, ActivityError> {
1082
+ BARR.wait().await;
1083
+ if !ACT_RAN.fetch_or(true, Ordering::Relaxed) {
1084
+ // On first run fail the task so we'll get retried on the new worker
1085
+ return Err(anyhow!("Fail first time").into());
1086
+ }
1087
+ Ok(echo_me)
1088
+ }
1089
+ }
1090
+
1091
+ starter.sdk_config.register_activities(BlockingActivities);
983
1092
  let mut worker = starter.worker().await;
984
1093
  let client = starter.get_client().await;
985
1094
 
986
- static BARR: LazyLock<Barrier> = LazyLock::new(|| Barrier::new(2));
987
- static ACT_RAN: AtomicBool = AtomicBool::new(false);
988
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
989
- ctx.update_handler(
990
- "update",
991
- |_: &_, _: ()| Ok(()),
992
- move |ctx: UpdateContext, _: ()| async move {
993
- ctx.wf_ctx
994
- .activity(ActivityOptions {
995
- activity_type: "blocks".to_string(),
996
- input: "hi!".as_json_payload().expect("serializes fine"),
997
- start_to_close_timeout: Some(Duration::from_secs(2)),
998
- ..Default::default()
999
- })
1000
- .await;
1001
- Ok(())
1002
- },
1003
- );
1004
- let mut sig = ctx.make_signal_channel("done");
1005
- sig.next().await;
1006
- Ok(().into())
1007
- });
1008
- worker.register_activity("blocks", |_ctx: ActContext, echo_me: String| async move {
1009
- BARR.wait().await;
1010
- if !ACT_RAN.fetch_or(true, Ordering::Relaxed) {
1011
- // On first run fail the task so we'll get retried on the new worker
1012
- return Err(anyhow!("Fail first time").into());
1095
+ #[workflow]
1096
+ #[derive(Default)]
1097
+ struct WorkerRestartedInMiddleOfUpdateWf {
1098
+ done: bool,
1099
+ }
1100
+
1101
+ #[workflow_methods]
1102
+ impl WorkerRestartedInMiddleOfUpdateWf {
1103
+ #[run]
1104
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
1105
+ ctx.wait_condition(|s| s.done).await;
1106
+ Ok(())
1013
1107
  }
1014
- Ok(echo_me)
1015
- });
1016
1108
 
1017
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
1109
+ #[signal]
1110
+ fn done_signal(&mut self, _ctx: &mut SyncWorkflowContext<Self>, _: ()) {
1111
+ self.done = true;
1112
+ }
1018
1113
 
1019
- let wf_id = starter.get_task_queue().to_string();
1020
- let update = async {
1021
- let res = client
1022
- .update_workflow_execution(
1023
- wf_id.clone(),
1024
- "".to_string(),
1025
- "update".to_string(),
1026
- WaitPolicy {
1027
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
1114
+ #[update]
1115
+ async fn do_update(
1116
+ ctx: &mut WorkflowContext<Self>,
1117
+ _: (),
1118
+ ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
1119
+ ctx.start_activity(
1120
+ BlockingActivities::blocks,
1121
+ "hi!".to_string(),
1122
+ ActivityOptions {
1123
+ start_to_close_timeout: Some(Duration::from_secs(2)),
1124
+ ..Default::default()
1028
1125
  },
1029
- [().as_json_payload().unwrap()].into_payloads(),
1030
1126
  )
1031
- .await
1032
- .unwrap();
1033
- assert!(res.outcome.unwrap().is_success());
1034
- client
1035
- .signal_workflow_execution(
1036
- wf_id.clone(),
1037
- "".to_string(),
1038
- "done".to_string(),
1039
- None,
1040
- None,
1127
+ .await?;
1128
+ Ok(())
1129
+ }
1130
+ }
1131
+
1132
+ worker.register_workflow::<WorkerRestartedInMiddleOfUpdateWf>();
1133
+ let task_queue = starter.get_task_queue().to_owned();
1134
+ let handle = worker
1135
+ .submit_workflow(
1136
+ WorkerRestartedInMiddleOfUpdateWf::run,
1137
+ (),
1138
+ WorkflowStartOptions::new(task_queue.clone(), starter.get_wf_id().to_owned()).build(),
1139
+ )
1140
+ .await
1141
+ .unwrap();
1142
+
1143
+ let wf_id = task_queue;
1144
+ let update = async {
1145
+ let res = handle
1146
+ .execute_update(
1147
+ WorkerRestartedInMiddleOfUpdateWf::do_update,
1148
+ (),
1149
+ WorkflowExecuteUpdateOptions::default(),
1150
+ )
1151
+ .await;
1152
+ assert!(res.is_ok());
1153
+ handle
1154
+ .signal(
1155
+ WorkerRestartedInMiddleOfUpdateWf::done_signal,
1156
+ (),
1157
+ WorkflowSignalOptions::default(),
1041
1158
  )
1042
1159
  .await
1043
1160
  .unwrap();
@@ -1051,10 +1168,19 @@ async fn worker_restarted_in_middle_of_update() {
1051
1168
  // Allow it to start again, the second time
1052
1169
  BARR.wait().await;
1053
1170
  // Poke the workflow off the sticky queue to get it to complete faster than WFT timeout
1054
- client
1055
- .reset_sticky_task_queue(wf_id.clone(), "".to_string())
1056
- .await
1057
- .unwrap();
1171
+ WorkflowService::reset_sticky_task_queue(
1172
+ &mut client.clone(),
1173
+ ResetStickyTaskQueueRequest {
1174
+ namespace: client.namespace(),
1175
+ execution: Some(WorkflowExecution {
1176
+ workflow_id: wf_id.clone(),
1177
+ run_id: "".to_string(),
1178
+ }),
1179
+ }
1180
+ .into_request(),
1181
+ )
1182
+ .await
1183
+ .unwrap();
1058
1184
  };
1059
1185
  let run = async {
1060
1186
  // This run attempt will get shut down
@@ -1076,79 +1202,94 @@ async fn worker_restarted_in_middle_of_update() {
1076
1202
  async fn update_after_empty_wft() {
1077
1203
  let wf_name = "update_after_empty_wft";
1078
1204
  let mut starter = CoreWfStarter::new(wf_name);
1205
+ starter.sdk_config.register_activities(StdActivities);
1079
1206
  let mut worker = starter.worker().await;
1080
- let client = starter.get_client().await;
1081
1207
 
1082
1208
  static ACT_STARTED: AtomicBool = AtomicBool::new(false);
1083
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| async move {
1084
- ctx.update_handler(
1085
- "update",
1086
- |_: &_, _: ()| Ok(()),
1087
- move |ctx: UpdateContext, _: ()| async move {
1088
- if ACT_STARTED.load(Ordering::Acquire) {
1089
- return Ok(());
1090
- }
1091
- ctx.wf_ctx
1092
- .activity(ActivityOptions {
1093
- activity_type: "echo".to_string(),
1094
- input: "hi!".as_json_payload().expect("serializes fine"),
1209
+
1210
+ #[workflow]
1211
+ #[derive(Default)]
1212
+ struct UpdateAfterEmptyWftWf {
1213
+ signal_received: bool,
1214
+ }
1215
+
1216
+ #[workflow_methods]
1217
+ impl UpdateAfterEmptyWftWf {
1218
+ #[run]
1219
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
1220
+ let sig_handle = async {
1221
+ ctx.wait_condition(|s| s.signal_received).await;
1222
+ ACT_STARTED.store(true, Ordering::Release);
1223
+ let _ = ctx
1224
+ .start_activity(
1225
+ StdActivities::echo,
1226
+ "hi!".to_string(),
1227
+ ActivityOptions {
1228
+ start_to_close_timeout: Some(Duration::from_secs(2)),
1229
+ ..Default::default()
1230
+ },
1231
+ )
1232
+ .await;
1233
+ ACT_STARTED.store(false, Ordering::Release);
1234
+ };
1235
+ join!(sig_handle, async {
1236
+ ctx.timer(Duration::from_secs(2)).await;
1237
+ });
1238
+ Ok(())
1239
+ }
1240
+
1241
+ #[signal]
1242
+ fn signal_handler(&mut self, _ctx: &mut SyncWorkflowContext<Self>, _: ()) {
1243
+ self.signal_received = true;
1244
+ }
1245
+
1246
+ #[update]
1247
+ async fn do_update(ctx: &mut WorkflowContext<Self>, _: ()) {
1248
+ if ACT_STARTED.load(Ordering::Acquire) {
1249
+ return;
1250
+ }
1251
+ let _ = ctx
1252
+ .start_activity(
1253
+ StdActivities::echo,
1254
+ "hi!".to_string(),
1255
+ ActivityOptions {
1095
1256
  start_to_close_timeout: Some(Duration::from_secs(2)),
1096
1257
  ..Default::default()
1097
- })
1098
- .await;
1099
- Ok(())
1100
- },
1101
- );
1102
- let mut sig = ctx.make_signal_channel("signal");
1103
- let sig_handle = async {
1104
- sig.next().await;
1105
- ACT_STARTED.store(true, Ordering::Release);
1106
- ctx.activity(ActivityOptions {
1107
- activity_type: "echo".to_string(),
1108
- input: "hi!".as_json_payload().expect("serializes fine"),
1109
- start_to_close_timeout: Some(Duration::from_secs(2)),
1110
- ..Default::default()
1111
- })
1112
- .await;
1113
- ACT_STARTED.store(false, Ordering::Release);
1114
- };
1115
- join!(sig_handle, async {
1116
- ctx.timer(Duration::from_secs(2)).await;
1117
- });
1118
- Ok(().into())
1119
- });
1120
- worker.register_activity("echo", |_ctx: ActContext, echo_me: String| async move {
1121
- Ok(echo_me)
1122
- });
1258
+ },
1259
+ )
1260
+ .await;
1261
+ }
1262
+ }
1123
1263
 
1124
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
1264
+ worker.register_workflow::<UpdateAfterEmptyWftWf>();
1265
+ let task_queue = starter.get_task_queue().to_owned();
1266
+ let handle = worker
1267
+ .submit_workflow(
1268
+ UpdateAfterEmptyWftWf::run,
1269
+ (),
1270
+ WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
1271
+ )
1272
+ .await
1273
+ .unwrap();
1125
1274
 
1126
- let wf_id = starter.get_task_queue().to_string();
1127
1275
  let update = async {
1128
- client
1129
- .signal_workflow_execution(
1130
- wf_id.clone(),
1131
- "".to_string(),
1132
- "signal".to_string(),
1133
- None,
1134
- None,
1276
+ handle
1277
+ .signal(
1278
+ UpdateAfterEmptyWftWf::signal_handler,
1279
+ (),
1280
+ WorkflowSignalOptions::default(),
1135
1281
  )
1136
1282
  .await
1137
1283
  .unwrap();
1138
1284
  tokio::time::sleep(Duration::from_millis(500)).await;
1139
- let res = client
1140
- .update_workflow_execution(
1141
- wf_id.clone(),
1142
- "".to_string(),
1143
- "update".to_string(),
1144
- WaitPolicy {
1145
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
1146
- },
1147
- [().as_json_payload().unwrap()].into_payloads(),
1285
+ handle
1286
+ .execute_update(
1287
+ UpdateAfterEmptyWftWf::do_update,
1288
+ (),
1289
+ WorkflowExecuteUpdateOptions::default(),
1148
1290
  )
1149
1291
  .await
1150
1292
  .unwrap();
1151
- assert!(res.outcome.unwrap().is_success());
1152
1293
  };
1153
1294
  let runner = async {
1154
1295
  worker.run_until_done().await.unwrap();
@@ -1164,64 +1305,69 @@ async fn update_after_empty_wft() {
1164
1305
  async fn update_lost_on_activity_mismatch() {
1165
1306
  let wf_name = "update_lost_on_activity_mismatch";
1166
1307
  let mut starter = CoreWfStarter::new(wf_name);
1308
+ starter.sdk_config.register_activities(StdActivities);
1167
1309
  let mut worker = starter.worker().await;
1168
- let client = starter.get_client().await;
1169
1310
 
1170
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| async move {
1171
- let can_run = Arc::new(AtomicUsize::new(1));
1172
- let cr = can_run.clone();
1173
- ctx.update_handler(
1174
- "update",
1175
- |_: &_, _: ()| Ok(()),
1176
- move |_: UpdateContext, _: ()| {
1177
- let cr = cr.clone();
1178
- async move {
1179
- cr.fetch_add(1, Ordering::Relaxed);
1180
- Ok(())
1181
- }
1182
- },
1183
- );
1184
- for _ in 1..=3 {
1185
- let cr = can_run.clone();
1186
- ctx.wait_condition(|| cr.load(Ordering::Relaxed) > 0).await;
1187
- ctx.activity(ActivityOptions {
1188
- activity_type: "echo".to_string(),
1189
- input: "hi!".as_json_payload().expect("serializes fine"),
1190
- start_to_close_timeout: Some(Duration::from_secs(2)),
1191
- ..Default::default()
1192
- })
1193
- .await;
1194
- can_run.fetch_sub(1, Ordering::Release);
1311
+ #[workflow]
1312
+ #[derive(Default)]
1313
+ struct UpdateLostOnActivityMismatchWf {
1314
+ can_run: usize,
1315
+ }
1316
+
1317
+ #[workflow_methods]
1318
+ impl UpdateLostOnActivityMismatchWf {
1319
+ #[run]
1320
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
1321
+ ctx.state_mut(|s| s.can_run = 1);
1322
+ for _ in 1..=3 {
1323
+ ctx.wait_condition(|s| s.can_run > 0).await;
1324
+ let _ = ctx
1325
+ .start_activity(
1326
+ StdActivities::echo,
1327
+ "hi!".to_string(),
1328
+ ActivityOptions {
1329
+ start_to_close_timeout: Some(Duration::from_secs(2)),
1330
+ ..Default::default()
1331
+ },
1332
+ )
1333
+ .await;
1334
+ ctx.state_mut(|s| s.can_run -= 1);
1335
+ }
1336
+ Ok(())
1195
1337
  }
1196
- Ok(().into())
1197
- });
1198
- worker.register_activity("echo", |_ctx: ActContext, echo_me: String| async move {
1199
- Ok(echo_me)
1200
- });
1201
1338
 
1202
- let core_worker = worker.core_worker.clone();
1203
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
1339
+ #[update]
1340
+ fn do_update(&mut self, _ctx: &mut SyncWorkflowContext<Self>, _: ()) {
1341
+ self.can_run += 1;
1342
+ }
1343
+ }
1344
+
1345
+ worker.register_workflow::<UpdateLostOnActivityMismatchWf>();
1346
+ let core_worker = worker.core_worker();
1347
+ let task_queue = starter.get_task_queue().to_owned();
1348
+ let handle = worker
1349
+ .submit_workflow(
1350
+ UpdateLostOnActivityMismatchWf::run,
1351
+ (),
1352
+ WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
1353
+ )
1354
+ .await
1355
+ .unwrap();
1204
1356
 
1205
- let wf_id = starter.get_task_queue().to_string();
1206
1357
  let update = async {
1207
1358
  // Need time to get to condition
1208
1359
  tokio::time::sleep(Duration::from_millis(200)).await;
1209
1360
  // Evict wf
1210
- core_worker.request_workflow_eviction(handle.info().run_id.as_ref().unwrap());
1361
+ core_worker.request_workflow_eviction(handle.run_id().unwrap());
1211
1362
  for _ in 1..=2 {
1212
- let res = client
1213
- .update_workflow_execution(
1214
- wf_id.clone(),
1215
- "".to_string(),
1216
- "update".to_string(),
1217
- WaitPolicy {
1218
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
1219
- },
1220
- [().as_json_payload().unwrap()].into_payloads(),
1363
+ handle
1364
+ .execute_update(
1365
+ UpdateLostOnActivityMismatchWf::do_update,
1366
+ (),
1367
+ WorkflowExecuteUpdateOptions::default(),
1221
1368
  )
1222
1369
  .await
1223
1370
  .unwrap();
1224
- assert!(res.outcome.unwrap().is_success());
1225
1371
  }
1226
1372
  };
1227
1373
  let runner = async {