temporalio 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +20 -0
  4. data/README.md +130 -0
  5. data/bridge/Cargo.lock +2865 -0
  6. data/bridge/Cargo.toml +26 -0
  7. data/bridge/sdk-core/ARCHITECTURE.md +76 -0
  8. data/bridge/sdk-core/Cargo.lock +2606 -0
  9. data/bridge/sdk-core/Cargo.toml +2 -0
  10. data/bridge/sdk-core/LICENSE.txt +23 -0
  11. data/bridge/sdk-core/README.md +107 -0
  12. data/bridge/sdk-core/arch_docs/diagrams/README.md +10 -0
  13. data/bridge/sdk-core/arch_docs/diagrams/sticky_queues.puml +40 -0
  14. data/bridge/sdk-core/arch_docs/diagrams/workflow_internals.svg +1 -0
  15. data/bridge/sdk-core/arch_docs/sticky_queues.md +51 -0
  16. data/bridge/sdk-core/bridge-ffi/Cargo.toml +24 -0
  17. data/bridge/sdk-core/bridge-ffi/LICENSE.txt +23 -0
  18. data/bridge/sdk-core/bridge-ffi/build.rs +25 -0
  19. data/bridge/sdk-core/bridge-ffi/include/sdk-core-bridge.h +249 -0
  20. data/bridge/sdk-core/bridge-ffi/src/lib.rs +825 -0
  21. data/bridge/sdk-core/bridge-ffi/src/wrappers.rs +211 -0
  22. data/bridge/sdk-core/client/Cargo.toml +40 -0
  23. data/bridge/sdk-core/client/LICENSE.txt +23 -0
  24. data/bridge/sdk-core/client/src/lib.rs +1294 -0
  25. data/bridge/sdk-core/client/src/metrics.rs +165 -0
  26. data/bridge/sdk-core/client/src/raw.rs +931 -0
  27. data/bridge/sdk-core/client/src/retry.rs +674 -0
  28. data/bridge/sdk-core/client/src/workflow_handle/mod.rs +185 -0
  29. data/bridge/sdk-core/core/Cargo.toml +116 -0
  30. data/bridge/sdk-core/core/LICENSE.txt +23 -0
  31. data/bridge/sdk-core/core/benches/workflow_replay.rs +73 -0
  32. data/bridge/sdk-core/core/src/abstractions.rs +166 -0
  33. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +911 -0
  34. data/bridge/sdk-core/core/src/core_tests/child_workflows.rs +221 -0
  35. data/bridge/sdk-core/core/src/core_tests/determinism.rs +107 -0
  36. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +515 -0
  37. data/bridge/sdk-core/core/src/core_tests/mod.rs +100 -0
  38. data/bridge/sdk-core/core/src/core_tests/queries.rs +736 -0
  39. data/bridge/sdk-core/core/src/core_tests/replay_flag.rs +65 -0
  40. data/bridge/sdk-core/core/src/core_tests/workers.rs +259 -0
  41. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +124 -0
  42. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +2070 -0
  43. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +515 -0
  44. data/bridge/sdk-core/core/src/lib.rs +175 -0
  45. data/bridge/sdk-core/core/src/log_export.rs +62 -0
  46. data/bridge/sdk-core/core/src/pollers/mod.rs +54 -0
  47. data/bridge/sdk-core/core/src/pollers/poll_buffer.rs +297 -0
  48. data/bridge/sdk-core/core/src/protosext/mod.rs +428 -0
  49. data/bridge/sdk-core/core/src/replay/mod.rs +71 -0
  50. data/bridge/sdk-core/core/src/retry_logic.rs +202 -0
  51. data/bridge/sdk-core/core/src/telemetry/metrics.rs +383 -0
  52. data/bridge/sdk-core/core/src/telemetry/mod.rs +412 -0
  53. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +77 -0
  54. data/bridge/sdk-core/core/src/test_help/mod.rs +875 -0
  55. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +580 -0
  56. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +1042 -0
  57. data/bridge/sdk-core/core/src/worker/activities.rs +464 -0
  58. data/bridge/sdk-core/core/src/worker/client/mocks.rs +87 -0
  59. data/bridge/sdk-core/core/src/worker/client.rs +347 -0
  60. data/bridge/sdk-core/core/src/worker/mod.rs +566 -0
  61. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +37 -0
  62. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +110 -0
  63. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +458 -0
  64. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +911 -0
  65. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +298 -0
  66. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +171 -0
  67. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +860 -0
  68. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +140 -0
  69. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +161 -0
  70. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +133 -0
  71. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +1448 -0
  72. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +342 -0
  73. data/bridge/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +127 -0
  74. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +712 -0
  75. data/bridge/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +71 -0
  76. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +443 -0
  77. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +439 -0
  78. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +169 -0
  79. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +246 -0
  80. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +96 -0
  81. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +1184 -0
  82. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +277 -0
  83. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +198 -0
  84. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +647 -0
  85. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +1143 -0
  86. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +145 -0
  87. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +88 -0
  88. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +940 -0
  89. data/bridge/sdk-core/core-api/Cargo.toml +31 -0
  90. data/bridge/sdk-core/core-api/LICENSE.txt +23 -0
  91. data/bridge/sdk-core/core-api/src/errors.rs +95 -0
  92. data/bridge/sdk-core/core-api/src/lib.rs +151 -0
  93. data/bridge/sdk-core/core-api/src/worker.rs +135 -0
  94. data/bridge/sdk-core/etc/deps.svg +187 -0
  95. data/bridge/sdk-core/etc/dynamic-config.yaml +2 -0
  96. data/bridge/sdk-core/etc/otel-collector-config.yaml +36 -0
  97. data/bridge/sdk-core/etc/prometheus.yaml +6 -0
  98. data/bridge/sdk-core/fsm/Cargo.toml +18 -0
  99. data/bridge/sdk-core/fsm/LICENSE.txt +23 -0
  100. data/bridge/sdk-core/fsm/README.md +3 -0
  101. data/bridge/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +27 -0
  102. data/bridge/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +23 -0
  103. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +647 -0
  104. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +8 -0
  105. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.rs +18 -0
  106. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +12 -0
  107. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dynamic_dest_pass.rs +41 -0
  108. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.rs +14 -0
  109. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.stderr +11 -0
  110. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_arg_pass.rs +32 -0
  111. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_pass.rs +31 -0
  112. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/medium_complex_pass.rs +46 -0
  113. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.rs +29 -0
  114. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +12 -0
  115. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/simple_pass.rs +32 -0
  116. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.rs +18 -0
  117. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +5 -0
  118. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.rs +11 -0
  119. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +5 -0
  120. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.rs +11 -0
  121. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +5 -0
  122. data/bridge/sdk-core/fsm/rustfsm_trait/Cargo.toml +14 -0
  123. data/bridge/sdk-core/fsm/rustfsm_trait/LICENSE.txt +23 -0
  124. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +249 -0
  125. data/bridge/sdk-core/fsm/src/lib.rs +2 -0
  126. data/bridge/sdk-core/histories/fail_wf_task.bin +0 -0
  127. data/bridge/sdk-core/histories/timer_workflow_history.bin +0 -0
  128. data/bridge/sdk-core/integ-with-otel.sh +7 -0
  129. data/bridge/sdk-core/protos/api_upstream/README.md +9 -0
  130. data/bridge/sdk-core/protos/api_upstream/api-linter.yaml +40 -0
  131. data/bridge/sdk-core/protos/api_upstream/buf.yaml +12 -0
  132. data/bridge/sdk-core/protos/api_upstream/dependencies/gogoproto/gogo.proto +141 -0
  133. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +86 -0
  134. data/bridge/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +83 -0
  135. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +259 -0
  136. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +112 -0
  137. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +46 -0
  138. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/cluster.proto +40 -0
  139. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +57 -0
  140. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +55 -0
  141. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +168 -0
  142. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +97 -0
  143. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +51 -0
  144. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +50 -0
  145. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +41 -0
  146. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +60 -0
  147. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +59 -0
  148. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +51 -0
  149. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +122 -0
  150. data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +108 -0
  151. data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +114 -0
  152. data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +56 -0
  153. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +751 -0
  154. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +97 -0
  155. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +161 -0
  156. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +99 -0
  157. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +61 -0
  158. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +55 -0
  159. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +300 -0
  160. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +108 -0
  161. data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +46 -0
  162. data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +59 -0
  163. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +145 -0
  164. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +1124 -0
  165. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +401 -0
  166. data/bridge/sdk-core/protos/grpc/health/v1/health.proto +63 -0
  167. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
  168. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +79 -0
  169. data/bridge/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +210 -0
  170. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +77 -0
  171. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +15 -0
  172. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +30 -0
  173. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
  174. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +261 -0
  175. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +297 -0
  176. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +29 -0
  177. data/bridge/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
  178. data/bridge/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
  179. data/bridge/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
  180. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
  181. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
  182. data/bridge/sdk-core/rustfmt.toml +1 -0
  183. data/bridge/sdk-core/sdk/Cargo.toml +47 -0
  184. data/bridge/sdk-core/sdk/LICENSE.txt +23 -0
  185. data/bridge/sdk-core/sdk/src/activity_context.rs +230 -0
  186. data/bridge/sdk-core/sdk/src/app_data.rs +37 -0
  187. data/bridge/sdk-core/sdk/src/conversions.rs +8 -0
  188. data/bridge/sdk-core/sdk/src/interceptors.rs +17 -0
  189. data/bridge/sdk-core/sdk/src/lib.rs +792 -0
  190. data/bridge/sdk-core/sdk/src/payload_converter.rs +11 -0
  191. data/bridge/sdk-core/sdk/src/workflow_context/options.rs +295 -0
  192. data/bridge/sdk-core/sdk/src/workflow_context.rs +683 -0
  193. data/bridge/sdk-core/sdk/src/workflow_future.rs +503 -0
  194. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +30 -0
  195. data/bridge/sdk-core/sdk-core-protos/LICENSE.txt +23 -0
  196. data/bridge/sdk-core/sdk-core-protos/build.rs +108 -0
  197. data/bridge/sdk-core/sdk-core-protos/src/constants.rs +7 -0
  198. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +497 -0
  199. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +230 -0
  200. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +1910 -0
  201. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
  202. data/bridge/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  203. data/bridge/sdk-core/test-utils/Cargo.toml +35 -0
  204. data/bridge/sdk-core/test-utils/src/canned_histories.rs +1579 -0
  205. data/bridge/sdk-core/test-utils/src/histfetch.rs +28 -0
  206. data/bridge/sdk-core/test-utils/src/lib.rs +598 -0
  207. data/bridge/sdk-core/tests/integ_tests/client_tests.rs +36 -0
  208. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +128 -0
  209. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +218 -0
  210. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +146 -0
  211. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +437 -0
  212. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
  213. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +878 -0
  214. data/bridge/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +61 -0
  215. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +59 -0
  216. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +58 -0
  217. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +50 -0
  218. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +60 -0
  219. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +54 -0
  220. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +634 -0
  221. data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +113 -0
  222. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +137 -0
  223. data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +93 -0
  224. data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +167 -0
  225. data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +99 -0
  226. data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +131 -0
  227. data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +75 -0
  228. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +587 -0
  229. data/bridge/sdk-core/tests/load_tests.rs +191 -0
  230. data/bridge/sdk-core/tests/main.rs +111 -0
  231. data/bridge/sdk-core/tests/runner.rs +93 -0
  232. data/bridge/src/connection.rs +167 -0
  233. data/bridge/src/lib.rs +180 -0
  234. data/bridge/src/runtime.rs +47 -0
  235. data/bridge/src/worker.rs +73 -0
  236. data/ext/Rakefile +9 -0
  237. data/lib/bridge.so +0 -0
  238. data/lib/gen/dependencies/gogoproto/gogo_pb.rb +14 -0
  239. data/lib/gen/temporal/api/batch/v1/message_pb.rb +48 -0
  240. data/lib/gen/temporal/api/cluster/v1/message_pb.rb +67 -0
  241. data/lib/gen/temporal/api/command/v1/message_pb.rb +166 -0
  242. data/lib/gen/temporal/api/common/v1/message_pb.rb +69 -0
  243. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +32 -0
  244. data/lib/gen/temporal/api/enums/v1/cluster_pb.rb +26 -0
  245. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +37 -0
  246. data/lib/gen/temporal/api/enums/v1/common_pb.rb +41 -0
  247. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +67 -0
  248. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +71 -0
  249. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +37 -0
  250. data/lib/gen/temporal/api/enums/v1/query_pb.rb +31 -0
  251. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +24 -0
  252. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +28 -0
  253. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +30 -0
  254. data/lib/gen/temporal/api/enums/v1/update_pb.rb +28 -0
  255. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +89 -0
  256. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +84 -0
  257. data/lib/gen/temporal/api/failure/v1/message_pb.rb +83 -0
  258. data/lib/gen/temporal/api/filter/v1/message_pb.rb +40 -0
  259. data/lib/gen/temporal/api/history/v1/message_pb.rb +489 -0
  260. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +63 -0
  261. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +125 -0
  262. data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +20 -0
  263. data/lib/gen/temporal/api/query/v1/message_pb.rb +38 -0
  264. data/lib/gen/temporal/api/replication/v1/message_pb.rb +37 -0
  265. data/lib/gen/temporal/api/schedule/v1/message_pb.rb +128 -0
  266. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +73 -0
  267. data/lib/gen/temporal/api/update/v1/message_pb.rb +26 -0
  268. data/lib/gen/temporal/api/version/v1/message_pb.rb +41 -0
  269. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +110 -0
  270. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +771 -0
  271. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +20 -0
  272. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +58 -0
  273. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +57 -0
  274. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +222 -0
  275. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +57 -0
  276. data/lib/gen/temporal/sdk/core/common/common_pb.rb +22 -0
  277. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +34 -0
  278. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +27 -0
  279. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +164 -0
  280. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +192 -0
  281. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +34 -0
  282. data/lib/temporal/bridge.rb +14 -0
  283. data/lib/temporal/client/implementation.rb +339 -0
  284. data/lib/temporal/client/workflow_handle.rb +243 -0
  285. data/lib/temporal/client.rb +144 -0
  286. data/lib/temporal/connection.rb +736 -0
  287. data/lib/temporal/data_converter.rb +150 -0
  288. data/lib/temporal/error/failure.rb +194 -0
  289. data/lib/temporal/error/workflow_failure.rb +17 -0
  290. data/lib/temporal/errors.rb +22 -0
  291. data/lib/temporal/failure_converter/base.rb +26 -0
  292. data/lib/temporal/failure_converter/basic.rb +313 -0
  293. data/lib/temporal/failure_converter.rb +8 -0
  294. data/lib/temporal/interceptor/chain.rb +27 -0
  295. data/lib/temporal/interceptor/client.rb +102 -0
  296. data/lib/temporal/payload_codec/base.rb +32 -0
  297. data/lib/temporal/payload_converter/base.rb +24 -0
  298. data/lib/temporal/payload_converter/bytes.rb +26 -0
  299. data/lib/temporal/payload_converter/composite.rb +47 -0
  300. data/lib/temporal/payload_converter/encoding_base.rb +35 -0
  301. data/lib/temporal/payload_converter/json.rb +25 -0
  302. data/lib/temporal/payload_converter/nil.rb +25 -0
  303. data/lib/temporal/payload_converter.rb +14 -0
  304. data/lib/temporal/retry_policy.rb +82 -0
  305. data/lib/temporal/retry_state.rb +35 -0
  306. data/lib/temporal/runtime.rb +22 -0
  307. data/lib/temporal/timeout_type.rb +29 -0
  308. data/lib/temporal/version.rb +3 -0
  309. data/lib/temporal/workflow/execution_info.rb +54 -0
  310. data/lib/temporal/workflow/execution_status.rb +36 -0
  311. data/lib/temporal/workflow/id_reuse_policy.rb +36 -0
  312. data/lib/temporal/workflow/query_reject_condition.rb +33 -0
  313. data/lib/temporal.rb +8 -0
  314. data/lib/temporalio.rb +3 -0
  315. data/lib/thermite_patch.rb +23 -0
  316. data/temporalio.gemspec +41 -0
  317. metadata +583 -0
@@ -0,0 +1,647 @@
1
+ use proc_macro::TokenStream;
2
+ use quote::{quote, quote_spanned};
3
+ use std::collections::{hash_map::Entry, HashMap, HashSet};
4
+ use syn::{
5
+ parenthesized,
6
+ parse::{Parse, ParseStream, Result},
7
+ parse_macro_input,
8
+ punctuated::Punctuated,
9
+ spanned::Spanned,
10
+ Error, Fields, Ident, Token, Type, Variant, Visibility,
11
+ };
12
+
13
+ /// Parses a DSL for defining finite state machines, and produces code implementing the
14
+ /// [StateMachine](trait.StateMachine.html) trait.
15
+ ///
16
+ /// An example state machine definition of a card reader for unlocking a door:
17
+ /// ```
18
+ /// # extern crate rustfsm_trait as rustfsm;
19
+ /// use rustfsm_procmacro::fsm;
20
+ /// use std::convert::Infallible;
21
+ /// use rustfsm_trait::{StateMachine, TransitionResult};
22
+ ///
23
+ /// fsm! {
24
+ /// name CardReader; command Commands; error Infallible; shared_state SharedState;
25
+ ///
26
+ /// Locked --(CardReadable(CardData), shared on_card_readable) --> ReadingCard;
27
+ /// Locked --(CardReadable(CardData), shared on_card_readable) --> Locked;
28
+ /// ReadingCard --(CardAccepted, on_card_accepted) --> DoorOpen;
29
+ /// ReadingCard --(CardRejected, on_card_rejected) --> Locked;
30
+ /// DoorOpen --(DoorClosed, on_door_closed) --> Locked;
31
+ /// }
32
+ ///
33
+ /// #[derive(Clone)]
34
+ /// pub struct SharedState {
35
+ /// last_id: Option<String>
36
+ /// }
37
+ ///
38
+ /// #[derive(Debug, Clone, Eq, PartialEq, Hash)]
39
+ /// pub enum Commands {
40
+ /// StartBlinkingLight,
41
+ /// StopBlinkingLight,
42
+ /// ProcessData(CardData),
43
+ /// }
44
+ ///
45
+ /// type CardData = String;
46
+ ///
47
+ /// /// Door is locked / idle / we are ready to read
48
+ /// #[derive(Debug, Clone, Eq, PartialEq, Hash, Default)]
49
+ /// pub struct Locked {}
50
+ ///
51
+ /// /// Actively reading the card
52
+ /// #[derive(Debug, Clone, Eq, PartialEq, Hash)]
53
+ /// pub struct ReadingCard {
54
+ /// card_data: CardData,
55
+ /// }
56
+ ///
57
+ /// /// The door is open, we shouldn't be accepting cards and should be blinking the light
58
+ /// #[derive(Debug, Clone, Eq, PartialEq, Hash)]
59
+ /// pub struct DoorOpen {}
60
+ /// impl DoorOpen {
61
+ /// fn on_door_closed(&self) -> CardReaderTransition<Locked> {
62
+ /// TransitionResult::ok(vec![], Locked {})
63
+ /// }
64
+ /// }
65
+ ///
66
+ /// impl Locked {
67
+ /// fn on_card_readable(&self, shared_dat: SharedState, data: CardData)
68
+ /// -> CardReaderTransition<ReadingCardOrLocked> {
69
+ /// match shared_dat.last_id {
70
+ /// // Arbitrarily deny the same person entering twice in a row
71
+ /// Some(d) if d == data => TransitionResult::ok(vec![], Locked {}.into()),
72
+ /// _ => {
73
+ /// // Otherwise issue a processing command. This illustrates using the same handler
74
+ /// // for different destinations
75
+ /// TransitionResult::ok_shared(
76
+ /// vec![
77
+ /// Commands::ProcessData(data.clone()),
78
+ /// Commands::StartBlinkingLight,
79
+ /// ],
80
+ /// ReadingCard { card_data: data.clone() }.into(),
81
+ /// SharedState { last_id: Some(data) }
82
+ /// )
83
+ /// }
84
+ /// }
85
+ /// }
86
+ /// }
87
+ ///
88
+ /// impl ReadingCard {
89
+ /// fn on_card_accepted(&self) -> CardReaderTransition<DoorOpen> {
90
+ /// TransitionResult::ok(vec![Commands::StopBlinkingLight], DoorOpen {})
91
+ /// }
92
+ /// fn on_card_rejected(&self) -> CardReaderTransition<Locked> {
93
+ /// TransitionResult::ok(vec![Commands::StopBlinkingLight], Locked {})
94
+ /// }
95
+ /// }
96
+ ///
97
+ /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
98
+ /// let crs = CardReaderState::Locked(Locked {});
99
+ /// let mut cr = CardReader { state: crs, shared_state: SharedState { last_id: None } };
100
+ /// let cmds = cr.on_event_mut(CardReaderEvents::CardReadable("badguy".to_string()))?;
101
+ /// assert_eq!(cmds[0], Commands::ProcessData("badguy".to_string()));
102
+ /// assert_eq!(cmds[1], Commands::StartBlinkingLight);
103
+ ///
104
+ /// let cmds = cr.on_event_mut(CardReaderEvents::CardRejected)?;
105
+ /// assert_eq!(cmds[0], Commands::StopBlinkingLight);
106
+ ///
107
+ /// let cmds = cr.on_event_mut(CardReaderEvents::CardReadable("goodguy".to_string()))?;
108
+ /// assert_eq!(cmds[0], Commands::ProcessData("goodguy".to_string()));
109
+ /// assert_eq!(cmds[1], Commands::StartBlinkingLight);
110
+ ///
111
+ /// let cmds = cr.on_event_mut(CardReaderEvents::CardAccepted)?;
112
+ /// assert_eq!(cmds[0], Commands::StopBlinkingLight);
113
+ /// # Ok(())
114
+ /// # }
115
+ /// ```
116
+ ///
117
+ /// In the above example the first word is the name of the state machine, then after the comma the
118
+ /// type (which you must define separately) of commands produced by the machine.
119
+ ///
120
+ /// then each line represents a transition, where the first word is the initial state, the tuple
121
+ /// inside the arrow is `(eventtype[, event handler])`, and the word after the arrow is the
122
+ /// destination state. here `eventtype` is an enum variant , and `event_handler` is a function you
123
+ /// must define outside the enum whose form depends on the event variant. the only variant types
124
+ /// allowed are unit and one-item tuple variants. For unit variants, the function takes no
125
+ /// parameters. For the tuple variants, the function takes the variant data as its parameter. In
126
+ /// either case the function is expected to return a `TransitionResult` to the appropriate state.
127
+ ///
128
+ /// The first transition can be interpreted as "If the machine is in the locked state, when a
129
+ /// `CardReadable` event is seen, call `on_card_readable` (passing in `CardData`) and transition to
130
+ /// the `ReadingCard` state.
131
+ ///
132
+ /// The macro will generate a few things:
133
+ /// * A struct for the overall state machine, named with the provided name. Here:
134
+ /// ```text
135
+ /// struct CardMachine {
136
+ /// state: CardMachineState,
137
+ /// shared_state: CardId,
138
+ /// }
139
+ /// ```
140
+ /// * An enum with a variant for each state, named with the provided name + "State".
141
+ /// ```text
142
+ /// enum CardMachineState {
143
+ /// Locked(Locked),
144
+ /// ReadingCard(ReadingCard),
145
+ /// Unlocked(Unlocked),
146
+ /// }
147
+ /// ```
148
+ ///
149
+ /// You are expected to define a type for each state, to contain that state's data. If there is
150
+ /// no data, you can simply: `type StateName = ()`
151
+ /// * For any instance of transitions with the same event/handler which transition to different
152
+ /// destination states (dynamic destinations), an enum named like `DestAOrDestBOrDestC` is
153
+ /// generated. This enum must be used as the destination "state" from those handlers.
154
+ /// * An enum with a variant for each event. You are expected to define the type (if any) contained
155
+ /// in the event variant.
156
+ /// ```text
157
+ /// enum CardMachineEvents {
158
+ /// CardReadable(CardData)
159
+ /// }
160
+ /// ```
161
+ /// * An implementation of the [StateMachine](trait.StateMachine.html) trait for the generated state
162
+ /// machine enum (in this case, `CardMachine`)
163
+ /// * A type alias for a [TransitionResult](enum.TransitionResult.html) with the appropriate generic
164
+ /// parameters set for your machine. It is named as your machine with `Transition` appended. In
165
+ /// this case, `CardMachineTransition`.
166
+ #[proc_macro]
167
+ pub fn fsm(input: TokenStream) -> TokenStream {
168
+ let def: StateMachineDefinition = parse_macro_input!(input as StateMachineDefinition);
169
+ def.codegen()
170
+ }
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: Punctuated<Transition, Token![;]> =
213
+ input.parse_terminated(Transition::parse)?;
214
+ let transitions: Vec<_> = transitions.into_iter().collect();
215
+ // Check for and whine about any identical transitions. We do this here because preserving
216
+ // the order transitions were defined in is important, so simply collecting to a set is
217
+ // not ideal.
218
+ let trans_set: HashSet<_> = transitions.iter().collect();
219
+ if trans_set.len() != transitions.len() {
220
+ return Err(syn::Error::new(
221
+ input.span(),
222
+ "Duplicate transitions are not allowed!",
223
+ ));
224
+ }
225
+ Ok(Self {
226
+ visibility,
227
+ name,
228
+ shared_state_type,
229
+ command_type,
230
+ error_type,
231
+ transitions,
232
+ })
233
+ }
234
+ }
235
+
236
+ fn parse_machine_types(input: ParseStream) -> Result<(Ident, Ident, Ident, Option<Type>)> {
237
+ let _: kw::name = input.parse()?;
238
+ let name: Ident = input.parse()?;
239
+ input.parse::<Token![;]>()?;
240
+
241
+ let _: kw::command = input.parse()?;
242
+ let command_type: Ident = input.parse()?;
243
+ input.parse::<Token![;]>()?;
244
+
245
+ let _: kw::error = input.parse()?;
246
+ let error_type: Ident = input.parse()?;
247
+ input.parse::<Token![;]>()?;
248
+
249
+ let shared_state_type: Option<Type> = if input.peek(kw::shared_state) {
250
+ let _: kw::shared_state = input.parse()?;
251
+ let typep = input.parse()?;
252
+ input.parse::<Token![;]>()?;
253
+ Some(typep)
254
+ } else {
255
+ None
256
+ };
257
+ Ok((name, command_type, error_type, shared_state_type))
258
+ }
259
+
260
+ #[derive(Debug, Clone, Eq, PartialEq, Hash)]
261
+ struct Transition {
262
+ from: Ident,
263
+ to: Vec<Ident>,
264
+ event: Variant,
265
+ handler: Option<Ident>,
266
+ mutates_shared: bool,
267
+ }
268
+
269
+ impl Parse for Transition {
270
+ fn parse(input: ParseStream) -> Result<Self> {
271
+ // Parse the initial state name
272
+ let from: Ident = input.parse()?;
273
+ // Parse at least one dash
274
+ input.parse::<Token![-]>()?;
275
+ while input.peek(Token![-]) {
276
+ input.parse::<Token![-]>()?;
277
+ }
278
+ // Parse transition information inside parens
279
+ let transition_info;
280
+ parenthesized!(transition_info in input);
281
+ // Get the event variant definition
282
+ let event: Variant = transition_info.parse()?;
283
+ // Reject non-unit or single-item-tuple variants
284
+ match &event.fields {
285
+ Fields::Named(_) => {
286
+ return Err(Error::new(
287
+ event.span(),
288
+ "Struct variants are not supported for events",
289
+ ))
290
+ }
291
+ Fields::Unnamed(uf) => {
292
+ if uf.unnamed.len() != 1 {
293
+ return Err(Error::new(
294
+ event.span(),
295
+ "Only tuple variants with exactly one item are supported for events",
296
+ ));
297
+ }
298
+ }
299
+ Fields::Unit => {}
300
+ }
301
+ // Check if there is an event handler, and parse it
302
+ let (mutates_shared, handler) = if transition_info.peek(Token![,]) {
303
+ transition_info.parse::<Token![,]>()?;
304
+ // Check for mut keyword signifying handler wants to mutate shared state
305
+ let mutates = if transition_info.peek(kw::shared) {
306
+ transition_info.parse::<kw::shared>()?;
307
+ true
308
+ } else {
309
+ false
310
+ };
311
+ (mutates, Some(transition_info.parse()?))
312
+ } else {
313
+ (false, None)
314
+ };
315
+ // Parse at least one dash followed by the "arrow"
316
+ input.parse::<Token![-]>()?;
317
+ while input.peek(Token![-]) {
318
+ input.parse::<Token![-]>()?;
319
+ }
320
+ input.parse::<Token![>]>()?;
321
+ // Parse the destination state
322
+ let to: Ident = input.parse()?;
323
+
324
+ Ok(Self {
325
+ from,
326
+ event,
327
+ handler,
328
+ to: vec![to],
329
+ mutates_shared,
330
+ })
331
+ }
332
+ }
333
+
334
+ impl StateMachineDefinition {
335
+ fn codegen(&self) -> TokenStream {
336
+ let visibility = self.visibility.clone();
337
+ // First extract all of the states into a set, and build the enum's insides
338
+ let states = self.all_states();
339
+ let state_variants = states.iter().map(|s| {
340
+ let statestr = s.to_string();
341
+ quote! {
342
+ #[display(fmt=#statestr)]
343
+ #s(#s)
344
+ }
345
+ });
346
+ let name = &self.name;
347
+ let name_str = &self.name.to_string();
348
+
349
+ let transition_result_name = Ident::new(&format!("{}Transition", name), name.span());
350
+ let transition_type_alias = quote! {
351
+ type #transition_result_name<Ds, Sm = #name> = TransitionResult<Sm, Ds>;
352
+ };
353
+
354
+ let state_enum_name = Ident::new(&format!("{}State", name), name.span());
355
+ // If user has not defined any shared state, use the unit type.
356
+ let shared_state_type = self
357
+ .shared_state_type
358
+ .clone()
359
+ .unwrap_or_else(|| syn::parse_str("()").unwrap());
360
+ let machine_struct = quote! {
361
+ #[derive(Clone)]
362
+ #visibility struct #name {
363
+ state: #state_enum_name,
364
+ shared_state: #shared_state_type
365
+ }
366
+ };
367
+ let states_enum = quote! {
368
+ #[derive(::derive_more::From, Clone, ::derive_more::Display)]
369
+ #visibility enum #state_enum_name {
370
+ #(#state_variants),*
371
+ }
372
+ };
373
+ let state_is_final_match_arms = states.iter().map(|s| {
374
+ let val = if self.is_final_state(s) {
375
+ quote! { true }
376
+ } else {
377
+ quote! { false }
378
+ };
379
+ quote! { #state_enum_name::#s(_) => #val }
380
+ });
381
+ let states_enum_impl = quote! {
382
+ impl #state_enum_name {
383
+ fn is_final(&self) -> bool {
384
+ match self {
385
+ #(#state_is_final_match_arms),*
386
+ }
387
+ }
388
+ }
389
+ };
390
+
391
+ // Build the events enum
392
+ let events: HashSet<Variant> = self.transitions.iter().map(|t| t.event.clone()).collect();
393
+ let events_enum_name = Ident::new(&format!("{}Events", name), name.span());
394
+ let events: Vec<_> = events
395
+ .into_iter()
396
+ .map(|v| {
397
+ let vname = v.ident.to_string();
398
+ quote! {
399
+ #[display(fmt=#vname)]
400
+ #v
401
+ }
402
+ })
403
+ .collect();
404
+ let events_enum = quote! {
405
+ #[derive(::derive_more::Display)]
406
+ #visibility enum #events_enum_name {
407
+ #(#events),*
408
+ }
409
+ };
410
+
411
+ // Construct the trait implementation
412
+ let cmd_type = &self.command_type;
413
+ let err_type = &self.error_type;
414
+ let mut statemap: HashMap<Ident, Vec<Transition>> = HashMap::new();
415
+ for t in &self.transitions {
416
+ statemap
417
+ .entry(t.from.clone())
418
+ .and_modify(|v| v.push(t.clone()))
419
+ .or_insert_with(|| vec![t.clone()]);
420
+ }
421
+ // Add any states without any transitions to the map
422
+ for s in &states {
423
+ if !statemap.contains_key(s) {
424
+ statemap.insert(s.clone(), vec![]);
425
+ }
426
+ }
427
+ let mut multi_dest_enums = vec![];
428
+ let state_branches: Vec<_> = statemap.into_iter().map(|(from, transitions)| {
429
+ // Merge transition dest states with the same handler
430
+ let transitions = merge_transition_dests(transitions);
431
+ let event_branches = transitions
432
+ .into_iter()
433
+ .map(|ts| {
434
+ let ev_variant = &ts.event.ident;
435
+ if let Some(ts_fn) = ts.handler.clone() {
436
+ let span = ts_fn.span();
437
+ let trans_type = match ts.to.as_slice() {
438
+ [] => unreachable!("There will be at least one dest state in transitions"),
439
+ [one_to] => quote! {
440
+ #transition_result_name<#one_to>
441
+ },
442
+ multi_dests => {
443
+ let string_dests: Vec<_> = multi_dests.iter()
444
+ .map(ToString::to_string).collect();
445
+ let enum_ident = Ident::new(&string_dests.join("Or"),
446
+ multi_dests[0].span());
447
+ let multi_dest_enum = quote! {
448
+ #[derive(::derive_more::From)]
449
+ #visibility enum #enum_ident {
450
+ #(#multi_dests(#multi_dests)),*
451
+ }
452
+ impl ::core::convert::From<#enum_ident> for #state_enum_name {
453
+ fn from(v: #enum_ident) -> Self {
454
+ match v {
455
+ #( #enum_ident::#multi_dests(sv) =>
456
+ Self::#multi_dests(sv) ),*
457
+ }
458
+ }
459
+ }
460
+ };
461
+ multi_dest_enums.push(multi_dest_enum);
462
+ quote! {
463
+ #transition_result_name<#enum_ident>
464
+ }
465
+ }
466
+ };
467
+ match ts.event.fields {
468
+ Fields::Unnamed(_) => {
469
+ let arglist = if ts.mutates_shared {
470
+ quote! {self.shared_state, val}
471
+ } else {
472
+ quote! {val}
473
+ };
474
+ quote_spanned! {span=>
475
+ #events_enum_name::#ev_variant(val) => {
476
+ let res: #trans_type = state_data.#ts_fn(#arglist);
477
+ res.into_general()
478
+ }
479
+ }
480
+ }
481
+ Fields::Unit => {
482
+ let arglist = if ts.mutates_shared {
483
+ quote! {self.shared_state}
484
+ } else {
485
+ quote! {}
486
+ };
487
+ quote_spanned! {span=>
488
+ #events_enum_name::#ev_variant => {
489
+ let res: #trans_type = state_data.#ts_fn(#arglist);
490
+ res.into_general()
491
+ }
492
+ }
493
+ }
494
+ Fields::Named(_) => unreachable!(),
495
+ }
496
+ } else {
497
+ // If events do not have a handler, attempt to construct the next state
498
+ // using `Default`.
499
+ if let [new_state] = ts.to.as_slice() {
500
+ let span = new_state.span();
501
+ let default_trans = quote_spanned! {span=>
502
+ TransitionResult::<_, #new_state>::from::<#from>(state_data).into_general()
503
+ };
504
+ let span = ts.event.span();
505
+ match ts.event.fields {
506
+ Fields::Unnamed(_) => quote_spanned! {span=>
507
+ #events_enum_name::#ev_variant(_val) => {
508
+ #default_trans
509
+ }
510
+ },
511
+ Fields::Unit => quote_spanned! {span=>
512
+ #events_enum_name::#ev_variant => {
513
+ #default_trans
514
+ }
515
+ },
516
+ Fields::Named(_) => unreachable!(),
517
+ }
518
+
519
+ } else {
520
+ unreachable!("It should be impossible to have more than one dest state in no-handler transitions")
521
+ }
522
+ }
523
+ })
524
+ // Since most states won't handle every possible event, return an error to that effect
525
+ .chain(std::iter::once(
526
+ quote! { _ => { return TransitionResult::InvalidTransition } },
527
+ ));
528
+ quote! {
529
+ #state_enum_name::#from(state_data) => match event {
530
+ #(#event_branches),*
531
+ }
532
+ }
533
+ }).collect();
534
+
535
+ let viz_str = self.visualize();
536
+
537
+ let trait_impl = quote! {
538
+ impl ::rustfsm::StateMachine for #name {
539
+ type Error = #err_type;
540
+ type State = #state_enum_name;
541
+ type SharedState = #shared_state_type;
542
+ type Event = #events_enum_name;
543
+ type Command = #cmd_type;
544
+
545
+ fn name(&self) -> &str {
546
+ #name_str
547
+ }
548
+
549
+ fn on_event(self, event: #events_enum_name)
550
+ -> ::rustfsm::TransitionResult<Self, Self::State> {
551
+ match self.state {
552
+ #(#state_branches),*
553
+ }
554
+ }
555
+
556
+ fn state(&self) -> &Self::State {
557
+ &self.state
558
+ }
559
+
560
+ fn set_state(&mut self, new: Self::State) {
561
+ self.state = new
562
+ }
563
+
564
+ fn shared_state(&self) -> &Self::SharedState{
565
+ &self.shared_state
566
+ }
567
+
568
+ fn has_reached_final_state(&self) -> bool {
569
+ self.state.is_final()
570
+ }
571
+
572
+ fn from_parts(shared: Self::SharedState, state: Self::State) -> Self {
573
+ Self { shared_state: shared, state }
574
+ }
575
+
576
+ fn visualizer() -> &'static str {
577
+ #viz_str
578
+ }
579
+ }
580
+ };
581
+
582
+ let output = quote! {
583
+ #transition_type_alias
584
+ #machine_struct
585
+ #states_enum
586
+ #(#multi_dest_enums)*
587
+ #states_enum_impl
588
+ #events_enum
589
+ #trait_impl
590
+ };
591
+
592
+ TokenStream::from(output)
593
+ }
594
+
595
+ fn all_states(&self) -> HashSet<Ident> {
596
+ self.transitions
597
+ .iter()
598
+ .flat_map(|t| {
599
+ let mut states = t.to.clone();
600
+ states.push(t.from.clone());
601
+ states
602
+ })
603
+ .collect()
604
+ }
605
+
606
+ fn visualize(&self) -> String {
607
+ let transitions: Vec<String> = self
608
+ .transitions
609
+ .iter()
610
+ .flat_map(|t| {
611
+ t.to.iter()
612
+ .map(move |d| format!("{} --> {}: {}", t.from, d, t.event.ident))
613
+ })
614
+ // Add all final state transitions
615
+ .chain(
616
+ self.all_states()
617
+ .iter()
618
+ .filter(|s| self.is_final_state(s))
619
+ .map(|s| format!("{} --> [*]", s)),
620
+ )
621
+ .collect();
622
+ let transitions = transitions.join("\n");
623
+ format!("@startuml\n{}\n@enduml", transitions)
624
+ }
625
+ }
626
+
627
+ /// Merge transition's dest state lists for those with the same from state & handler
628
+ fn merge_transition_dests(transitions: Vec<Transition>) -> Vec<Transition> {
629
+ let mut map = HashMap::<_, Transition>::new();
630
+ for t in transitions {
631
+ // We want to use the transition sans-destinations as the key
632
+ let without_dests = {
633
+ let mut wd = t.clone();
634
+ wd.to = vec![];
635
+ wd
636
+ };
637
+ match map.entry(without_dests) {
638
+ Entry::Occupied(mut e) => {
639
+ e.get_mut().to.extend(t.to.into_iter());
640
+ }
641
+ Entry::Vacant(v) => {
642
+ v.insert(t);
643
+ }
644
+ }
645
+ }
646
+ map.into_iter().map(|(_, v)| v).collect()
647
+ }
@@ -0,0 +1,8 @@
1
+ extern crate rustfsm_trait as rustfsm;
2
+
3
+ #[test]
4
+ fn tests() {
5
+ let t = trybuild::TestCases::new();
6
+ t.pass("tests/trybuild/*_pass.rs");
7
+ t.compile_fail("tests/trybuild/*_fail.rs");
8
+ }
@@ -0,0 +1,18 @@
1
+ extern crate rustfsm_trait as rustfsm;
2
+
3
+ use rustfsm_procmacro::fsm;
4
+
5
+ fsm! {
6
+ name SimpleMachine; command SimpleMachineCommand; error Infallible;
7
+
8
+ One --(A)--> Two;
9
+ One --(A)--> Two;
10
+ }
11
+
12
+ #[derive(Default, Clone)]
13
+ pub struct One {}
14
+
15
+ #[derive(Default, Clone)]
16
+ pub struct Two {}
17
+
18
+ fn main() {}
@@ -0,0 +1,12 @@
1
+ error: Duplicate transitions are not allowed!
2
+ --> $DIR/dupe_transitions_fail.rs:5:1
3
+ |
4
+ 5 | / fsm! {
5
+ 6 | | name SimpleMachine; command SimpleMachineCommand; error Infallible;
6
+ 7 | |
7
+ 8 | | One --(A)--> Two;
8
+ 9 | | One --(A)--> Two;
9
+ 10 | | }
10
+ | |_^
11
+ |
12
+ = note: this error originates in the macro `fsm` (in Nightly builds, run with -Z macro-backtrace for more info)