@temporalio/core-bridge 1.14.2-canary-release-testing.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/Cargo.lock +794 -650
  2. package/bridge-macros/src/derive_tryintojs.rs +40 -0
  3. package/lib/native.d.ts +24 -3
  4. package/package.json +4 -4
  5. package/releases/aarch64-apple-darwin/index.node +0 -0
  6. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  7. package/releases/x86_64-apple-darwin/index.node +0 -0
  8. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  9. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  10. package/sdk-core/.github/workflows/per-pr.yml +6 -6
  11. package/sdk-core/AGENTS.md +42 -31
  12. package/sdk-core/Cargo.toml +4 -1
  13. package/sdk-core/README.md +19 -13
  14. package/sdk-core/crates/client/Cargo.toml +4 -0
  15. package/sdk-core/crates/client/README.md +139 -0
  16. package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
  17. package/sdk-core/crates/client/src/callback_based.rs +7 -0
  18. package/sdk-core/crates/client/src/errors.rs +294 -0
  19. package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +370 -159
  20. package/sdk-core/crates/client/src/lib.rs +920 -1326
  21. package/sdk-core/crates/client/src/metrics.rs +24 -33
  22. package/sdk-core/crates/client/src/options_structs.rs +457 -0
  23. package/sdk-core/crates/client/src/replaceable.rs +5 -4
  24. package/sdk-core/crates/client/src/request_extensions.rs +8 -9
  25. package/sdk-core/crates/client/src/retry.rs +99 -54
  26. package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +104 -29
  27. package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
  28. package/sdk-core/crates/common/Cargo.toml +62 -3
  29. package/sdk-core/crates/common/build.rs +742 -12
  30. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
  31. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/create-release.yml +0 -5
  32. package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
  33. package/sdk-core/crates/common/protos/api_upstream/README.md +8 -0
  34. package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
  35. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +3329 -2647
  36. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +2734 -708
  37. package/sdk-core/crates/common/protos/api_upstream/temporal/api/activity/v1/message.proto +155 -3
  38. package/sdk-core/crates/common/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
  39. package/sdk-core/crates/common/protos/api_upstream/temporal/api/common/v1/message.proto +8 -1
  40. package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +27 -1
  41. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/activity.proto +81 -0
  42. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/event_type.proto +4 -0
  43. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +4 -0
  44. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +15 -0
  45. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +63 -15
  46. package/sdk-core/crates/common/protos/api_upstream/temporal/api/errordetails/v1/message.proto +8 -0
  47. package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
  48. package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +111 -17
  49. package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +21 -0
  50. package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +20 -1
  51. package/sdk-core/crates/common/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +4 -0
  52. package/sdk-core/crates/common/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
  53. package/sdk-core/crates/common/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -0
  54. package/sdk-core/crates/common/protos/api_upstream/temporal/api/worker/v1/message.proto +4 -7
  55. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflow/v1/message.proto +80 -22
  56. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +347 -23
  57. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +242 -43
  58. package/sdk-core/crates/common/protos/local/temporal/sdk/core/core_interface.proto +15 -0
  59. package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +9 -2
  60. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +8 -0
  61. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +22 -5
  62. package/sdk-core/crates/common/src/activity_definition.rs +20 -0
  63. package/sdk-core/crates/common/src/data_converters.rs +770 -0
  64. package/sdk-core/crates/common/src/envconfig.rs +5 -0
  65. package/sdk-core/crates/common/src/lib.rs +15 -211
  66. package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
  67. package/sdk-core/crates/common/src/priority.rs +110 -0
  68. package/sdk-core/crates/common/src/protos/canned_histories.rs +19 -0
  69. package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
  70. package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
  71. package/sdk-core/crates/common/src/protos/mod.rs +134 -27
  72. package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
  73. package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
  74. package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +11 -16
  75. package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
  76. package/sdk-core/crates/common/src/telemetry/metrics.rs +272 -225
  77. package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
  78. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
  79. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
  80. package/sdk-core/crates/common/src/telemetry.rs +278 -19
  81. package/sdk-core/crates/common/src/worker.rs +68 -636
  82. package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
  83. package/sdk-core/crates/macros/Cargo.toml +5 -1
  84. package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
  85. package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
  86. package/sdk-core/crates/macros/src/lib.rs +138 -512
  87. package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
  88. package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
  89. package/sdk-core/crates/sdk/Cargo.toml +19 -6
  90. package/sdk-core/crates/sdk/README.md +415 -0
  91. package/sdk-core/crates/sdk/src/activities.rs +417 -0
  92. package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
  93. package/sdk-core/crates/sdk/src/lib.rs +759 -442
  94. package/sdk-core/crates/sdk/src/workflow_context/options.rs +64 -35
  95. package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
  96. package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
  97. package/sdk-core/crates/sdk/src/workflows.rs +711 -0
  98. package/sdk-core/crates/sdk-core/Cargo.toml +59 -65
  99. package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +45 -54
  100. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
  101. package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
  102. package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
  103. package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +22 -21
  104. package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
  105. package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
  106. package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
  107. package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +647 -27
  108. package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +46 -41
  109. package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +13 -16
  110. package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
  111. package/sdk-core/crates/sdk-core/src/lib.rs +60 -123
  112. package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
  113. package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +411 -32
  114. package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
  115. package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
  116. package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +183 -198
  117. package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -281
  118. package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +35 -16
  119. package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
  120. package/sdk-core/crates/sdk-core/src/worker/activities/activity_heartbeat_manager.rs +1 -0
  121. package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
  122. package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
  123. package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +11 -5
  124. package/sdk-core/crates/sdk-core/src/worker/client.rs +104 -86
  125. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +10 -14
  126. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1175 -241
  127. package/sdk-core/crates/sdk-core/src/worker/nexus.rs +150 -23
  128. package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
  129. package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
  130. package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +25 -27
  131. package/sdk-core/crates/sdk-core/src/worker/tuner.rs +64 -44
  132. package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
  133. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/patch_state_machine.rs +5 -8
  134. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
  135. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +28 -4
  136. package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +20 -41
  137. package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +50 -9
  138. package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
  139. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
  140. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
  141. package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
  142. package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
  143. package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
  144. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
  145. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
  146. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
  147. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
  148. package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
  149. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
  150. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
  151. package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
  152. package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
  153. package/sdk-core/crates/sdk-core/tests/common/mod.rs +281 -236
  154. package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
  155. package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +9 -14
  156. package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -66
  157. package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +306 -268
  158. package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
  159. package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
  160. package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
  161. package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +37 -38
  162. package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +49 -40
  163. package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +447 -300
  164. package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
  165. package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +157 -157
  166. package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
  167. package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -463
  168. package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
  169. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +389 -265
  170. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +250 -185
  171. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -49
  172. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
  173. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +437 -327
  174. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -58
  175. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -30
  176. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -251
  177. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
  178. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +110 -46
  179. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -149
  180. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -32
  181. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1040
  182. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -43
  183. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +402 -245
  184. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +343 -207
  185. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
  186. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
  187. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +155 -140
  188. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -113
  189. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -44
  190. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -48
  191. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -56
  192. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +365 -242
  193. package/sdk-core/crates/sdk-core/tests/main.rs +22 -16
  194. package/sdk-core/crates/sdk-core/tests/manual_tests.rs +233 -187
  195. package/sdk-core/crates/sdk-core/tests/runner.rs +4 -6
  196. package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +73 -27
  197. package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
  198. package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
  199. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
  200. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
  201. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
  202. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
  203. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
  204. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
  205. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
  206. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
  207. package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +8 -1
  208. package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +37 -26
  209. package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +180 -87
  210. package/sdk-core/crates/sdk-core-c-bridge/src/lib.rs +89 -5
  211. package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +10 -16
  212. package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +59 -67
  213. package/sdk-core/crates/sdk-core-c-bridge/src/testing.rs +10 -10
  214. package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +57 -22
  215. package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +108 -12
  216. package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +9 -52
  217. package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +74 -91
  218. package/sdk-core/rustfmt.toml +2 -1
  219. package/src/client.rs +206 -289
  220. package/src/helpers/try_into_js.rs +88 -2
  221. package/src/metrics.rs +277 -35
  222. package/src/runtime.rs +94 -45
  223. package/src/testing.rs +9 -16
  224. package/src/worker.rs +86 -68
  225. package/ts/native.ts +39 -3
  226. package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
  227. package/sdk-core/crates/common/src/errors.rs +0 -85
  228. package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
  229. package/sdk-core/crates/macros/LICENSE.txt +0 -21
  230. package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
  231. package/sdk-core/crates/sdk/src/app_data.rs +0 -37
  232. package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
  233. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
@@ -1,21 +1,142 @@
1
1
  use proc_macro::TokenStream;
2
- use quote::{quote, quote_spanned};
3
- use std::collections::{HashMap, HashSet, hash_map::Entry};
4
- use syn::{
5
- Error, Fields, Ident, Token, Type, Variant, Visibility, parenthesized,
6
- parse::{Parse, ParseStream, Result},
7
- parse_macro_input,
8
- spanned::Spanned,
9
- };
2
+ use syn::parse_macro_input;
3
+
4
+ mod activities_definitions;
5
+ mod fsm_impl;
6
+ mod macro_utils;
7
+ mod workflow_definitions;
8
+
9
+ /// Can be used to define Activities for invocation and execution. Using this macro requires that
10
+ /// you also depend on the `temporalio_sdk` crate.
11
+ ///
12
+ /// For a usage example, see that crate's documentation.
13
+ #[proc_macro_attribute]
14
+ pub fn activities(_attr: TokenStream, item: TokenStream) -> TokenStream {
15
+ let def: activities_definitions::ActivitiesDefinition =
16
+ parse_macro_input!(item as activities_definitions::ActivitiesDefinition);
17
+ def.codegen()
18
+ }
19
+
20
+ /// Marks a method within an `#[activities]` impl block as an activity.
21
+ /// This attribute is processed by the `#[activities]` macro and should not be used standalone.
22
+ #[proc_macro_attribute]
23
+ pub fn activity(_attr: TokenStream, item: TokenStream) -> TokenStream {
24
+ item
25
+ }
26
+
27
+ /// Marks a struct as a workflow definition.
28
+ ///
29
+ /// This attribute can optionally specify a custom workflow name:
30
+ /// `#[workflow(name = "my-custom-workflow")]`
31
+ ///
32
+ /// If no name is specified, the struct name is used as the workflow type name.
33
+ ///
34
+ /// This attribute must be used in conjunction with `#[workflow_methods]` on an impl block.
35
+ #[proc_macro_attribute]
36
+ pub fn workflow(_attr: TokenStream, item: TokenStream) -> TokenStream {
37
+ // Pass through - the struct is not modified, just marked for workflow_methods
38
+ item
39
+ }
40
+
41
+ /// Defines workflow methods for a workflow struct. Using this macro requires that
42
+ /// you also depend on the `temporalio_sdk` crate.
43
+ ///
44
+ /// This macro processes an impl block and generates:
45
+ /// - Marker structs for each workflow method
46
+ /// - Trait implementations for workflow definition and execution
47
+ /// - Registration code for workers
48
+ ///
49
+ /// ## Macro Attributes
50
+ ///
51
+ /// - `factory_only` - When set, the workflow must be registered using
52
+ /// `register_workflow_with_factory` and does not need to implement `Default` or define an `#[init]`
53
+ /// method. Ex: `#[workflow_methods(factory_only)]`
54
+ ///
55
+ /// ## Method Attributes
56
+ ///
57
+ /// - `#[init]` - Optional initialization method. Signature: `fn new(input: T, ctx: &WorkflowContext) -> Self`
58
+ /// - `#[run]` - Required main workflow function. Signature: `async fn run(&mut self, ctx: &mut WorkflowContext) -> WorkflowResult<T>`
59
+ /// - `#[signal]` - Signal handler. Sync: `fn signal(&mut self, ctx: &mut SyncWorkflowContext, input: T)`. Async: `async fn signal(ctx: &mut WorkflowContext, input: T)`
60
+ /// - `#[query]` - Query handler. Signature: `fn query(&self, ctx: &WorkflowContextView, input: T) -> R` (must NOT be async)
61
+ /// - `#[update]` - Update handler. Sync: `fn update(&mut self, ctx: &mut SyncWorkflowContext, input: T) -> R`. Async: `async fn update(ctx: &mut WorkflowContext, input: T) -> R`
62
+ ///
63
+ /// For a usage example, see the `temporalio_sdk` crate's documentation.
64
+ #[proc_macro_attribute]
65
+ pub fn workflow_methods(attr: TokenStream, item: TokenStream) -> TokenStream {
66
+ let factory_only = !attr.is_empty() && attr.to_string().contains("factory_only");
67
+ let def: workflow_definitions::WorkflowMethodsDefinition =
68
+ parse_macro_input!(item as workflow_definitions::WorkflowMethodsDefinition);
69
+ def.codegen_with_options(factory_only)
70
+ }
71
+
72
+ /// Marks a method within a `#[workflow_methods]` impl block as the initialization method.
73
+ /// This attribute is processed by the `#[workflow_methods]` macro and should not be used standalone.
74
+ #[proc_macro_attribute]
75
+ pub fn init(_attr: TokenStream, item: TokenStream) -> TokenStream {
76
+ item
77
+ }
78
+
79
+ /// Marks a method within a `#[workflow_methods]` impl block as the main run method.
80
+ /// This attribute is processed by the `#[workflow_methods]` macro and should not be used standalone.
81
+ #[proc_macro_attribute]
82
+ pub fn run(_attr: TokenStream, item: TokenStream) -> TokenStream {
83
+ item
84
+ }
85
+
86
+ /// Marks a method within a `#[workflow_methods]` impl block as a signal handler.
87
+ /// This attribute is processed by the `#[workflow_methods]` macro and should not be used standalone.
88
+ ///
89
+ /// Supports an optional `name` parameter to override the signal name:
90
+ /// `#[signal(name = "my_signal")]`
91
+ #[proc_macro_attribute]
92
+ pub fn signal(_attr: TokenStream, item: TokenStream) -> TokenStream {
93
+ item
94
+ }
95
+
96
+ /// Marks a method within a `#[workflow_methods]` impl block as a query handler.
97
+ /// This attribute is processed by the `#[workflow_methods]` macro and should not be used standalone.
98
+ ///
99
+ /// Supports an optional `name` parameter to override the query name:
100
+ /// `#[query(name = "my_query")]`
101
+ #[proc_macro_attribute]
102
+ pub fn query(_attr: TokenStream, item: TokenStream) -> TokenStream {
103
+ item
104
+ }
105
+
106
+ /// Marks a method within a `#[workflow_methods]` impl block as an update handler.
107
+ /// This attribute is processed by the `#[workflow_methods]` macro and should not be used standalone.
108
+ ///
109
+ /// Supports an optional `name` parameter to override the update name:
110
+ /// `#[update(name = "my_update")]`
111
+ #[proc_macro_attribute]
112
+ pub fn update(_attr: TokenStream, item: TokenStream) -> TokenStream {
113
+ item
114
+ }
115
+
116
+ /// Marks a method within a `#[workflow_methods]` impl block as a validator for an update handler.
117
+ /// This attribute is processed by the `#[workflow_methods]` macro and should not be used standalone.
118
+ ///
119
+ /// The parameter specifies which update this validator applies to:
120
+ /// `#[update_validator(my_update)]`
121
+ ///
122
+ /// The validator method must:
123
+ /// - Take `&self` (not `&mut self`)
124
+ /// - Take `&WorkflowContextView` as the first parameter
125
+ /// - Take a reference to the update's input type as the second parameter
126
+ /// - Return `Result<(), Box<dyn std::error::Error + Send + Sync>>`
127
+ #[proc_macro_attribute]
128
+ pub fn update_validator(_attr: TokenStream, item: TokenStream) -> TokenStream {
129
+ item
130
+ }
10
131
 
11
132
  /// Parses a DSL for defining finite state machines, and produces code implementing the
12
133
  /// [StateMachine](trait.StateMachine.html) trait.
13
134
  ///
14
135
  /// An example state machine definition of a card reader for unlocking a door:
15
136
  /// ```
16
- /// use temporalio_macros::fsm;
17
137
  /// use std::convert::Infallible;
18
138
  /// use temporalio_common::fsm_trait::{StateMachine, TransitionResult};
139
+ /// use temporalio_macros::fsm;
19
140
  ///
20
141
  /// fsm! {
21
142
  /// name CardReader; command Commands; error Infallible; shared_state SharedState;
@@ -29,7 +150,7 @@ use syn::{
29
150
  ///
30
151
  /// #[derive(Clone)]
31
152
  /// pub struct SharedState {
32
- /// last_id: Option<String>
153
+ /// last_id: Option<String>,
33
154
  /// }
34
155
  ///
35
156
  /// #[derive(Debug, Clone, Eq, PartialEq, Hash)]
@@ -61,8 +182,11 @@ use syn::{
61
182
  /// }
62
183
  ///
63
184
  /// impl Locked {
64
- /// fn on_card_readable(&self, shared_dat: &mut SharedState, data: CardData)
65
- /// -> CardReaderTransition<ReadingCardOrLocked> {
185
+ /// fn on_card_readable(
186
+ /// &self,
187
+ /// shared_dat: &mut SharedState,
188
+ /// data: CardData,
189
+ /// ) -> CardReaderTransition<ReadingCardOrLocked> {
66
190
  /// match &shared_dat.last_id {
67
191
  /// // Arbitrarily deny the same person entering twice in a row
68
192
  /// Some(d) if d == &data => TransitionResult::ok(vec![], Locked {}.into()),
@@ -165,505 +289,7 @@ use syn::{
165
289
  /// this case, `CardReaderTransition`.
166
290
  #[proc_macro]
167
291
  pub fn fsm(input: TokenStream) -> TokenStream {
168
- let def: StateMachineDefinition = parse_macro_input!(input as StateMachineDefinition);
292
+ let def: fsm_impl::StateMachineDefinition =
293
+ parse_macro_input!(input as fsm_impl::StateMachineDefinition);
169
294
  def.codegen()
170
295
  }
171
-
172
- mod kw {
173
- syn::custom_keyword!(name);
174
- syn::custom_keyword!(command);
175
- syn::custom_keyword!(error);
176
- syn::custom_keyword!(shared);
177
- syn::custom_keyword!(shared_state);
178
- }
179
-
180
- struct StateMachineDefinition {
181
- visibility: Visibility,
182
- name: Ident,
183
- shared_state_type: Option<Type>,
184
- command_type: Ident,
185
- error_type: Ident,
186
- transitions: Vec<Transition>,
187
- }
188
-
189
- impl StateMachineDefinition {
190
- fn is_final_state(&self, state: &Ident) -> bool {
191
- // If no transitions go from this state, it's a final state.
192
- !self.transitions.iter().any(|t| t.from == *state)
193
- }
194
- }
195
-
196
- impl Parse for StateMachineDefinition {
197
- fn parse(input: ParseStream) -> Result<Self> {
198
- // Parse visibility if present
199
- let visibility = input.parse()?;
200
- // parse the state machine name, command type, and error type
201
- let (name, command_type, error_type, shared_state_type) = parse_machine_types(input)
202
- .map_err(|mut e| {
203
- e.combine(Error::new(
204
- e.span(),
205
- "The fsm definition should begin with `name MachineName; command CommandType; \
206
- error ErrorType;` optionally followed by `shared_state SharedStateType;`",
207
- ));
208
- e
209
- })?;
210
- // Then the state machine definition is simply a sequence of transitions separated by
211
- // semicolons
212
- let transitions = input.parse_terminated(Transition::parse, Token![;])?;
213
- let transitions: Vec<_> = transitions.into_iter().collect();
214
- // Check for and whine about any identical transitions. We do this here because preserving
215
- // the order transitions were defined in is important, so simply collecting to a set is
216
- // not ideal.
217
- let trans_set: HashSet<_> = transitions.iter().collect();
218
- if trans_set.len() != transitions.len() {
219
- return Err(Error::new(
220
- input.span(),
221
- "Duplicate transitions are not allowed!",
222
- ));
223
- }
224
- Ok(Self {
225
- visibility,
226
- name,
227
- shared_state_type,
228
- command_type,
229
- error_type,
230
- transitions,
231
- })
232
- }
233
- }
234
-
235
- fn parse_machine_types(input: ParseStream) -> Result<(Ident, Ident, Ident, Option<Type>)> {
236
- let _: kw::name = input.parse()?;
237
- let name: Ident = input.parse()?;
238
- input.parse::<Token![;]>()?;
239
-
240
- let _: kw::command = input.parse()?;
241
- let command_type: Ident = input.parse()?;
242
- input.parse::<Token![;]>()?;
243
-
244
- let _: kw::error = input.parse()?;
245
- let error_type: Ident = input.parse()?;
246
- input.parse::<Token![;]>()?;
247
-
248
- let shared_state_type: Option<Type> = if input.peek(kw::shared_state) {
249
- let _: kw::shared_state = input.parse()?;
250
- let typep = input.parse()?;
251
- input.parse::<Token![;]>()?;
252
- Some(typep)
253
- } else {
254
- None
255
- };
256
- Ok((name, command_type, error_type, shared_state_type))
257
- }
258
-
259
- #[derive(Debug, Clone, Eq, PartialEq, Hash)]
260
- struct Transition {
261
- from: Ident,
262
- to: Vec<Ident>,
263
- event: Variant,
264
- handler: Option<Ident>,
265
- mutates_shared: bool,
266
- }
267
-
268
- impl Parse for Transition {
269
- fn parse(input: ParseStream) -> Result<Self> {
270
- // Parse the initial state name
271
- let from: Ident = input.parse()?;
272
- // Parse at least one dash
273
- input.parse::<Token![-]>()?;
274
- while input.peek(Token![-]) {
275
- input.parse::<Token![-]>()?;
276
- }
277
- // Parse transition information inside parens
278
- let transition_info;
279
- parenthesized!(transition_info in input);
280
- // Get the event variant definition
281
- let event: Variant = transition_info.parse()?;
282
- // Reject non-unit or single-item-tuple variants
283
- match &event.fields {
284
- Fields::Named(_) => {
285
- return Err(Error::new(
286
- event.span(),
287
- "Struct variants are not supported for events",
288
- ));
289
- }
290
- Fields::Unnamed(uf) => {
291
- if uf.unnamed.len() != 1 {
292
- return Err(Error::new(
293
- event.span(),
294
- "Only tuple variants with exactly one item are supported for events",
295
- ));
296
- }
297
- }
298
- Fields::Unit => {}
299
- }
300
- // Check if there is an event handler, and parse it
301
- let (mutates_shared, handler) = if transition_info.peek(Token![,]) {
302
- transition_info.parse::<Token![,]>()?;
303
- // Check for mut keyword signifying handler wants to mutate shared state
304
- let mutates = if transition_info.peek(kw::shared) {
305
- transition_info.parse::<kw::shared>()?;
306
- true
307
- } else {
308
- false
309
- };
310
- (mutates, Some(transition_info.parse()?))
311
- } else {
312
- (false, None)
313
- };
314
- // Parse at least one dash followed by the "arrow"
315
- input.parse::<Token![-]>()?;
316
- while input.peek(Token![-]) {
317
- input.parse::<Token![-]>()?;
318
- }
319
- input.parse::<Token![>]>()?;
320
- // Parse the destination state
321
- let to: Ident = input.parse()?;
322
-
323
- Ok(Self {
324
- from,
325
- event,
326
- handler,
327
- to: vec![to],
328
- mutates_shared,
329
- })
330
- }
331
- }
332
-
333
- impl StateMachineDefinition {
334
- fn codegen(&self) -> TokenStream {
335
- let visibility = self.visibility.clone();
336
- // First extract all of the states into a set, and build the enum's insides
337
- let states = self.all_states();
338
- let state_variants = states.iter().map(|s| {
339
- let statestr = s.to_string();
340
- quote! {
341
- #[display(#statestr)]
342
- #s(#s)
343
- }
344
- });
345
- let name = &self.name;
346
- let name_str = &self.name.to_string();
347
-
348
- let transition_result_name = Ident::new(&format!("{name}Transition"), name.span());
349
- let transition_type_alias = quote! {
350
- type #transition_result_name<Ds, Sm = #name> = TransitionResult<Sm, Ds>;
351
- };
352
-
353
- let state_enum_name = Ident::new(&format!("{name}State"), name.span());
354
- // If user has not defined any shared state, use the unit type.
355
- let shared_state_type = self
356
- .shared_state_type
357
- .clone()
358
- .unwrap_or_else(|| syn::parse_str("()").unwrap());
359
- let machine_struct = quote! {
360
- #[derive(Clone)]
361
- #visibility struct #name {
362
- state: ::core::option::Option<#state_enum_name>,
363
- shared_state: #shared_state_type
364
- }
365
- };
366
- let states_enum = quote! {
367
- #[derive(::derive_more::From, Clone, ::derive_more::Display)]
368
- #visibility enum #state_enum_name {
369
- #(#state_variants),*
370
- }
371
- };
372
- let state_is_final_match_arms = states.iter().map(|s| {
373
- let val = if self.is_final_state(s) {
374
- quote! { true }
375
- } else {
376
- quote! { false }
377
- };
378
- quote! { #state_enum_name::#s(_) => #val }
379
- });
380
- let states_enum_impl = quote! {
381
- impl #state_enum_name {
382
- fn is_final(&self) -> bool {
383
- match self {
384
- #(#state_is_final_match_arms),*
385
- }
386
- }
387
- }
388
- };
389
-
390
- // Build the events enum
391
- let events: HashSet<Variant> = self.transitions.iter().map(|t| t.event.clone()).collect();
392
- let events_enum_name = Ident::new(&format!("{name}Events"), name.span());
393
- let events: Vec<_> = events
394
- .into_iter()
395
- .map(|v| {
396
- let vname = v.ident.to_string();
397
- quote! {
398
- #[display(#vname)]
399
- #v
400
- }
401
- })
402
- .collect();
403
- let events_enum = quote! {
404
- #[derive(::derive_more::Display)]
405
- #visibility enum #events_enum_name {
406
- #(#events),*
407
- }
408
- };
409
-
410
- // Construct the trait implementation
411
- let cmd_type = &self.command_type;
412
- let err_type = &self.error_type;
413
- let mut statemap: HashMap<Ident, Vec<Transition>> = HashMap::new();
414
- for t in &self.transitions {
415
- statemap
416
- .entry(t.from.clone())
417
- .and_modify(|v| v.push(t.clone()))
418
- .or_insert_with(|| vec![t.clone()]);
419
- }
420
- // Add any states without any transitions to the map
421
- for s in &states {
422
- if !statemap.contains_key(s) {
423
- statemap.insert(s.clone(), vec![]);
424
- }
425
- }
426
- let transition_result_transform = quote! {
427
- match res.into_cmd_result() {
428
- Ok((cmds, state)) => {
429
- self.state = Some(state);
430
- Ok(cmds)
431
- }
432
- Err(e) => Err(e)
433
- }
434
- };
435
- let mut multi_dest_enums = vec![];
436
- let mut multi_dest_enum_names = HashSet::new();
437
- let state_branches: Vec<_> = statemap.into_iter().map(|(from, transitions)| {
438
- let occupied_current_state = quote! { Some(#state_enum_name::#from(state_data)) };
439
- // Merge transition dest states with the same handler
440
- let transitions = merge_transition_dests(transitions);
441
- let event_branches = transitions
442
- .into_iter()
443
- .map(|ts| {
444
- let ev_variant = &ts.event.ident;
445
- if let Some(ts_fn) = ts.handler.clone() {
446
- let span = ts_fn.span();
447
- let trans_type = match ts.to.as_slice() {
448
- [] => unreachable!("There will be at least one dest state in transitions"),
449
- [one_to] => quote! {
450
- #transition_result_name<#one_to>
451
- },
452
- multi_dests => {
453
- let string_dests: Vec<_> = multi_dests.iter()
454
- .map(ToString::to_string).collect();
455
- let enum_ident = Ident::new(&string_dests.join("Or"),
456
- multi_dests[0].span());
457
- let multi_dest_enum = quote! {
458
- #[derive(::derive_more::From)]
459
- #visibility enum #enum_ident {
460
- #(#multi_dests(#multi_dests)),*
461
- }
462
- impl ::core::convert::From<#enum_ident> for #state_enum_name {
463
- fn from(v: #enum_ident) -> Self {
464
- match v {
465
- #( #enum_ident::#multi_dests(sv) =>
466
- Self::#multi_dests(sv) ),*
467
- }
468
- }
469
- }
470
- };
471
- // Deduplicate; two different events may each result in a transition
472
- // set with the same set of dest states
473
- if multi_dest_enum_names.insert(enum_ident.clone()) {
474
- multi_dest_enums.push(multi_dest_enum);
475
- }
476
- quote! {
477
- #transition_result_name<#enum_ident>
478
- }
479
- }
480
- };
481
- match ts.event.fields {
482
- Fields::Unnamed(_) => {
483
- let arglist = if ts.mutates_shared {
484
- quote! {&mut self.shared_state, val}
485
- } else {
486
- quote! {val}
487
- };
488
- quote_spanned! { span =>
489
- #events_enum_name::#ev_variant(val) => {
490
- let res: #trans_type = state_data.#ts_fn(#arglist);
491
- #transition_result_transform
492
- }
493
- }
494
- }
495
- Fields::Unit => {
496
- let arglist = if ts.mutates_shared {
497
- quote! {&mut self.shared_state}
498
- } else {
499
- quote! {}
500
- };
501
- quote_spanned! { span =>
502
- #events_enum_name::#ev_variant => {
503
- let res: #trans_type = state_data.#ts_fn(#arglist);
504
- #transition_result_transform
505
- }
506
- }
507
- }
508
- Fields::Named(_) => unreachable!(),
509
- }
510
- } else {
511
- // If events do not have a handler, attempt to construct the next state
512
- // using `Default`.
513
- if let [new_state] = ts.to.as_slice() {
514
- let span = new_state.span();
515
- let default_trans = quote_spanned! { span =>
516
- let res = TransitionResult::<Self, #new_state>::from::<#from>(state_data);
517
- #transition_result_transform
518
- };
519
- let span = ts.event.span();
520
- match ts.event.fields {
521
- Fields::Unnamed(_) => quote_spanned! { span =>
522
- #events_enum_name::#ev_variant(_val) => {
523
- #default_trans
524
- }
525
- },
526
- Fields::Unit => quote_spanned! { span =>
527
- #events_enum_name::#ev_variant => {
528
- #default_trans
529
- }
530
- },
531
- Fields::Named(_) => unreachable!(),
532
- }
533
- } else {
534
- unreachable!("It should be impossible to have more than one dest state \
535
- in no-handler transitions")
536
- }
537
- }
538
- })
539
- // Since most states won't handle every possible event, return an error to that
540
- // effect
541
- .chain(std::iter::once(
542
- quote! { _ => {
543
- // Restore state in event the transition doesn't match
544
- self.state = #occupied_current_state;
545
- return Err(::temporalio_common::fsm_trait::MachineError::InvalidTransition)
546
- } },
547
- ));
548
- quote! {
549
- #occupied_current_state => match event {
550
- #(#event_branches),*
551
- }
552
- }
553
- }).chain(std::iter::once(
554
- quote! {
555
- None => Err(::temporalio_common::fsm_trait::MachineError::InvalidTransition)
556
- }
557
- )).collect();
558
-
559
- let viz_str = self.visualize();
560
-
561
- let trait_impl = quote! {
562
- impl ::temporalio_common::fsm_trait::StateMachine for #name {
563
- type Error = #err_type;
564
- type State = #state_enum_name;
565
- type SharedState = #shared_state_type;
566
- type Event = #events_enum_name;
567
- type Command = #cmd_type;
568
-
569
- fn name(&self) -> &str {
570
- #name_str
571
- }
572
-
573
- fn on_event(&mut self, event: #events_enum_name)
574
- -> ::core::result::Result<::std::vec::Vec<Self::Command>,
575
- ::temporalio_common::fsm_trait::MachineError<Self::Error>> {
576
- let taken_state = self.state.take();
577
- match taken_state {
578
- #(#state_branches),*
579
- }
580
- }
581
-
582
- fn state(&self) -> &Self::State {
583
- self.state.as_ref().unwrap()
584
- }
585
-
586
- fn shared_state(&self) -> &Self::SharedState{
587
- &self.shared_state
588
- }
589
-
590
- fn has_reached_final_state(&self) -> bool {
591
- self.state.as_ref().unwrap().is_final()
592
- }
593
-
594
- fn from_parts(state: Self::State, shared: Self::SharedState) -> Self {
595
- Self { shared_state: shared, state: Some(state) }
596
- }
597
-
598
- fn visualizer() -> &'static str {
599
- #viz_str
600
- }
601
- }
602
- };
603
-
604
- let output = quote! {
605
- #transition_type_alias
606
- #machine_struct
607
- #states_enum
608
- #(#multi_dest_enums)*
609
- #states_enum_impl
610
- #events_enum
611
- #trait_impl
612
- };
613
-
614
- TokenStream::from(output)
615
- }
616
-
617
- fn all_states(&self) -> HashSet<Ident> {
618
- self.transitions
619
- .iter()
620
- .flat_map(|t| {
621
- let mut states = t.to.clone();
622
- states.push(t.from.clone());
623
- states
624
- })
625
- .collect()
626
- }
627
-
628
- fn visualize(&self) -> String {
629
- let transitions: Vec<String> = self
630
- .transitions
631
- .iter()
632
- .flat_map(|t| {
633
- t.to.iter()
634
- .map(move |d| format!("{} --> {}: {}", t.from, d, t.event.ident))
635
- })
636
- // Add all final state transitions
637
- .chain(
638
- self.all_states()
639
- .iter()
640
- .filter(|s| self.is_final_state(s))
641
- .map(|s| format!("{s} --> [*]")),
642
- )
643
- .collect();
644
- let transitions = transitions.join("\n");
645
- format!("@startuml\n{transitions}\n@enduml")
646
- }
647
- }
648
-
649
- /// Merge transition's dest state lists for those with the same from state & handler
650
- fn merge_transition_dests(transitions: Vec<Transition>) -> Vec<Transition> {
651
- let mut map = HashMap::<_, Transition>::new();
652
- for t in transitions {
653
- // We want to use the transition sans-destinations as the key
654
- let without_dests = {
655
- let mut wd = t.clone();
656
- wd.to = vec![];
657
- wd
658
- };
659
- match map.entry(without_dests) {
660
- Entry::Occupied(mut e) => {
661
- e.get_mut().to.extend(t.to.into_iter());
662
- }
663
- Entry::Vacant(v) => {
664
- v.insert(t);
665
- }
666
- }
667
- }
668
- map.into_values().collect()
669
- }