@temporalio/core-bridge 1.15.0 → 1.16.1

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 (209) hide show
  1. package/Cargo.lock +172 -70
  2. package/lib/native.d.ts +1 -1
  3. package/package.json +2 -2
  4. package/releases/aarch64-apple-darwin/index.node +0 -0
  5. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  6. package/releases/x86_64-apple-darwin/index.node +0 -0
  7. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  8. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  9. package/sdk-core/.github/workflows/per-pr.yml +6 -6
  10. package/sdk-core/AGENTS.md +41 -30
  11. package/sdk-core/Cargo.toml +3 -0
  12. package/sdk-core/README.md +15 -9
  13. package/sdk-core/crates/client/Cargo.toml +4 -0
  14. package/sdk-core/crates/client/README.md +139 -0
  15. package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
  16. package/sdk-core/crates/client/src/callback_based.rs +7 -0
  17. package/sdk-core/crates/client/src/errors.rs +294 -0
  18. package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +280 -159
  19. package/sdk-core/crates/client/src/lib.rs +920 -1326
  20. package/sdk-core/crates/client/src/metrics.rs +24 -33
  21. package/sdk-core/crates/client/src/options_structs.rs +457 -0
  22. package/sdk-core/crates/client/src/replaceable.rs +5 -4
  23. package/sdk-core/crates/client/src/request_extensions.rs +8 -9
  24. package/sdk-core/crates/client/src/retry.rs +99 -54
  25. package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +1 -1
  26. package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
  27. package/sdk-core/crates/common/Cargo.toml +61 -2
  28. package/sdk-core/crates/common/build.rs +742 -12
  29. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
  30. package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
  31. package/sdk-core/crates/common/protos/api_upstream/buf.yaml +0 -3
  32. package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
  33. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +1166 -770
  34. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +1243 -750
  35. package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +2 -2
  36. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +4 -3
  37. package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
  38. package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +4 -0
  39. package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
  40. package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +16 -1
  41. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -6
  42. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +88 -33
  43. package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +4 -2
  44. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +4 -0
  45. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +5 -5
  46. package/sdk-core/crates/common/src/activity_definition.rs +20 -0
  47. package/sdk-core/crates/common/src/data_converters.rs +770 -0
  48. package/sdk-core/crates/common/src/envconfig.rs +5 -0
  49. package/sdk-core/crates/common/src/lib.rs +15 -211
  50. package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
  51. package/sdk-core/crates/common/src/priority.rs +110 -0
  52. package/sdk-core/crates/common/src/protos/canned_histories.rs +3 -0
  53. package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
  54. package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
  55. package/sdk-core/crates/common/src/protos/mod.rs +122 -27
  56. package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
  57. package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
  58. package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +5 -7
  59. package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
  60. package/sdk-core/crates/common/src/telemetry/metrics.rs +268 -223
  61. package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
  62. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
  63. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
  64. package/sdk-core/crates/common/src/telemetry.rs +264 -4
  65. package/sdk-core/crates/common/src/worker.rs +68 -603
  66. package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
  67. package/sdk-core/crates/macros/Cargo.toml +5 -1
  68. package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
  69. package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
  70. package/sdk-core/crates/macros/src/lib.rs +138 -512
  71. package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
  72. package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
  73. package/sdk-core/crates/sdk/Cargo.toml +19 -6
  74. package/sdk-core/crates/sdk/README.md +415 -0
  75. package/sdk-core/crates/sdk/src/activities.rs +417 -0
  76. package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
  77. package/sdk-core/crates/sdk/src/lib.rs +757 -442
  78. package/sdk-core/crates/sdk/src/workflow_context/options.rs +45 -35
  79. package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
  80. package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
  81. package/sdk-core/crates/sdk/src/workflows.rs +711 -0
  82. package/sdk-core/crates/sdk-core/Cargo.toml +57 -64
  83. package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +41 -35
  84. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
  85. package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
  86. package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
  87. package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +13 -15
  88. package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
  89. package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
  90. package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
  91. package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +493 -26
  92. package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +4 -8
  93. package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +7 -7
  94. package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
  95. package/sdk-core/crates/sdk-core/src/lib.rs +41 -111
  96. package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
  97. package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +118 -19
  98. package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
  99. package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
  100. package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +179 -196
  101. package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -280
  102. package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +6 -9
  103. package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
  104. package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
  105. package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
  106. package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +9 -5
  107. package/sdk-core/crates/sdk-core/src/worker/client.rs +103 -81
  108. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +7 -11
  109. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1124 -229
  110. package/sdk-core/crates/sdk-core/src/worker/nexus.rs +145 -23
  111. package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
  112. package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
  113. package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +13 -13
  114. package/sdk-core/crates/sdk-core/src/worker/tuner.rs +28 -8
  115. package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
  116. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
  117. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +19 -4
  118. package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +14 -18
  119. package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +4 -6
  120. package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
  121. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
  122. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
  123. package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
  124. package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
  125. package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
  126. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
  127. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
  128. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
  129. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
  130. package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
  131. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
  132. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
  133. package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
  134. package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
  135. package/sdk-core/crates/sdk-core/tests/common/mod.rs +241 -196
  136. package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
  137. package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +3 -5
  138. package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -64
  139. package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +298 -252
  140. package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
  141. package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
  142. package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
  143. package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +16 -12
  144. package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +48 -40
  145. package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +327 -255
  146. package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
  147. package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +147 -126
  148. package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
  149. package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -453
  150. package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
  151. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +360 -231
  152. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +248 -185
  153. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -43
  154. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
  155. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +428 -315
  156. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -56
  157. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -28
  158. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -243
  159. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
  160. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +101 -42
  161. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -147
  162. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -28
  163. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1036
  164. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -41
  165. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +397 -238
  166. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +414 -189
  167. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
  168. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
  169. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +154 -137
  170. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -105
  171. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -38
  172. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -40
  173. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -54
  174. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +363 -226
  175. package/sdk-core/crates/sdk-core/tests/main.rs +17 -15
  176. package/sdk-core/crates/sdk-core/tests/manual_tests.rs +207 -152
  177. package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +65 -34
  178. package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
  179. package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
  180. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
  181. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
  182. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
  183. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
  184. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
  185. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
  186. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
  187. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
  188. package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +7 -1
  189. package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +14 -14
  190. package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +83 -74
  191. package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +9 -14
  192. package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +1 -2
  193. package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +13 -13
  194. package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +6 -6
  195. package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +3 -4
  196. package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +62 -75
  197. package/sdk-core/rustfmt.toml +2 -1
  198. package/src/client.rs +205 -318
  199. package/src/metrics.rs +22 -30
  200. package/src/runtime.rs +4 -5
  201. package/src/worker.rs +16 -19
  202. package/ts/native.ts +1 -1
  203. package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
  204. package/sdk-core/crates/common/src/errors.rs +0 -85
  205. package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
  206. package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
  207. package/sdk-core/crates/sdk/src/app_data.rs +0 -37
  208. package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
  209. 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,35 +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.worker_config.task_types = WorkerTaskTypes::workflow_only();
746
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
728
747
  let mut worker = starter.worker().await;
729
- let client = starter.get_client().await;
730
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
731
- ctx.update_handler(
732
- "update",
733
- |_: &_, _: ()| Err(anyhow!("ahhhhh noooo")),
734
- move |_: UpdateContext, _: ()| async { Ok("hi") },
735
- );
736
- ctx.timer(Duration::from_secs(1)).await;
737
- Ok(().into())
738
- });
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
+ }
739
777
 
740
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
741
- 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();
742
788
  let update = async {
743
- let res = client
744
- .update_workflow_execution(
745
- wf_id.clone(),
746
- "".to_string(),
747
- "update".to_string(),
748
- WaitPolicy {
749
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
750
- },
751
- [().as_json_payload().unwrap()].into_payloads(),
789
+ let res = handle
790
+ .execute_update(
791
+ UpdateRejectionSdkWf::do_update,
792
+ (),
793
+ WorkflowExecuteUpdateOptions::default(),
752
794
  )
753
- .await
754
- .unwrap();
755
- assert!(!res.outcome.unwrap().is_success());
795
+ .await;
796
+ assert!(res.is_err());
756
797
  };
757
798
  let run = async {
758
799
  worker.run_until_done().await.unwrap();
@@ -768,35 +809,48 @@ async fn update_rejection_sdk() {
768
809
  async fn update_fail_sdk() {
769
810
  let wf_name = "update_fail_sdk";
770
811
  let mut starter = CoreWfStarter::new(wf_name);
771
- starter.worker_config.task_types = WorkerTaskTypes::workflow_only();
812
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
772
813
  let mut worker = starter.worker().await;
773
- let client = starter.get_client().await;
774
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
775
- ctx.update_handler(
776
- "update",
777
- |_: &_, _: ()| Ok(()),
778
- move |_: UpdateContext, _: ()| async { Err::<(), _>(anyhow!("nooooo")) },
779
- );
780
- ctx.timer(Duration::from_secs(1)).await;
781
- Ok(().into())
782
- });
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
+ }
783
834
 
784
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
785
- 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();
786
845
  let update = async {
787
- let res = client
788
- .update_workflow_execution(
789
- wf_id.clone(),
790
- "".to_string(),
791
- "update".to_string(),
792
- WaitPolicy {
793
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
794
- },
795
- [().as_json_payload().unwrap()].into_payloads(),
846
+ let res = handle
847
+ .execute_update(
848
+ UpdateFailSdkWf::do_update,
849
+ (),
850
+ WorkflowExecuteUpdateOptions::default(),
796
851
  )
797
- .await
798
- .unwrap();
799
- assert!(!res.outcome.unwrap().is_success());
852
+ .await;
853
+ assert!(res.is_err());
800
854
  };
801
855
  let run = async {
802
856
  worker.run_until_done().await.unwrap();
@@ -812,39 +866,53 @@ async fn update_fail_sdk() {
812
866
  async fn update_timer_sequence() {
813
867
  let wf_name = "update_timer_sequence";
814
868
  let mut starter = CoreWfStarter::new(wf_name);
815
- starter.worker_config.task_types = WorkerTaskTypes::workflow_only();
869
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
816
870
  let mut worker = starter.worker().await;
817
- let client = starter.get_client().await;
818
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
819
- ctx.update_handler(
820
- "update",
821
- |_: &_, _: ()| Ok(()),
822
- move |ctx: UpdateContext, _: ()| async move {
823
- ctx.wf_ctx.timer(Duration::from_millis(1)).await;
824
- ctx.wf_ctx.timer(Duration::from_millis(1)).await;
825
- Ok("done")
826
- },
827
- );
828
- ctx.timer(Duration::from_secs(2)).await;
829
- Ok(().into())
830
- });
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
+ }
831
884
 
832
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
833
- 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();
834
907
  let update = async {
835
- let res = client
836
- .update_workflow_execution(
837
- wf_id.clone(),
838
- "".to_string(),
839
- "update".to_string(),
840
- WaitPolicy {
841
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
842
- },
843
- [().as_json_payload().unwrap()].into_payloads(),
908
+ let res = handle
909
+ .execute_update(
910
+ UpdateTimerSequenceWf::do_update,
911
+ (),
912
+ WorkflowExecuteUpdateOptions::default(),
844
913
  )
845
- .await
846
- .unwrap();
847
- assert!(res.outcome.unwrap().is_success());
914
+ .await;
915
+ assert!(res.unwrap() == "done");
848
916
  };
849
917
  let run = async {
850
918
  worker.run_until_done().await.unwrap();
@@ -860,42 +928,62 @@ async fn update_timer_sequence() {
860
928
  async fn task_failure_during_validation() {
861
929
  let wf_name = "task_failure_during_validation";
862
930
  let mut starter = CoreWfStarter::new(wf_name);
863
- starter.worker_config.task_types = WorkerTaskTypes::workflow_only();
931
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
864
932
  starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
865
933
  let mut worker = starter.worker().await;
866
- let client = starter.get_client().await;
867
- static FAILCT: AtomicUsize = AtomicUsize::new(0);
868
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
869
- ctx.update_handler(
870
- "update",
871
- |_: &_, _: ()| {
872
- if FAILCT.fetch_add(1, Ordering::Relaxed) < 2 {
873
- panic!("ahhhhhh");
874
- }
875
- Ok(())
876
- },
877
- move |_: UpdateContext, _: ()| async move { Ok("done") },
878
- );
879
- ctx.timer(Duration::from_secs(1)).await;
880
- Ok(().into())
881
- });
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
+ }
882
967
 
883
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
884
- 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();
885
978
  let update = async {
886
- let res = client
887
- .update_workflow_execution(
888
- wf_id.clone(),
889
- "".to_string(),
890
- "update".to_string(),
891
- WaitPolicy {
892
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
893
- },
894
- [().as_json_payload().unwrap()].into_payloads(),
979
+ let res = handle
980
+ .execute_update(
981
+ TaskFailureDuringValidationWf::do_update,
982
+ (),
983
+ WorkflowExecuteUpdateOptions::default(),
895
984
  )
896
- .await
897
- .unwrap();
898
- assert!(res.outcome.unwrap().is_success());
985
+ .await;
986
+ assert!(res.unwrap() == "done");
899
987
  };
900
988
  let run = async {
901
989
  worker.run_until_done().await.unwrap();
@@ -921,40 +1009,53 @@ async fn task_failure_during_validation() {
921
1009
  async fn task_failure_after_update() {
922
1010
  let wf_name = "task_failure_after_update";
923
1011
  let mut starter = CoreWfStarter::new(wf_name);
924
- starter.worker_config.task_types = WorkerTaskTypes::workflow_only();
1012
+ starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
925
1013
  starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
926
1014
  let mut worker = starter.worker().await;
927
- let client = starter.get_client().await;
928
- static FAILCT: AtomicUsize = AtomicUsize::new(0);
929
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
930
- ctx.update_handler(
931
- "update",
932
- |_: &_, _: ()| Ok(()),
933
- move |_: UpdateContext, _: ()| async move { Ok("done") },
934
- );
935
- ctx.timer(Duration::from_millis(1)).await;
936
- if FAILCT.fetch_add(1, Ordering::Relaxed) < 1 {
937
- 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(())
938
1029
  }
939
- Ok(().into())
940
- });
941
1030
 
942
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
943
- 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();
944
1050
  let update = async {
945
- let res = client
946
- .update_workflow_execution(
947
- wf_id.clone(),
948
- "".to_string(),
949
- "update".to_string(),
950
- WaitPolicy {
951
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
952
- },
953
- [().as_json_payload().unwrap()].into_payloads(),
1051
+ let res = handle
1052
+ .execute_update(
1053
+ TaskFailureAfterUpdateWf::do_update,
1054
+ (),
1055
+ WorkflowExecuteUpdateOptions::default(),
954
1056
  )
955
- .await
956
- .unwrap();
957
- assert!(res.outcome.unwrap().is_success());
1057
+ .await;
1058
+ assert!(res.unwrap() == "done");
958
1059
  };
959
1060
  let run = async {
960
1061
  worker.run_until_done().await.unwrap();
@@ -966,68 +1067,94 @@ async fn task_failure_after_update() {
966
1067
  .unwrap();
967
1068
  }
968
1069
 
1070
+ static BARR: LazyLock<Barrier> = LazyLock::new(|| Barrier::new(2));
1071
+ static ACT_RAN: AtomicBool = AtomicBool::new(false);
969
1072
  #[tokio::test]
970
1073
  async fn worker_restarted_in_middle_of_update() {
971
1074
  let wf_name = "worker_restarted_in_middle_of_update";
972
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);
973
1092
  let mut worker = starter.worker().await;
974
1093
  let client = starter.get_client().await;
975
1094
 
976
- static BARR: LazyLock<Barrier> = LazyLock::new(|| Barrier::new(2));
977
- static ACT_RAN: AtomicBool = AtomicBool::new(false);
978
- worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
979
- ctx.update_handler(
980
- "update",
981
- |_: &_, _: ()| Ok(()),
982
- move |ctx: UpdateContext, _: ()| async move {
983
- ctx.wf_ctx
984
- .activity(ActivityOptions {
985
- activity_type: "blocks".to_string(),
986
- input: "hi!".as_json_payload().expect("serializes fine"),
987
- start_to_close_timeout: Some(Duration::from_secs(2)),
988
- ..Default::default()
989
- })
990
- .await;
991
- Ok(())
992
- },
993
- );
994
- let mut sig = ctx.make_signal_channel("done");
995
- sig.next().await;
996
- Ok(().into())
997
- });
998
- worker.register_activity("blocks", |_ctx: ActContext, echo_me: String| async move {
999
- BARR.wait().await;
1000
- if !ACT_RAN.fetch_or(true, Ordering::Relaxed) {
1001
- // On first run fail the task so we'll get retried on the new worker
1002
- 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(())
1003
1107
  }
1004
- Ok(echo_me)
1005
- });
1006
1108
 
1007
- 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
+ }
1008
1113
 
1009
- let wf_id = starter.get_task_queue().to_string();
1010
- let update = async {
1011
- let res = client
1012
- .update_workflow_execution(
1013
- wf_id.clone(),
1014
- "".to_string(),
1015
- "update".to_string(),
1016
- WaitPolicy {
1017
- 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()
1018
1125
  },
1019
- [().as_json_payload().unwrap()].into_payloads(),
1020
1126
  )
1021
- .await
1022
- .unwrap();
1023
- assert!(res.outcome.unwrap().is_success());
1024
- client
1025
- .signal_workflow_execution(
1026
- wf_id.clone(),
1027
- "".to_string(),
1028
- "done".to_string(),
1029
- None,
1030
- 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(),
1031
1158
  )
1032
1159
  .await
1033
1160
  .unwrap();
@@ -1041,10 +1168,19 @@ async fn worker_restarted_in_middle_of_update() {
1041
1168
  // Allow it to start again, the second time
1042
1169
  BARR.wait().await;
1043
1170
  // Poke the workflow off the sticky queue to get it to complete faster than WFT timeout
1044
- client
1045
- .reset_sticky_task_queue(wf_id.clone(), "".to_string())
1046
- .await
1047
- .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();
1048
1184
  };
1049
1185
  let run = async {
1050
1186
  // This run attempt will get shut down
@@ -1066,79 +1202,94 @@ async fn worker_restarted_in_middle_of_update() {
1066
1202
  async fn update_after_empty_wft() {
1067
1203
  let wf_name = "update_after_empty_wft";
1068
1204
  let mut starter = CoreWfStarter::new(wf_name);
1205
+ starter.sdk_config.register_activities(StdActivities);
1069
1206
  let mut worker = starter.worker().await;
1070
- let client = starter.get_client().await;
1071
1207
 
1072
1208
  static ACT_STARTED: AtomicBool = AtomicBool::new(false);
1073
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| async move {
1074
- ctx.update_handler(
1075
- "update",
1076
- |_: &_, _: ()| Ok(()),
1077
- move |ctx: UpdateContext, _: ()| async move {
1078
- if ACT_STARTED.load(Ordering::Acquire) {
1079
- return Ok(());
1080
- }
1081
- ctx.wf_ctx
1082
- .activity(ActivityOptions {
1083
- activity_type: "echo".to_string(),
1084
- 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 {
1085
1256
  start_to_close_timeout: Some(Duration::from_secs(2)),
1086
1257
  ..Default::default()
1087
- })
1088
- .await;
1089
- Ok(())
1090
- },
1091
- );
1092
- let mut sig = ctx.make_signal_channel("signal");
1093
- let sig_handle = async {
1094
- sig.next().await;
1095
- ACT_STARTED.store(true, Ordering::Release);
1096
- ctx.activity(ActivityOptions {
1097
- activity_type: "echo".to_string(),
1098
- input: "hi!".as_json_payload().expect("serializes fine"),
1099
- start_to_close_timeout: Some(Duration::from_secs(2)),
1100
- ..Default::default()
1101
- })
1102
- .await;
1103
- ACT_STARTED.store(false, Ordering::Release);
1104
- };
1105
- join!(sig_handle, async {
1106
- ctx.timer(Duration::from_secs(2)).await;
1107
- });
1108
- Ok(().into())
1109
- });
1110
- worker.register_activity("echo", |_ctx: ActContext, echo_me: String| async move {
1111
- Ok(echo_me)
1112
- });
1258
+ },
1259
+ )
1260
+ .await;
1261
+ }
1262
+ }
1113
1263
 
1114
- 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();
1115
1274
 
1116
- let wf_id = starter.get_task_queue().to_string();
1117
1275
  let update = async {
1118
- client
1119
- .signal_workflow_execution(
1120
- wf_id.clone(),
1121
- "".to_string(),
1122
- "signal".to_string(),
1123
- None,
1124
- None,
1276
+ handle
1277
+ .signal(
1278
+ UpdateAfterEmptyWftWf::signal_handler,
1279
+ (),
1280
+ WorkflowSignalOptions::default(),
1125
1281
  )
1126
1282
  .await
1127
1283
  .unwrap();
1128
1284
  tokio::time::sleep(Duration::from_millis(500)).await;
1129
- let res = client
1130
- .update_workflow_execution(
1131
- wf_id.clone(),
1132
- "".to_string(),
1133
- "update".to_string(),
1134
- WaitPolicy {
1135
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
1136
- },
1137
- [().as_json_payload().unwrap()].into_payloads(),
1285
+ handle
1286
+ .execute_update(
1287
+ UpdateAfterEmptyWftWf::do_update,
1288
+ (),
1289
+ WorkflowExecuteUpdateOptions::default(),
1138
1290
  )
1139
1291
  .await
1140
1292
  .unwrap();
1141
- assert!(res.outcome.unwrap().is_success());
1142
1293
  };
1143
1294
  let runner = async {
1144
1295
  worker.run_until_done().await.unwrap();
@@ -1154,64 +1305,69 @@ async fn update_after_empty_wft() {
1154
1305
  async fn update_lost_on_activity_mismatch() {
1155
1306
  let wf_name = "update_lost_on_activity_mismatch";
1156
1307
  let mut starter = CoreWfStarter::new(wf_name);
1308
+ starter.sdk_config.register_activities(StdActivities);
1157
1309
  let mut worker = starter.worker().await;
1158
- let client = starter.get_client().await;
1159
1310
 
1160
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| async move {
1161
- let can_run = Arc::new(AtomicUsize::new(1));
1162
- let cr = can_run.clone();
1163
- ctx.update_handler(
1164
- "update",
1165
- |_: &_, _: ()| Ok(()),
1166
- move |_: UpdateContext, _: ()| {
1167
- let cr = cr.clone();
1168
- async move {
1169
- cr.fetch_add(1, Ordering::Relaxed);
1170
- Ok(())
1171
- }
1172
- },
1173
- );
1174
- for _ in 1..=3 {
1175
- let cr = can_run.clone();
1176
- ctx.wait_condition(|| cr.load(Ordering::Relaxed) > 0).await;
1177
- ctx.activity(ActivityOptions {
1178
- activity_type: "echo".to_string(),
1179
- input: "hi!".as_json_payload().expect("serializes fine"),
1180
- start_to_close_timeout: Some(Duration::from_secs(2)),
1181
- ..Default::default()
1182
- })
1183
- .await;
1184
- 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(())
1185
1337
  }
1186
- Ok(().into())
1187
- });
1188
- worker.register_activity("echo", |_ctx: ActContext, echo_me: String| async move {
1189
- Ok(echo_me)
1190
- });
1191
1338
 
1192
- let core_worker = worker.core_worker.clone();
1193
- 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();
1194
1356
 
1195
- let wf_id = starter.get_task_queue().to_string();
1196
1357
  let update = async {
1197
1358
  // Need time to get to condition
1198
1359
  tokio::time::sleep(Duration::from_millis(200)).await;
1199
1360
  // Evict wf
1200
- core_worker.request_workflow_eviction(handle.info().run_id.as_ref().unwrap());
1361
+ core_worker.request_workflow_eviction(handle.run_id().unwrap());
1201
1362
  for _ in 1..=2 {
1202
- let res = client
1203
- .update_workflow_execution(
1204
- wf_id.clone(),
1205
- "".to_string(),
1206
- "update".to_string(),
1207
- WaitPolicy {
1208
- lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
1209
- },
1210
- [().as_json_payload().unwrap()].into_payloads(),
1363
+ handle
1364
+ .execute_update(
1365
+ UpdateLostOnActivityMismatchWf::do_update,
1366
+ (),
1367
+ WorkflowExecuteUpdateOptions::default(),
1211
1368
  )
1212
1369
  .await
1213
1370
  .unwrap();
1214
- assert!(res.outcome.unwrap().is_success());
1215
1371
  }
1216
1372
  };
1217
1373
  let runner = async {