@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
@@ -2,7 +2,7 @@ use crate::{
2
2
  common::{CoreWfStarter, WorkflowHandleExt, rand_6_chars},
3
3
  integ_tests::mk_nexus_endpoint,
4
4
  };
5
- use anyhow::bail;
5
+ use anyhow::anyhow;
6
6
  use assert_matches::assert_matches;
7
7
  use std::{
8
8
  sync::{
@@ -11,9 +11,15 @@ use std::{
11
11
  },
12
12
  time::Duration,
13
13
  };
14
- use temporalio_client::{WfClientExt, WorkflowClientTrait, WorkflowOptions};
14
+ use temporalio_client::{
15
+ UntypedSignal, UntypedWorkflow, WorkflowCancelOptions, WorkflowSignalOptions,
16
+ WorkflowStartOptions,
17
+ };
15
18
  use temporalio_common::{
16
- errors::PollError,
19
+ data_converters::{
20
+ GenericPayloadConverter, PayloadConverter, RawValue, SerializationContext,
21
+ SerializationContextData,
22
+ },
17
23
  protos::{
18
24
  coresdk::{
19
25
  FromJsonPayloadExt,
@@ -35,15 +41,19 @@ use temporalio_common::{
35
41
  },
36
42
  worker::WorkerTaskTypes,
37
43
  };
38
- use temporalio_sdk::{CancellableFuture, NexusOperationOptions, WfContext, WfExitValue};
44
+ use temporalio_macros::{workflow, workflow_methods};
45
+ use temporalio_sdk::{
46
+ CancellableFuture, NexusOperationOptions, SyncWorkflowContext, WorkflowContext,
47
+ WorkflowContextView, WorkflowResult, WorkflowTermination,
48
+ };
49
+ use temporalio_sdk_core::PollError;
39
50
  use tokio::{
40
51
  join,
41
52
  sync::{mpsc, watch},
42
53
  };
43
- use tokio_stream::StreamExt;
44
54
 
45
- #[derive(Debug, PartialEq, Eq, Clone, Copy)]
46
- enum Outcome {
55
+ #[derive(Debug, PartialEq, Eq, Clone, Copy, serde::Serialize, serde::Deserialize)]
56
+ pub(crate) enum Outcome {
47
57
  Succeed,
48
58
  Fail,
49
59
  Cancel,
@@ -51,6 +61,43 @@ enum Outcome {
51
61
  Timeout,
52
62
  }
53
63
 
64
+ #[workflow]
65
+ #[derive(Default)]
66
+ struct NexusBasicWf {
67
+ endpoint: String,
68
+ }
69
+
70
+ #[workflow_methods]
71
+ impl NexusBasicWf {
72
+ #[init]
73
+ fn new(_ctx: &WorkflowContextView, endpoint: String) -> Self {
74
+ Self { endpoint }
75
+ }
76
+
77
+ #[run]
78
+ pub(crate) async fn run(
79
+ ctx: &mut WorkflowContext<Self>,
80
+ ) -> WorkflowResult<Result<NexusOperationResult, Failure>> {
81
+ match ctx
82
+ .start_nexus_operation(NexusOperationOptions {
83
+ endpoint: ctx.state(|wf| wf.endpoint.clone()),
84
+ service: "svc".to_string(),
85
+ operation: "op".to_string(),
86
+ schedule_to_close_timeout: Some(Duration::from_secs(3)),
87
+ ..Default::default()
88
+ })
89
+ .await
90
+ {
91
+ Ok(started) => {
92
+ assert_eq!(started.operation_token, None);
93
+ let res = started.result().await;
94
+ Ok(Ok(res))
95
+ }
96
+ Err(failure) => Ok(Err(failure)),
97
+ }
98
+ }
99
+ }
100
+
54
101
  #[rstest::rstest]
55
102
  #[tokio::test]
56
103
  async fn nexus_basic(
@@ -58,42 +105,28 @@ async fn nexus_basic(
58
105
  ) {
59
106
  let wf_name = "nexus_basic";
60
107
  let mut starter = CoreWfStarter::new(wf_name);
61
- starter.worker_config.task_types(WorkerTaskTypes {
108
+ starter.sdk_config.task_types = WorkerTaskTypes {
62
109
  enable_workflows: true,
63
110
  enable_local_activities: false,
64
111
  enable_remote_activities: false,
65
112
  enable_nexus: true,
66
- });
113
+ };
67
114
  let mut worker = starter.worker().await;
68
115
  let core_worker = starter.get_worker().await;
69
116
 
70
117
  let endpoint = mk_nexus_endpoint(&mut starter).await;
71
118
 
72
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| {
73
- let endpoint = endpoint.clone();
74
- async move {
75
- match ctx
76
- .start_nexus_operation(NexusOperationOptions {
77
- endpoint,
78
- service: "svc".to_string(),
79
- operation: "op".to_string(),
80
- schedule_to_close_timeout: Some(Duration::from_secs(3)),
81
- ..Default::default()
82
- })
83
- .await
84
- {
85
- Ok(started) => {
86
- assert_eq!(started.operation_token, None);
87
- let res = started.result().await;
88
- Ok(Ok(res).into())
89
- }
90
- Err(failure) => Ok(Err(failure).into()),
91
- }
92
- }
93
- });
94
- let wf_handle = starter.start_with_worker(wf_name, &mut worker).await;
119
+ worker.register_workflow::<NexusBasicWf>();
120
+ let wf_handle = worker
121
+ .submit_workflow(
122
+ NexusBasicWf::run,
123
+ endpoint.clone(),
124
+ starter.workflow_options.clone(),
125
+ )
126
+ .await
127
+ .unwrap();
95
128
 
96
- let client = starter.get_client().await.get_client().clone();
129
+ let client = starter.get_client().await;
97
130
  let nexus_task_handle = async {
98
131
  let nt = core_worker.poll_nexus_task().await.unwrap().unwrap_task();
99
132
  match outcome {
@@ -132,6 +165,7 @@ async fn nexus_basic(
132
165
  core_worker
133
166
  .complete_nexus_task(NexusTaskCompletion {
134
167
  task_token: nt.task_token,
168
+ #[allow(deprecated)]
135
169
  status: Some(nexus_task_completion::Status::Error(HandlerError {
136
170
  error_type: "BAD_REQUEST".to_string(), // bad req is non-retryable
137
171
  failure: Some(nexus::v1::Failure {
@@ -157,12 +191,13 @@ async fn nexus_basic(
157
191
  });
158
192
 
159
193
  let res = client
160
- .get_untyped_workflow_handle(starter.get_task_queue().to_owned(), "")
161
- .get_workflow_result(Default::default())
194
+ .get_workflow_handle::<UntypedWorkflow>(starter.get_task_queue().to_owned())
195
+ .get_result(Default::default())
162
196
  .await
163
197
  .unwrap();
164
- let res = Result::<NexusOperationResult, Failure>::from_json_payload(&res.unwrap_success()[0])
165
- .unwrap();
198
+ let res =
199
+ Result::<NexusOperationResult, Failure>::from_json_payload(res.payloads.first().unwrap())
200
+ .unwrap();
166
201
  match outcome {
167
202
  Outcome::Succeed => {
168
203
  let p = assert_matches!(
@@ -194,6 +229,80 @@ async fn nexus_basic(
194
229
  .unwrap();
195
230
  }
196
231
 
232
+ #[workflow]
233
+ struct NexusAsyncWf {
234
+ endpoint: String,
235
+ schedule_to_close_timeout: Option<Duration>,
236
+ outcome: Outcome,
237
+ }
238
+
239
+ #[workflow_methods]
240
+ impl NexusAsyncWf {
241
+ #[init]
242
+ fn new(
243
+ _ctx: &WorkflowContextView,
244
+ (endpoint, schedule_to_close_timeout, outcome): (String, Option<Duration>, Outcome),
245
+ ) -> Self {
246
+ Self {
247
+ endpoint,
248
+ schedule_to_close_timeout,
249
+ outcome,
250
+ }
251
+ }
252
+
253
+ #[run]
254
+ pub(crate) async fn run(
255
+ ctx: &mut WorkflowContext<Self>,
256
+ ) -> WorkflowResult<NexusOperationResult> {
257
+ let started = ctx.start_nexus_operation(NexusOperationOptions {
258
+ endpoint: ctx.state(|wf| wf.endpoint.clone()),
259
+ service: "svc".to_string(),
260
+ operation: "op".to_string(),
261
+ schedule_to_close_timeout: ctx.state(|wf| wf.schedule_to_close_timeout),
262
+ ..Default::default()
263
+ });
264
+ if ctx.state(|wf| wf.outcome) == Outcome::CancelAfterRecordedBeforeStarted {
265
+ ctx.timer(Duration::from_millis(1)).await;
266
+ started.cancel();
267
+ }
268
+ let started = started.await.unwrap();
269
+ let result = started.result();
270
+ if matches!(ctx.state(|wf| wf.outcome), Outcome::Cancel) {
271
+ started.cancel();
272
+ started.cancel();
273
+ }
274
+ let res = result.await;
275
+ started.cancel();
276
+ Ok(res)
277
+ }
278
+ }
279
+
280
+ #[workflow]
281
+ struct AsyncCompleter {
282
+ outcome: Outcome,
283
+ }
284
+
285
+ #[workflow_methods]
286
+ impl AsyncCompleter {
287
+ #[init]
288
+ fn new(_ctx: &WorkflowContextView, outcome: Outcome) -> Self {
289
+ Self { outcome }
290
+ }
291
+
292
+ #[allow(dead_code)] // Started via untyped submitter handle
293
+ #[run]
294
+ pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> {
295
+ match ctx.state(|wf| wf.outcome) {
296
+ Outcome::Succeed => Ok("completed async".to_string()),
297
+ Outcome::Cancel | Outcome::CancelAfterRecordedBeforeStarted => {
298
+ ctx.cancelled().await;
299
+ Err(WorkflowTermination::Cancelled)
300
+ }
301
+ _ => Err(anyhow!("broken").into()),
302
+ }
303
+ }
304
+ }
305
+
197
306
  #[rstest::rstest]
198
307
  #[tokio::test]
199
308
  async fn nexus_async(
@@ -208,67 +317,40 @@ async fn nexus_async(
208
317
  ) {
209
318
  let wf_name = "nexus_async";
210
319
  let mut starter = CoreWfStarter::new(wf_name);
211
- starter.worker_config.task_types(WorkerTaskTypes {
320
+ starter.sdk_config.task_types = WorkerTaskTypes {
212
321
  enable_workflows: true,
213
322
  enable_local_activities: false,
214
323
  enable_remote_activities: false,
215
324
  enable_nexus: true,
216
- });
325
+ };
217
326
  let mut worker = starter.worker().await;
218
327
  let core_worker = starter.get_worker().await;
219
328
 
220
329
  let endpoint = mk_nexus_endpoint(&mut starter).await;
221
330
  let schedule_to_close_timeout = if outcome == Outcome::CancelAfterRecordedBeforeStarted {
222
- // If we set this, it'll time out before we can cancel it.
223
331
  None
224
332
  } else {
225
333
  Some(Duration::from_secs(5))
226
334
  };
227
335
 
228
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| {
229
- let endpoint = endpoint.clone();
230
- async move {
231
- let started = ctx.start_nexus_operation(NexusOperationOptions {
232
- endpoint,
233
- service: "svc".to_string(),
234
- operation: "op".to_string(),
235
- schedule_to_close_timeout,
236
- ..Default::default()
237
- });
238
- if outcome == Outcome::CancelAfterRecordedBeforeStarted {
239
- ctx.timer(Duration::from_millis(1)).await;
240
- started.cancel(&ctx);
241
- }
242
- let started = started.await.unwrap();
243
- let result = started.result();
244
- if matches!(outcome, Outcome::Cancel) {
245
- started.cancel(&ctx);
246
- // Make sure double-cancel doesn't cause problems
247
- started.cancel(&ctx);
248
- }
249
- let res = result.await;
250
- // Make sure cancel after completion doesn't cause problems
251
- started.cancel(&ctx);
252
- Ok(res.into())
253
- }
254
- });
255
- worker.register_wf(
256
- "async_completer".to_owned(),
257
- move |ctx: WfContext| async move {
258
- match outcome {
259
- Outcome::Succeed => Ok("completed async".into()),
260
- Outcome::Cancel | Outcome::CancelAfterRecordedBeforeStarted => {
261
- ctx.cancelled().await;
262
- Ok(WfExitValue::Cancelled)
263
- }
264
- _ => bail!("broken"),
265
- }
266
- },
267
- );
336
+ worker.register_workflow::<NexusAsyncWf>();
337
+ worker.register_workflow::<AsyncCompleter>();
268
338
  let submitter = worker.get_submitter_handle();
269
- let wf_handle = starter.start_with_worker(wf_name, &mut worker).await;
339
+ let converter = PayloadConverter::default();
340
+ let ser_ctx = SerializationContext {
341
+ data: &SerializationContextData::Workflow,
342
+ converter: &converter,
343
+ };
344
+ let wf_handle = worker
345
+ .submit_workflow(
346
+ NexusAsyncWf::run,
347
+ (endpoint.clone(), schedule_to_close_timeout, outcome),
348
+ starter.workflow_options.clone(),
349
+ )
350
+ .await
351
+ .unwrap();
270
352
 
271
- let client = starter.get_client().await.get_client().clone();
353
+ let client = starter.get_client().await;
272
354
  let nexus_task_handle = async {
273
355
  let mut nt = core_worker.poll_nexus_task().await.unwrap().unwrap_task();
274
356
  // Verify request header key for timeout exists and is lowercase
@@ -311,23 +393,22 @@ async fn nexus_async(
311
393
 
312
394
  // Start the workflow which will act like the nexus handler and complete the async
313
395
  // operation
396
+ let payloads = vec![converter.to_payload(&ser_ctx, &outcome).unwrap()];
397
+ let task_queue = starter.get_task_queue().to_owned();
314
398
  submitter
315
399
  .submit_wf(
316
- completer_id.clone(),
317
- "async_completer",
318
- vec![],
319
- WorkflowOptions {
320
- completion_callbacks: vec![Callback {
400
+ AsyncCompleter::name(),
401
+ payloads,
402
+ WorkflowStartOptions::new(task_queue, completer_id.clone())
403
+ .completion_callbacks(vec![Callback {
321
404
  variant: Some(callback::Variant::Nexus(callback::Nexus {
322
405
  url: start_req.callback,
323
406
  header: start_req.callback_header,
324
407
  })),
325
408
  links: links.clone(),
326
- }],
327
- // Also send links in the root of the workflow options for older servers.
328
- links,
329
- ..Default::default()
330
- },
409
+ }])
410
+ .links(links)
411
+ .build(),
331
412
  )
332
413
  .await
333
414
  .unwrap();
@@ -364,8 +445,13 @@ async fn nexus_async(
364
445
  nt.request.unwrap().variant.unwrap(),
365
446
  request::Variant::CancelOperation(_)
366
447
  );
367
- client
368
- .cancel_workflow_execution(completer_id, None, "nexus cancel".to_string(), None)
448
+ let handle = client.get_workflow_handle::<UntypedWorkflow>(completer_id);
449
+ handle
450
+ .cancel(
451
+ WorkflowCancelOptions::builder()
452
+ .reason("nexus cancel")
453
+ .build(),
454
+ )
369
455
  .await
370
456
  .unwrap();
371
457
  core_worker
@@ -393,11 +479,11 @@ async fn nexus_async(
393
479
  });
394
480
 
395
481
  let res = client
396
- .get_untyped_workflow_handle(starter.get_task_queue().to_owned(), "")
397
- .get_workflow_result(Default::default())
482
+ .get_workflow_handle::<UntypedWorkflow>(starter.get_task_queue().to_owned())
483
+ .get_result(Default::default())
398
484
  .await
399
485
  .unwrap();
400
- let res = NexusOperationResult::from_json_payload(&res.unwrap_success()[0]).unwrap();
486
+ let res = NexusOperationResult::from_json_payload(res.payloads.first().unwrap()).unwrap();
401
487
  match outcome {
402
488
  Outcome::Succeed => {
403
489
  let p = assert_matches!(
@@ -412,7 +498,7 @@ async fn nexus_async(
412
498
  Some(nexus_operation_result::Status::Failed(f)) => f
413
499
  );
414
500
  assert_eq!(f.message, "nexus operation completed unsuccessfully");
415
- assert_eq!(f.cause.unwrap().message, "broken");
501
+ assert_eq!(f.cause.unwrap().message, "Workflow execution error: broken");
416
502
  }
417
503
  Outcome::Cancel | Outcome::CancelAfterRecordedBeforeStarted => {
418
504
  let f = assert_matches!(
@@ -436,43 +522,64 @@ async fn nexus_async(
436
522
  .await
437
523
  .unwrap();
438
524
  }
525
+ #[workflow]
526
+ #[derive(Default)]
527
+ struct NexusCancelBeforeStartWf {
528
+ endpoint: String,
529
+ }
530
+
531
+ #[workflow_methods]
532
+ impl NexusCancelBeforeStartWf {
533
+ #[init]
534
+ fn new(_ctx: &WorkflowContextView, endpoint: String) -> Self {
535
+ Self { endpoint }
536
+ }
537
+
538
+ #[run]
539
+ pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
540
+ let started = ctx.start_nexus_operation(NexusOperationOptions {
541
+ endpoint: ctx.state(|wf| wf.endpoint.clone()),
542
+ service: "svc".to_string(),
543
+ operation: "op".to_string(),
544
+ ..Default::default()
545
+ });
546
+ started.cancel();
547
+ let res = started.await.unwrap_err();
548
+ assert_eq!(res.message, "Nexus Operation cancelled before scheduled");
549
+ if let FailureInfo::NexusOperationExecutionFailureInfo(fi) = res.failure_info.unwrap() {
550
+ assert_eq!(fi.endpoint, ctx.state(|wf| wf.endpoint.clone()));
551
+ assert_eq!(fi.service, "svc");
552
+ assert_eq!(fi.operation, "op");
553
+ } else {
554
+ panic!("unexpected failure info");
555
+ }
556
+ Ok(())
557
+ }
558
+ }
559
+
439
560
  #[tokio::test]
440
561
  async fn nexus_cancel_before_start() {
441
562
  let wf_name = "nexus_cancel_before_start";
442
563
  let mut starter = CoreWfStarter::new(wf_name);
443
- starter.worker_config.task_types(WorkerTaskTypes {
564
+ starter.sdk_config.task_types = WorkerTaskTypes {
444
565
  enable_workflows: true,
445
566
  enable_local_activities: false,
446
567
  enable_remote_activities: false,
447
568
  enable_nexus: true,
448
- });
569
+ };
449
570
  let mut worker = starter.worker().await;
450
571
 
451
572
  let endpoint = mk_nexus_endpoint(&mut starter).await;
452
573
 
453
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| {
454
- let endpoint = endpoint.clone();
455
- async move {
456
- let started = ctx.start_nexus_operation(NexusOperationOptions {
457
- endpoint: endpoint.clone(),
458
- service: "svc".to_string(),
459
- operation: "op".to_string(),
460
- ..Default::default()
461
- });
462
- started.cancel(&ctx);
463
- let res = started.await.unwrap_err();
464
- assert_eq!(res.message, "Nexus Operation cancelled before scheduled");
465
- if let FailureInfo::NexusOperationExecutionFailureInfo(fi) = res.failure_info.unwrap() {
466
- assert_eq!(fi.endpoint, endpoint);
467
- assert_eq!(fi.service, "svc");
468
- assert_eq!(fi.operation, "op");
469
- } else {
470
- panic!("unexpected failure info");
471
- }
472
- Ok(().into())
473
- }
474
- });
475
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
574
+ worker.register_workflow::<NexusCancelBeforeStartWf>();
575
+ let handle = worker
576
+ .submit_workflow(
577
+ NexusCancelBeforeStartWf::run,
578
+ endpoint,
579
+ starter.workflow_options.clone(),
580
+ )
581
+ .await
582
+ .unwrap();
476
583
 
477
584
  worker.run_until_done().await.unwrap();
478
585
 
@@ -482,55 +589,71 @@ async fn nexus_cancel_before_start() {
482
589
  .unwrap();
483
590
  }
484
591
 
592
+ #[workflow]
593
+ #[derive(Default)]
594
+ struct NexusMustCompleteTaskWf {
595
+ endpoint: String,
596
+ }
597
+
598
+ #[workflow_methods]
599
+ impl NexusMustCompleteTaskWf {
600
+ #[init]
601
+ fn new(_ctx: &WorkflowContextView, endpoint: String) -> Self {
602
+ Self { endpoint }
603
+ }
604
+
605
+ #[run]
606
+ pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
607
+ // We just need to create the command, not await it.
608
+ drop(ctx.start_nexus_operation(NexusOperationOptions {
609
+ endpoint: ctx.state(|wf| wf.endpoint.clone()),
610
+ service: "svc".to_string(),
611
+ operation: "op".to_string(),
612
+ ..Default::default()
613
+ }));
614
+ // Workflow completes right away, only having scheduled the operation. We need a timer
615
+ // to make sure the nexus task actually gets scheduled.
616
+ ctx.timer(Duration::from_millis(1)).await;
617
+ // started.await.unwrap();
618
+ Ok(())
619
+ }
620
+ }
621
+
485
622
  #[rstest::rstest]
486
623
  #[tokio::test]
487
624
  async fn nexus_must_complete_task_to_shutdown(#[values(true, false)] use_grace_period: bool) {
488
625
  let wf_name = "nexus_must_complete_task_to_shutdown";
489
626
  let mut starter = CoreWfStarter::new(wf_name);
490
- starter.worker_config.task_types(WorkerTaskTypes {
627
+ starter.sdk_config.task_types = WorkerTaskTypes {
491
628
  enable_workflows: true,
492
629
  enable_local_activities: false,
493
630
  enable_remote_activities: false,
494
631
  enable_nexus: true,
495
- });
632
+ };
496
633
  if use_grace_period {
497
- starter
498
- .worker_config
499
- .graceful_shutdown_period(Duration::from_millis(500));
634
+ starter.sdk_config.graceful_shutdown_period = Some(Duration::from_millis(500));
500
635
  }
501
636
  let mut worker = starter.worker().await;
502
637
  let core_worker = starter.get_worker().await;
503
638
 
504
639
  let endpoint = mk_nexus_endpoint(&mut starter).await;
505
640
 
506
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| {
507
- let endpoint = endpoint.clone();
508
- async move {
509
- // We just need to create the command, not await it.
510
- drop(ctx.start_nexus_operation(NexusOperationOptions {
511
- endpoint: endpoint.clone(),
512
- service: "svc".to_string(),
513
- operation: "op".to_string(),
514
- ..Default::default()
515
- }));
516
- // Workflow completes right away, only having scheduled the operation. We need a timer
517
- // to make sure the nexus task actually gets scheduled.
518
- ctx.timer(Duration::from_millis(1)).await;
519
- // started.await.unwrap();
520
- Ok(().into())
521
- }
522
- });
523
- let handle = starter.start_with_worker(wf_name, &mut worker).await;
641
+ worker.register_workflow::<NexusMustCompleteTaskWf>();
642
+ let handle = worker
643
+ .submit_workflow(
644
+ NexusMustCompleteTaskWf::run,
645
+ endpoint,
646
+ starter.workflow_options.clone(),
647
+ )
648
+ .await
649
+ .unwrap();
524
650
  let (complete_order_tx, mut complete_order_rx) = mpsc::unbounded_channel();
525
651
 
526
652
  let task_handle = async {
527
653
  // Should get the nexus task first
528
654
  let nt = core_worker.poll_nexus_task().await.unwrap().unwrap_task();
529
655
  // The workflow will complete
530
- handle
531
- .get_workflow_result(Default::default())
532
- .await
533
- .unwrap();
656
+ handle.get_result(Default::default()).await.unwrap();
534
657
  if use_grace_period {
535
658
  // Wait for cancel to be sent
536
659
  let nt = core_worker.poll_nexus_task().await.unwrap();
@@ -546,6 +669,7 @@ async fn nexus_must_complete_task_to_shutdown(#[values(true, false)] use_grace_p
546
669
  core_worker
547
670
  .complete_nexus_task(NexusTaskCompletion {
548
671
  task_token: nt.task_token,
672
+ #[allow(deprecated)]
549
673
  status: Some(nexus_task_completion::Status::Error(HandlerError {
550
674
  error_type: "BAD_REQUEST".to_string(), // bad req is non-retryable
551
675
  failure: Some(nexus::v1::Failure {
@@ -579,6 +703,89 @@ async fn nexus_must_complete_task_to_shutdown(#[values(true, false)] use_grace_p
579
703
  .unwrap();
580
704
  }
581
705
 
706
+ #[workflow]
707
+ struct NexusCancellationCallerWf {
708
+ endpoint: String,
709
+ schedule_to_close_timeout: Option<Duration>,
710
+ cancellation_type: NexusOperationCancellationType,
711
+ caller_op_future_tx: watch::Sender<bool>,
712
+ }
713
+
714
+ #[workflow_methods(factory_only)]
715
+ impl NexusCancellationCallerWf {
716
+ #[run(name = "nexus_cancellation_types")]
717
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<NexusOperationResult> {
718
+ let options = NexusOperationOptions {
719
+ endpoint: ctx.state(|wf| wf.endpoint.clone()),
720
+ service: "svc".to_string(),
721
+ operation: "op".to_string(),
722
+ schedule_to_close_timeout: ctx.state(|wf| wf.schedule_to_close_timeout),
723
+ cancellation_type: Some(ctx.state(|wf| wf.cancellation_type)),
724
+ ..Default::default()
725
+ };
726
+ let started = ctx.start_nexus_operation(options);
727
+ let started = started.await.unwrap();
728
+ let result = started.result();
729
+ started.cancel();
730
+ started.cancel();
731
+
732
+ let res = result.await;
733
+ ctx.state(|wf| wf.caller_op_future_tx.send(true).unwrap());
734
+
735
+ // Make sure cancel after op completion doesn't cause problems
736
+ started.cancel();
737
+
738
+ // We need to wait slightly so that the workflow is not complete at the same time
739
+ // cancellation is invoked. If it does, the caller workflow will close and the server
740
+ // won't attempt to send the cancellation to the handler
741
+ ctx.timer(Duration::from_millis(1)).await;
742
+ Ok(res)
743
+ }
744
+ }
745
+
746
+ #[workflow]
747
+ struct AsyncCompleterWf {
748
+ cancellation_type: NexusOperationCancellationType,
749
+ cancellation_wait_happened: Arc<AtomicBool>,
750
+ cancellation_tx: watch::Sender<bool>,
751
+ handler_exited_tx: watch::Sender<bool>,
752
+ proceed_signal_received: bool,
753
+ }
754
+
755
+ #[workflow_methods(factory_only)]
756
+ impl AsyncCompleterWf {
757
+ #[run(name = "async_completer")]
758
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
759
+ // Wait for cancellation
760
+ ctx.cancelled().await;
761
+ ctx.state(|wf| wf.cancellation_tx.send(true).unwrap());
762
+
763
+ if ctx.state(|wf| wf.cancellation_type)
764
+ == NexusOperationCancellationType::WaitCancellationCompleted
765
+ {
766
+ ctx.wait_condition(|wf| wf.cancellation_wait_happened.load(Ordering::Relaxed))
767
+ .await;
768
+ } else if ctx.state(|wf| wf.cancellation_type)
769
+ == NexusOperationCancellationType::WaitCancellationRequested
770
+ {
771
+ // For WAIT_REQUESTED, wait until the caller nexus op future has been resolved. This
772
+ // allows the test to verify that it resolved due to
773
+ // NexusOperationCancelRequestCompleted (written after cancel handler responds)
774
+ // rather than NexusOperationCanceled (written after handler workflow completes as
775
+ // cancelled).
776
+ ctx.wait_condition(|wf| wf.proceed_signal_received).await;
777
+ }
778
+
779
+ ctx.state(|wf| wf.handler_exited_tx.send(true).unwrap());
780
+ Err(WorkflowTermination::Cancelled)
781
+ }
782
+
783
+ #[signal(name = "proceed-to-exit")]
784
+ fn handle_proceed_signal(&mut self, _ctx: &mut SyncWorkflowContext<Self>) {
785
+ self.proceed_signal_received = true;
786
+ }
787
+ }
788
+
582
789
  #[rstest::rstest]
583
790
  #[tokio::test]
584
791
  async fn nexus_cancellation_types(
@@ -592,12 +799,12 @@ async fn nexus_cancellation_types(
592
799
  ) {
593
800
  let wf_name = "nexus_cancellation_types";
594
801
  let mut starter = CoreWfStarter::new(wf_name);
595
- starter.worker_config.task_types(WorkerTaskTypes {
802
+ starter.sdk_config.task_types = WorkerTaskTypes {
596
803
  enable_workflows: true,
597
804
  enable_local_activities: false,
598
805
  enable_remote_activities: false,
599
806
  enable_nexus: true,
600
- });
807
+ };
601
808
  let mut worker = starter.worker().await;
602
809
  let core_worker = starter.get_worker().await;
603
810
 
@@ -605,72 +812,35 @@ async fn nexus_cancellation_types(
605
812
  let schedule_to_close_timeout = Some(Duration::from_secs(5));
606
813
 
607
814
  let (caller_op_future_tx, caller_op_future_rx) = watch::channel(false);
608
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| {
815
+ worker.register_workflow_with_factory({
609
816
  let endpoint = endpoint.clone();
610
817
  let caller_op_future_tx = caller_op_future_tx.clone();
611
- async move {
612
- let options = NexusOperationOptions {
613
- endpoint,
614
- service: "svc".to_string(),
615
- operation: "op".to_string(),
616
- schedule_to_close_timeout,
617
- cancellation_type: Some(cancellation_type),
618
- ..Default::default()
619
- };
620
- let started = ctx.start_nexus_operation(options);
621
- let started = started.await.unwrap();
622
- let result = started.result();
623
- started.cancel(&ctx);
624
- started.cancel(&ctx);
625
-
626
- let res = result.await;
627
- caller_op_future_tx.send(true).unwrap();
628
-
629
- // Make sure cancel after op completion doesn't cause problems
630
- started.cancel(&ctx);
631
-
632
- // We need to wait slightly so that the workflow is not complete at the same time
633
- // cancellation is invoked. If it does, the caller workflow will close and the server
634
- // won't attempt to send the cancellation to the handler
635
- ctx.timer(Duration::from_millis(1)).await;
636
- Ok(res.into())
818
+ move || NexusCancellationCallerWf {
819
+ endpoint: endpoint.clone(),
820
+ schedule_to_close_timeout,
821
+ cancellation_type,
822
+ caller_op_future_tx: caller_op_future_tx.clone(),
637
823
  }
638
824
  });
639
825
 
640
826
  let cancellation_wait_happened = Arc::new(AtomicBool::new(false));
641
- let cancellation_wait_happened_clone = cancellation_wait_happened.clone();
642
827
  let (cancellation_tx, mut cancellation_rx) = watch::channel(false);
643
828
  let (handler_exited_tx, mut handler_exited_rx) = watch::channel(false);
644
- worker.register_wf("async_completer".to_owned(), move |ctx: WfContext| {
829
+ worker.register_workflow_with_factory({
830
+ let cancellation_wait_happened = cancellation_wait_happened.clone();
645
831
  let cancellation_tx = cancellation_tx.clone();
646
- let cancellation_wait_happened = cancellation_wait_happened_clone.clone();
647
832
  let handler_exited_tx = handler_exited_tx.clone();
648
- async move {
649
- // Wait for cancellation
650
- ctx.cancelled().await;
651
- cancellation_tx.send(true).unwrap();
652
-
653
- if cancellation_type == NexusOperationCancellationType::WaitCancellationCompleted {
654
- ctx.wait_condition(|| cancellation_wait_happened.load(Ordering::Relaxed))
655
- .await;
656
- } else if cancellation_type == NexusOperationCancellationType::WaitCancellationRequested
657
- {
658
- // For WAIT_REQUESTED, wait until the caller nexus op future has been resolved. This
659
- // allows the test to verify that it resolved due to
660
- // NexusOperationCancelRequestCompleted (written after cancel handler responds)
661
- // rather than NexusOperationCanceled (written after handler workflow completes as
662
- // cancelled).
663
- let mut signal_chan = ctx.make_signal_channel("proceed-to-exit");
664
- signal_chan.next().await;
665
- }
666
-
667
- handler_exited_tx.send(true).unwrap();
668
- Ok(WfExitValue::<()>::Cancelled)
833
+ move || AsyncCompleterWf {
834
+ cancellation_type,
835
+ cancellation_wait_happened: cancellation_wait_happened.clone(),
836
+ cancellation_tx: cancellation_tx.clone(),
837
+ handler_exited_tx: handler_exited_tx.clone(),
838
+ proceed_signal_received: false,
669
839
  }
670
840
  });
671
841
  let submitter = worker.get_submitter_handle();
672
842
  let wf_handle = starter.start_with_worker(wf_name, &mut worker).await;
673
- let client = starter.get_client().await.get_client().clone();
843
+ let client = starter.get_client().await;
674
844
  let (handler_wf_id_tx, mut handler_wf_id_rx) = tokio::sync::oneshot::channel();
675
845
  let completer_id = &format!("completer-{}", rand_6_chars());
676
846
  let nexus_task_handle = async {
@@ -689,23 +859,21 @@ async fn nexus_cancellation_types(
689
859
 
690
860
  // Start the workflow which will act like the nexus handler and complete the async
691
861
  // operation
862
+ let task_queue = starter.get_task_queue().to_owned();
692
863
  submitter
693
864
  .submit_wf(
694
- completer_id.clone(),
695
865
  "async_completer",
696
866
  vec![],
697
- WorkflowOptions {
698
- completion_callbacks: vec![Callback {
867
+ WorkflowStartOptions::new(task_queue, completer_id.clone())
868
+ .completion_callbacks(vec![Callback {
699
869
  variant: Some(callback::Variant::Nexus(callback::Nexus {
700
870
  url: start_req.callback,
701
871
  header: start_req.callback_header,
702
872
  })),
703
873
  links: links.clone(),
704
- }],
705
- // Also send links in the root of the workflow options for older servers.
706
- links,
707
- ..Default::default()
708
- },
874
+ }])
875
+ .links(links)
876
+ .build(),
709
877
  )
710
878
  .await
711
879
  .unwrap();
@@ -739,10 +907,7 @@ async fn nexus_cancellation_types(
739
907
  assert!(!*caller_op_future_rx.borrow());
740
908
  }
741
909
  NexusOperationCancellationType::Abandon | NexusOperationCancellationType::TryCancel => {
742
- wf_handle
743
- .get_workflow_result(Default::default())
744
- .await
745
- .unwrap();
910
+ wf_handle.get_result(Default::default()).await.unwrap();
746
911
  // The nexus op future should have been resolved
747
912
  assert!(*caller_op_future_rx.borrow())
748
913
  }
@@ -755,12 +920,12 @@ async fn nexus_cancellation_types(
755
920
  nt.request.unwrap().variant.unwrap(),
756
921
  request::Variant::CancelOperation(_)
757
922
  );
758
- client
759
- .cancel_workflow_execution(
760
- completer_id.to_string(),
761
- None,
762
- "nexus cancel".to_string(),
763
- None,
923
+ let handle = client.get_workflow_handle::<UntypedWorkflow>(completer_id.to_string());
924
+ handle
925
+ .cancel(
926
+ WorkflowCancelOptions::builder()
927
+ .reason("nexus cancel")
928
+ .build(),
764
929
  )
765
930
  .await
766
931
  .unwrap();
@@ -789,18 +954,14 @@ async fn nexus_cancellation_types(
789
954
  // Send a signal just to wake up the workflow so it'll check the condition
790
955
  // (it may already have completed, so ignore the result)
791
956
  let _ = client
792
- .signal_workflow_execution(
793
- completer_id.to_string(),
794
- "".to_string(),
795
- "wakeupdude".to_string(),
796
- None,
797
- None,
957
+ .get_workflow_handle::<UntypedWorkflow>(completer_id.to_string())
958
+ .signal(
959
+ UntypedSignal::new("wakeupdude"),
960
+ RawValue::empty(),
961
+ WorkflowSignalOptions::default(),
798
962
  )
799
963
  .await;
800
- wf_handle
801
- .get_workflow_result(Default::default())
802
- .await
803
- .unwrap();
964
+ wf_handle.get_result(Default::default()).await.unwrap();
804
965
  assert!(*caller_op_future_rx.borrow());
805
966
  }
806
967
 
@@ -829,12 +990,11 @@ async fn nexus_cancellation_types(
829
990
  .try_recv()
830
991
  .expect("Should have received handler workflow ID");
831
992
  client
832
- .signal_workflow_execution(
833
- handler_wf_id,
834
- "".to_string(),
835
- "proceed-to-exit".to_string(),
836
- None,
837
- None,
993
+ .get_workflow_handle::<async_completer_wf::Run>(handler_wf_id)
994
+ .signal(
995
+ AsyncCompleterWf::handle_proceed_signal,
996
+ (),
997
+ WorkflowSignalOptions::default(),
838
998
  )
839
999
  .await
840
1000
  .unwrap();
@@ -847,10 +1007,7 @@ async fn nexus_cancellation_types(
847
1007
  nexus_task_handle,
848
1008
  async { worker.inner_mut().run().await.unwrap() },
849
1009
  async {
850
- wf_handle
851
- .get_workflow_result(Default::default())
852
- .await
853
- .unwrap();
1010
+ wf_handle.get_result(Default::default()).await.unwrap();
854
1011
  if cancellation_type == NexusOperationCancellationType::TryCancel {
855
1012
  cancellation_rx.changed().await.unwrap();
856
1013
  }
@@ -873,11 +1030,11 @@ async fn nexus_cancellation_types(
873
1030
  }
874
1031
 
875
1032
  let res = client
876
- .get_untyped_workflow_handle(starter.get_task_queue().to_owned(), "")
877
- .get_workflow_result(Default::default())
1033
+ .get_workflow_handle::<UntypedWorkflow>(starter.get_task_queue().to_owned())
1034
+ .get_result(Default::default())
878
1035
  .await
879
1036
  .unwrap();
880
- let res = NexusOperationResult::from_json_payload(&res.unwrap_success()[0]).unwrap();
1037
+ let res = NexusOperationResult::from_json_payload(res.payloads.first().unwrap()).unwrap();
881
1038
 
882
1039
  match cancellation_type {
883
1040
  NexusOperationCancellationType::Abandon | NexusOperationCancellationType::TryCancel => {