@temporalio/core-bridge 1.15.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 (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 +16 -3
  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 +340 -188
  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 +15 -18
  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
@@ -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,7 +105,7 @@ 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,
@@ -69,31 +116,17 @@ async fn nexus_basic(
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,7 +317,7 @@ 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,
@@ -219,56 +328,29 @@ async fn nexus_async(
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,11 +522,46 @@ 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,
@@ -450,29 +571,15 @@ async fn nexus_cancel_before_start() {
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,53 +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.worker_config.graceful_shutdown_period = Some(Duration::from_millis(500));
634
+ starter.sdk_config.graceful_shutdown_period = Some(Duration::from_millis(500));
498
635
  }
499
636
  let mut worker = starter.worker().await;
500
637
  let core_worker = starter.get_worker().await;
501
638
 
502
639
  let endpoint = mk_nexus_endpoint(&mut starter).await;
503
640
 
504
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| {
505
- let endpoint = endpoint.clone();
506
- async move {
507
- // We just need to create the command, not await it.
508
- drop(ctx.start_nexus_operation(NexusOperationOptions {
509
- endpoint: endpoint.clone(),
510
- service: "svc".to_string(),
511
- operation: "op".to_string(),
512
- ..Default::default()
513
- }));
514
- // Workflow completes right away, only having scheduled the operation. We need a timer
515
- // to make sure the nexus task actually gets scheduled.
516
- ctx.timer(Duration::from_millis(1)).await;
517
- // started.await.unwrap();
518
- Ok(().into())
519
- }
520
- });
521
- 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();
522
650
  let (complete_order_tx, mut complete_order_rx) = mpsc::unbounded_channel();
523
651
 
524
652
  let task_handle = async {
525
653
  // Should get the nexus task first
526
654
  let nt = core_worker.poll_nexus_task().await.unwrap().unwrap_task();
527
655
  // The workflow will complete
528
- handle
529
- .get_workflow_result(Default::default())
530
- .await
531
- .unwrap();
656
+ handle.get_result(Default::default()).await.unwrap();
532
657
  if use_grace_period {
533
658
  // Wait for cancel to be sent
534
659
  let nt = core_worker.poll_nexus_task().await.unwrap();
@@ -544,6 +669,7 @@ async fn nexus_must_complete_task_to_shutdown(#[values(true, false)] use_grace_p
544
669
  core_worker
545
670
  .complete_nexus_task(NexusTaskCompletion {
546
671
  task_token: nt.task_token,
672
+ #[allow(deprecated)]
547
673
  status: Some(nexus_task_completion::Status::Error(HandlerError {
548
674
  error_type: "BAD_REQUEST".to_string(), // bad req is non-retryable
549
675
  failure: Some(nexus::v1::Failure {
@@ -577,6 +703,89 @@ async fn nexus_must_complete_task_to_shutdown(#[values(true, false)] use_grace_p
577
703
  .unwrap();
578
704
  }
579
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
+
580
789
  #[rstest::rstest]
581
790
  #[tokio::test]
582
791
  async fn nexus_cancellation_types(
@@ -590,7 +799,7 @@ async fn nexus_cancellation_types(
590
799
  ) {
591
800
  let wf_name = "nexus_cancellation_types";
592
801
  let mut starter = CoreWfStarter::new(wf_name);
593
- starter.worker_config.task_types = WorkerTaskTypes {
802
+ starter.sdk_config.task_types = WorkerTaskTypes {
594
803
  enable_workflows: true,
595
804
  enable_local_activities: false,
596
805
  enable_remote_activities: false,
@@ -603,72 +812,35 @@ async fn nexus_cancellation_types(
603
812
  let schedule_to_close_timeout = Some(Duration::from_secs(5));
604
813
 
605
814
  let (caller_op_future_tx, caller_op_future_rx) = watch::channel(false);
606
- worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| {
815
+ worker.register_workflow_with_factory({
607
816
  let endpoint = endpoint.clone();
608
817
  let caller_op_future_tx = caller_op_future_tx.clone();
609
- async move {
610
- let options = NexusOperationOptions {
611
- endpoint,
612
- service: "svc".to_string(),
613
- operation: "op".to_string(),
614
- schedule_to_close_timeout,
615
- cancellation_type: Some(cancellation_type),
616
- ..Default::default()
617
- };
618
- let started = ctx.start_nexus_operation(options);
619
- let started = started.await.unwrap();
620
- let result = started.result();
621
- started.cancel(&ctx);
622
- started.cancel(&ctx);
623
-
624
- let res = result.await;
625
- caller_op_future_tx.send(true).unwrap();
626
-
627
- // Make sure cancel after op completion doesn't cause problems
628
- started.cancel(&ctx);
629
-
630
- // We need to wait slightly so that the workflow is not complete at the same time
631
- // cancellation is invoked. If it does, the caller workflow will close and the server
632
- // won't attempt to send the cancellation to the handler
633
- ctx.timer(Duration::from_millis(1)).await;
634
- 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(),
635
823
  }
636
824
  });
637
825
 
638
826
  let cancellation_wait_happened = Arc::new(AtomicBool::new(false));
639
- let cancellation_wait_happened_clone = cancellation_wait_happened.clone();
640
827
  let (cancellation_tx, mut cancellation_rx) = watch::channel(false);
641
828
  let (handler_exited_tx, mut handler_exited_rx) = watch::channel(false);
642
- 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();
643
831
  let cancellation_tx = cancellation_tx.clone();
644
- let cancellation_wait_happened = cancellation_wait_happened_clone.clone();
645
832
  let handler_exited_tx = handler_exited_tx.clone();
646
- async move {
647
- // Wait for cancellation
648
- ctx.cancelled().await;
649
- cancellation_tx.send(true).unwrap();
650
-
651
- if cancellation_type == NexusOperationCancellationType::WaitCancellationCompleted {
652
- ctx.wait_condition(|| cancellation_wait_happened.load(Ordering::Relaxed))
653
- .await;
654
- } else if cancellation_type == NexusOperationCancellationType::WaitCancellationRequested
655
- {
656
- // For WAIT_REQUESTED, wait until the caller nexus op future has been resolved. This
657
- // allows the test to verify that it resolved due to
658
- // NexusOperationCancelRequestCompleted (written after cancel handler responds)
659
- // rather than NexusOperationCanceled (written after handler workflow completes as
660
- // cancelled).
661
- let mut signal_chan = ctx.make_signal_channel("proceed-to-exit");
662
- signal_chan.next().await;
663
- }
664
-
665
- handler_exited_tx.send(true).unwrap();
666
- 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,
667
839
  }
668
840
  });
669
841
  let submitter = worker.get_submitter_handle();
670
842
  let wf_handle = starter.start_with_worker(wf_name, &mut worker).await;
671
- let client = starter.get_client().await.get_client().clone();
843
+ let client = starter.get_client().await;
672
844
  let (handler_wf_id_tx, mut handler_wf_id_rx) = tokio::sync::oneshot::channel();
673
845
  let completer_id = &format!("completer-{}", rand_6_chars());
674
846
  let nexus_task_handle = async {
@@ -687,23 +859,21 @@ async fn nexus_cancellation_types(
687
859
 
688
860
  // Start the workflow which will act like the nexus handler and complete the async
689
861
  // operation
862
+ let task_queue = starter.get_task_queue().to_owned();
690
863
  submitter
691
864
  .submit_wf(
692
- completer_id.clone(),
693
865
  "async_completer",
694
866
  vec![],
695
- WorkflowOptions {
696
- completion_callbacks: vec![Callback {
867
+ WorkflowStartOptions::new(task_queue, completer_id.clone())
868
+ .completion_callbacks(vec![Callback {
697
869
  variant: Some(callback::Variant::Nexus(callback::Nexus {
698
870
  url: start_req.callback,
699
871
  header: start_req.callback_header,
700
872
  })),
701
873
  links: links.clone(),
702
- }],
703
- // Also send links in the root of the workflow options for older servers.
704
- links,
705
- ..Default::default()
706
- },
874
+ }])
875
+ .links(links)
876
+ .build(),
707
877
  )
708
878
  .await
709
879
  .unwrap();
@@ -737,10 +907,7 @@ async fn nexus_cancellation_types(
737
907
  assert!(!*caller_op_future_rx.borrow());
738
908
  }
739
909
  NexusOperationCancellationType::Abandon | NexusOperationCancellationType::TryCancel => {
740
- wf_handle
741
- .get_workflow_result(Default::default())
742
- .await
743
- .unwrap();
910
+ wf_handle.get_result(Default::default()).await.unwrap();
744
911
  // The nexus op future should have been resolved
745
912
  assert!(*caller_op_future_rx.borrow())
746
913
  }
@@ -753,12 +920,12 @@ async fn nexus_cancellation_types(
753
920
  nt.request.unwrap().variant.unwrap(),
754
921
  request::Variant::CancelOperation(_)
755
922
  );
756
- client
757
- .cancel_workflow_execution(
758
- completer_id.to_string(),
759
- None,
760
- "nexus cancel".to_string(),
761
- 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(),
762
929
  )
763
930
  .await
764
931
  .unwrap();
@@ -787,18 +954,14 @@ async fn nexus_cancellation_types(
787
954
  // Send a signal just to wake up the workflow so it'll check the condition
788
955
  // (it may already have completed, so ignore the result)
789
956
  let _ = client
790
- .signal_workflow_execution(
791
- completer_id.to_string(),
792
- "".to_string(),
793
- "wakeupdude".to_string(),
794
- None,
795
- None,
957
+ .get_workflow_handle::<UntypedWorkflow>(completer_id.to_string())
958
+ .signal(
959
+ UntypedSignal::new("wakeupdude"),
960
+ RawValue::empty(),
961
+ WorkflowSignalOptions::default(),
796
962
  )
797
963
  .await;
798
- wf_handle
799
- .get_workflow_result(Default::default())
800
- .await
801
- .unwrap();
964
+ wf_handle.get_result(Default::default()).await.unwrap();
802
965
  assert!(*caller_op_future_rx.borrow());
803
966
  }
804
967
 
@@ -827,12 +990,11 @@ async fn nexus_cancellation_types(
827
990
  .try_recv()
828
991
  .expect("Should have received handler workflow ID");
829
992
  client
830
- .signal_workflow_execution(
831
- handler_wf_id,
832
- "".to_string(),
833
- "proceed-to-exit".to_string(),
834
- None,
835
- None,
993
+ .get_workflow_handle::<async_completer_wf::Run>(handler_wf_id)
994
+ .signal(
995
+ AsyncCompleterWf::handle_proceed_signal,
996
+ (),
997
+ WorkflowSignalOptions::default(),
836
998
  )
837
999
  .await
838
1000
  .unwrap();
@@ -845,10 +1007,7 @@ async fn nexus_cancellation_types(
845
1007
  nexus_task_handle,
846
1008
  async { worker.inner_mut().run().await.unwrap() },
847
1009
  async {
848
- wf_handle
849
- .get_workflow_result(Default::default())
850
- .await
851
- .unwrap();
1010
+ wf_handle.get_result(Default::default()).await.unwrap();
852
1011
  if cancellation_type == NexusOperationCancellationType::TryCancel {
853
1012
  cancellation_rx.changed().await.unwrap();
854
1013
  }
@@ -871,11 +1030,11 @@ async fn nexus_cancellation_types(
871
1030
  }
872
1031
 
873
1032
  let res = client
874
- .get_untyped_workflow_handle(starter.get_task_queue().to_owned(), "")
875
- .get_workflow_result(Default::default())
1033
+ .get_workflow_handle::<UntypedWorkflow>(starter.get_task_queue().to_owned())
1034
+ .get_result(Default::default())
876
1035
  .await
877
1036
  .unwrap();
878
- let res = NexusOperationResult::from_json_payload(&res.unwrap_success()[0]).unwrap();
1037
+ let res = NexusOperationResult::from_json_payload(res.payloads.first().unwrap()).unwrap();
879
1038
 
880
1039
  match cancellation_type {
881
1040
  NexusOperationCancellationType::Abandon | NexusOperationCancellationType::TryCancel => {