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,792 @@
1
+ #![warn(missing_docs)] // error if there are missing docs
2
+
3
+ //! This crate defines an alpha-stage Temporal Rust SDK.
4
+ //!
5
+ //! Currently defining activities and running an activity-only worker is the most stable code.
6
+ //! Workflow definitions exist and running a workflow worker works, but the API is still very
7
+ //! unstable.
8
+ //!
9
+ //! An example of running an activity worker:
10
+ //! ```no_run
11
+ //! use std::{str::FromStr, sync::Arc};
12
+ //! use temporal_sdk::{sdk_client_options, ActContext, Worker};
13
+ //! use temporal_sdk_core::{init_worker, telemetry_init, TelemetryOptionsBuilder, Url};
14
+ //! use temporal_sdk_core_api::worker::WorkerConfigBuilder;
15
+ //!
16
+ //! #[tokio::main]
17
+ //! async fn main() -> Result<(), Box<dyn std::error::Error>> {
18
+ //! let server_options = sdk_client_options(Url::from_str("http://localhost:7233")?).build()?;
19
+ //!
20
+ //! let client = server_options.connect("default", None, None).await?;
21
+ //!
22
+ //! let telemetry_options = TelemetryOptionsBuilder::default().build()?;
23
+ //! telemetry_init(&telemetry_options)?;
24
+ //!
25
+ //! let worker_config = WorkerConfigBuilder::default()
26
+ //! .namespace("default")
27
+ //! .task_queue("task_queue")
28
+ //! .build()?;
29
+ //!
30
+ //! let core_worker = init_worker(worker_config, client);
31
+ //!
32
+ //! let mut worker = Worker::new_from_core(Arc::new(core_worker), "task_queue");
33
+ //! worker.register_activity(
34
+ //! "echo_activity",
35
+ //! |_ctx: ActContext, echo_me: String| async move { Ok(echo_me) },
36
+ //! );
37
+ //!
38
+ //! worker.run().await?;
39
+ //!
40
+ //! Ok(())
41
+ //! }
42
+ //! ```
43
+
44
+ #[macro_use]
45
+ extern crate tracing;
46
+
47
+ mod activity_context;
48
+ mod app_data;
49
+ mod conversions;
50
+ pub mod interceptors;
51
+ mod payload_converter;
52
+ mod workflow_context;
53
+ mod workflow_future;
54
+
55
+ pub use activity_context::ActContext;
56
+ pub use temporal_client::Namespace;
57
+ pub use workflow_context::{
58
+ ActivityOptions, CancellableFuture, ChildWorkflow, ChildWorkflowOptions, LocalActivityOptions,
59
+ Signal, SignalData, SignalWorkflowOptions, WfContext,
60
+ };
61
+
62
+ use crate::{
63
+ interceptors::WorkerInterceptor,
64
+ workflow_context::{ChildWfCommon, PendingChildWorkflow},
65
+ };
66
+ use anyhow::{anyhow, bail, Context};
67
+ use app_data::AppData;
68
+ use futures::{future::BoxFuture, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
69
+ use std::{
70
+ cell::RefCell,
71
+ collections::HashMap,
72
+ fmt::{Debug, Display, Formatter},
73
+ future::Future,
74
+ sync::Arc,
75
+ };
76
+ use temporal_client::ClientOptionsBuilder;
77
+ use temporal_sdk_core::Url;
78
+ use temporal_sdk_core_api::{
79
+ errors::{PollActivityError, PollWfError},
80
+ Worker as CoreWorker,
81
+ };
82
+ use temporal_sdk_core_protos::{
83
+ coresdk::{
84
+ activity_result::{ActivityExecutionResult, ActivityResolution},
85
+ activity_task::{activity_task, ActivityTask},
86
+ child_workflow::ChildWorkflowResult,
87
+ common::NamespacedWorkflowExecution,
88
+ workflow_activation::{
89
+ resolve_child_workflow_execution_start::Status as ChildWorkflowStartStatus,
90
+ workflow_activation_job::Variant, WorkflowActivation, WorkflowActivationJob,
91
+ },
92
+ workflow_commands::{workflow_command, ContinueAsNewWorkflowExecution},
93
+ workflow_completion::WorkflowActivationCompletion,
94
+ ActivityTaskCompletion, AsJsonPayloadExt, FromJsonPayloadExt,
95
+ },
96
+ temporal::api::{common::v1::Payload, failure::v1::Failure},
97
+ TaskToken,
98
+ };
99
+ use tokio::{
100
+ sync::{
101
+ mpsc::{unbounded_channel, UnboundedSender},
102
+ oneshot,
103
+ },
104
+ task::JoinError,
105
+ };
106
+ use tokio_stream::wrappers::UnboundedReceiverStream;
107
+ use tokio_util::sync::CancellationToken;
108
+
109
+ const VERSION: &str = env!("CARGO_PKG_VERSION");
110
+
111
+ /// Returns a [ClientOptionsBuilder] with required fields set to appropriate values
112
+ /// for the Rust SDK.
113
+ pub fn sdk_client_options(url: impl Into<Url>) -> ClientOptionsBuilder {
114
+ let mut builder = ClientOptionsBuilder::default();
115
+ builder
116
+ .target_url(url)
117
+ .client_name("rust-sdk".to_string())
118
+ .client_version(VERSION.to_string());
119
+
120
+ builder
121
+ }
122
+
123
+ /// A worker that can poll for and respond to workflow tasks by using [WorkflowFunction]s,
124
+ /// and activity tasks by using [ActivityFunction]s
125
+ pub struct Worker {
126
+ common: CommonWorker,
127
+ workflow_half: WorkflowHalf,
128
+ activity_half: ActivityHalf,
129
+ app_data: Option<AppData>,
130
+ }
131
+
132
+ struct CommonWorker {
133
+ worker: Arc<dyn CoreWorker>,
134
+ task_queue: String,
135
+ worker_interceptor: Option<Box<dyn WorkerInterceptor>>,
136
+ }
137
+
138
+ struct WorkflowHalf {
139
+ /// Maps run id to cached workflow state
140
+ workflows: RefCell<HashMap<String, WorkflowData>>,
141
+ /// Maps workflow type to the function for executing workflow runs with that ID
142
+ workflow_fns: RefCell<HashMap<String, WorkflowFunction>>,
143
+ }
144
+ struct WorkflowData {
145
+ /// Channel used to send the workflow activations
146
+ activation_chan: UnboundedSender<WorkflowActivation>,
147
+ }
148
+
149
+ struct WorkflowFutureHandle<F: Future<Output = Result<WorkflowResult<()>, JoinError>>> {
150
+ join_handle: F,
151
+ run_id: String,
152
+ }
153
+
154
+ struct ActivityHalf {
155
+ /// Maps activity type to the function for executing activities of that type
156
+ activity_fns: HashMap<String, ActivityFunction>,
157
+ task_tokens_to_cancels: HashMap<TaskToken, CancellationToken>,
158
+ }
159
+
160
+ impl Worker {
161
+ /// Create a new Rust SDK worker from a core worker
162
+ pub fn new_from_core(worker: Arc<dyn CoreWorker>, task_queue: impl Into<String>) -> Self {
163
+ Self {
164
+ common: CommonWorker {
165
+ worker,
166
+ task_queue: task_queue.into(),
167
+ worker_interceptor: None,
168
+ },
169
+ workflow_half: WorkflowHalf {
170
+ workflows: Default::default(),
171
+ workflow_fns: Default::default(),
172
+ },
173
+ activity_half: ActivityHalf {
174
+ activity_fns: Default::default(),
175
+ task_tokens_to_cancels: Default::default(),
176
+ },
177
+ app_data: Some(Default::default()),
178
+ }
179
+ }
180
+
181
+ /// Returns the task queue name this worker polls on
182
+ pub fn task_queue(&self) -> &str {
183
+ &self.common.task_queue
184
+ }
185
+
186
+ /// Return a handle that can be used to initiate shutdown.
187
+ /// TODO: Doc better after shutdown changes
188
+ pub fn shutdown_handle(&self) -> impl Fn() {
189
+ let w = self.common.worker.clone();
190
+ move || w.initiate_shutdown()
191
+ }
192
+
193
+ /// Register a Workflow function to invoke when the Worker is asked to run a workflow of
194
+ /// `workflow_type`
195
+ pub fn register_wf<F: Into<WorkflowFunction>>(
196
+ &mut self,
197
+ workflow_type: impl Into<String>,
198
+ wf_function: F,
199
+ ) {
200
+ self.workflow_half
201
+ .workflow_fns
202
+ .get_mut()
203
+ .insert(workflow_type.into(), wf_function.into());
204
+ }
205
+
206
+ /// Register an Activity function to invoke when the Worker is asked to run an activity of
207
+ /// `activity_type`
208
+ pub fn register_activity<A, R, O>(
209
+ &mut self,
210
+ activity_type: impl Into<String>,
211
+ act_function: impl IntoActivityFunc<A, R, O>,
212
+ ) {
213
+ self.activity_half.activity_fns.insert(
214
+ activity_type.into(),
215
+ ActivityFunction {
216
+ act_func: act_function.into_activity_fn(),
217
+ },
218
+ );
219
+ }
220
+
221
+ /// Insert Custom App Context for Workflows and Activities
222
+ pub fn insert_app_data<T: Send + Sync + 'static>(&mut self, data: T) {
223
+ self.app_data.as_mut().map(|a| a.insert(data));
224
+ }
225
+
226
+ /// Runs the worker. Eventually resolves after the worker has been explicitly shut down,
227
+ /// or may return early with an error in the event of some unresolvable problem.
228
+ pub async fn run(&mut self) -> Result<(), anyhow::Error> {
229
+ let shutdown_token = CancellationToken::new();
230
+ let (common, wf_half, act_half, app_data) = self.split_apart();
231
+ let safe_app_data = Arc::new(
232
+ app_data
233
+ .take()
234
+ .ok_or_else(|| anyhow!("app_data should exist on run"))?,
235
+ );
236
+ let (wf_future_tx, wf_future_rx) = unbounded_channel();
237
+ let (completions_tx, completions_rx) = unbounded_channel();
238
+ let wf_future_joiner = async {
239
+ UnboundedReceiverStream::new(wf_future_rx)
240
+ .map(Result::<_, anyhow::Error>::Ok)
241
+ .try_for_each_concurrent(
242
+ None,
243
+ |WorkflowFutureHandle {
244
+ join_handle,
245
+ run_id,
246
+ }| {
247
+ let wf_half = &*wf_half;
248
+ async move {
249
+ join_handle.await??;
250
+ info!(run_id=%run_id, "Removing workflow from cache");
251
+ wf_half.workflows.borrow_mut().remove(&run_id);
252
+ Ok(())
253
+ }
254
+ },
255
+ )
256
+ .await
257
+ .context("Workflow futures encountered an error")
258
+ };
259
+ let wf_completion_processor = async {
260
+ UnboundedReceiverStream::new(completions_rx)
261
+ .map(Ok)
262
+ .try_for_each_concurrent(None, |completion| async {
263
+ if let Some(ref i) = common.worker_interceptor {
264
+ i.on_workflow_activation_completion(&completion).await;
265
+ }
266
+ common.worker.complete_workflow_activation(completion).await
267
+ })
268
+ .map_err(anyhow::Error::from)
269
+ .await
270
+ .context("Workflow completions processor encountered an error")
271
+ };
272
+ tokio::try_join!(
273
+ // Workflow polling loop
274
+ async {
275
+ loop {
276
+ let activation = match common.worker.poll_workflow_activation().await {
277
+ Err(PollWfError::ShutDown) => {
278
+ break;
279
+ }
280
+ o => o?,
281
+ };
282
+ if let Some(wf_fut) = wf_half.workflow_activation_handler(
283
+ common,
284
+ shutdown_token.clone(),
285
+ activation,
286
+ &completions_tx,
287
+ )? {
288
+ if wf_future_tx.send(wf_fut).is_err() {
289
+ panic!(
290
+ "Receive half of completion processor channel cannot be dropped"
291
+ );
292
+ }
293
+ }
294
+ }
295
+ // Tell still-alive workflows to evict themselves
296
+ shutdown_token.cancel();
297
+ // It's important to drop these so the future and completion processors will
298
+ // terminate.
299
+ drop(wf_future_tx);
300
+ drop(completions_tx);
301
+ Result::<_, anyhow::Error>::Ok(())
302
+ },
303
+ // Only poll on the activity queue if activity functions have been registered. This
304
+ // makes tests which use mocks dramatically more manageable.
305
+ async {
306
+ if !act_half.activity_fns.is_empty() {
307
+ let shutdown_token = shutdown_token.clone();
308
+ loop {
309
+ tokio::select! {
310
+ activity = common.worker.poll_activity_task() => {
311
+ if matches!(activity, Err(PollActivityError::ShutDown)) {
312
+ break;
313
+ }
314
+ act_half.activity_task_handler(
315
+ common.worker.clone(),
316
+ safe_app_data.clone(),
317
+ common.task_queue.clone(),
318
+ activity?
319
+ )?;
320
+ },
321
+ _ = shutdown_token.cancelled() => { break }
322
+ }
323
+ }
324
+ };
325
+ Result::<_, anyhow::Error>::Ok(())
326
+ },
327
+ wf_future_joiner,
328
+ wf_completion_processor,
329
+ )?;
330
+
331
+ info!("Polling loops exited");
332
+ if let Some(i) = self.common.worker_interceptor.as_ref() {
333
+ i.on_shutdown(self);
334
+ }
335
+ self.common.worker.shutdown().await;
336
+ self.app_data = Some(
337
+ Arc::try_unwrap(safe_app_data)
338
+ .map_err(|_| anyhow!("some references of AppData exist on worker shutdown"))?,
339
+ );
340
+ Ok(())
341
+ }
342
+
343
+ /// Set a [WorkerInterceptor]
344
+ pub fn set_worker_interceptor(&mut self, interceptor: Box<dyn WorkerInterceptor>) {
345
+ self.common.worker_interceptor = Some(interceptor);
346
+ }
347
+
348
+ /// Turns this rust worker into a new worker with all the same workflows and activities
349
+ /// registered, but with a new underlying core worker. Can be used to swap the worker for
350
+ /// a replay worker, change task queues, etc.
351
+ pub fn with_new_core_worker(&mut self, new_core_worker: Arc<dyn CoreWorker>) {
352
+ self.common.worker = new_core_worker;
353
+ }
354
+
355
+ /// Returns number of currently cached workflows as understood by the SDK. Importantly, this
356
+ /// is not the same as understood by core, though they *should* always be in sync.
357
+ pub fn cached_workflows(&self) -> usize {
358
+ self.workflow_half.workflows.borrow().len()
359
+ }
360
+
361
+ fn split_apart(
362
+ &mut self,
363
+ ) -> (
364
+ &mut CommonWorker,
365
+ &mut WorkflowHalf,
366
+ &mut ActivityHalf,
367
+ &mut Option<AppData>,
368
+ ) {
369
+ (
370
+ &mut self.common,
371
+ &mut self.workflow_half,
372
+ &mut self.activity_half,
373
+ &mut self.app_data,
374
+ )
375
+ }
376
+ }
377
+
378
+ impl WorkflowHalf {
379
+ fn workflow_activation_handler(
380
+ &self,
381
+ common: &CommonWorker,
382
+ shutdown_token: CancellationToken,
383
+ activation: WorkflowActivation,
384
+ completions_tx: &UnboundedSender<WorkflowActivationCompletion>,
385
+ ) -> Result<
386
+ Option<WorkflowFutureHandle<impl Future<Output = Result<WorkflowResult<()>, JoinError>>>>,
387
+ anyhow::Error,
388
+ > {
389
+ let mut res = None;
390
+ let run_id = activation.run_id.clone();
391
+
392
+ // If the activation is to start a workflow, create a new workflow driver for it,
393
+ // using the function associated with that workflow id
394
+ if let Some(WorkflowActivationJob {
395
+ variant: Some(Variant::StartWorkflow(sw)),
396
+ }) = activation.jobs.get(0)
397
+ {
398
+ let workflow_type = &sw.workflow_type;
399
+ let wf_fns_borrow = self.workflow_fns.borrow();
400
+ let wf_function = wf_fns_borrow
401
+ .get(workflow_type)
402
+ .ok_or_else(|| anyhow!("Workflow type {workflow_type} not found"))?;
403
+
404
+ let (wff, activations) = wf_function.start_workflow(
405
+ common.worker.get_config().namespace.clone(),
406
+ common.task_queue.clone(),
407
+ // NOTE: Don't clone args if this gets ported to be a non-test rust worker
408
+ sw.arguments.clone(),
409
+ completions_tx.clone(),
410
+ );
411
+ let jh = tokio::spawn(async move {
412
+ tokio::select! {
413
+ r = wff => r,
414
+ // TODO: This probably shouldn't abort early, as it could cause an in-progress
415
+ // complete to abort. Send synthetic remove activation
416
+ _ = shutdown_token.cancelled() => {
417
+ Ok(WfExitValue::Evicted)
418
+ }
419
+ }
420
+ });
421
+ res = Some(WorkflowFutureHandle {
422
+ join_handle: jh,
423
+ run_id: run_id.clone(),
424
+ });
425
+ self.workflows.borrow_mut().insert(
426
+ run_id.clone(),
427
+ WorkflowData {
428
+ activation_chan: activations,
429
+ },
430
+ );
431
+ }
432
+
433
+ // The activation is expected to apply to some workflow we know about. Use it to
434
+ // unblock things and advance the workflow.
435
+ if let Some(dat) = self.workflows.borrow_mut().get_mut(&run_id) {
436
+ dat.activation_chan
437
+ .send(activation)
438
+ .expect("Workflow should exist if we're sending it an activation");
439
+ } else {
440
+ bail!(
441
+ "Got activation {:?} for unknown workflow {}",
442
+ activation,
443
+ run_id
444
+ );
445
+ };
446
+
447
+ Ok(res)
448
+ }
449
+ }
450
+
451
+ impl ActivityHalf {
452
+ /// Spawns off a task to handle the provided activity task
453
+ fn activity_task_handler(
454
+ &mut self,
455
+ worker: Arc<dyn CoreWorker>,
456
+ app_data: Arc<AppData>,
457
+ task_queue: String,
458
+ activity: ActivityTask,
459
+ ) -> Result<(), anyhow::Error> {
460
+ match activity.variant {
461
+ Some(activity_task::Variant::Start(start)) => {
462
+ let act_fn = self
463
+ .activity_fns
464
+ .get(&start.activity_type)
465
+ .ok_or_else(|| {
466
+ anyhow!(
467
+ "No function registered for activity type {}",
468
+ start.activity_type
469
+ )
470
+ })?
471
+ .clone();
472
+ let ct = CancellationToken::new();
473
+ let task_token = activity.task_token;
474
+ self.task_tokens_to_cancels
475
+ .insert(task_token.clone().into(), ct.clone());
476
+
477
+ let (ctx, arg) = ActContext::new(
478
+ worker.clone(),
479
+ app_data,
480
+ ct,
481
+ task_queue,
482
+ task_token.clone(),
483
+ start,
484
+ );
485
+ tokio::spawn(async move {
486
+ let output = (act_fn.act_func)(ctx, arg).await;
487
+ let result = match output {
488
+ Ok(ActExitValue::Normal(p)) => ActivityExecutionResult::ok(p),
489
+ Ok(ActExitValue::WillCompleteAsync) => {
490
+ ActivityExecutionResult::will_complete_async()
491
+ }
492
+ Err(err) => match err.downcast::<ActivityCancelledError>() {
493
+ Ok(ce) => ActivityExecutionResult::cancel_from_details(ce.details),
494
+ Err(other_err) => ActivityExecutionResult::fail(other_err.into()),
495
+ },
496
+ };
497
+ worker
498
+ .complete_activity_task(ActivityTaskCompletion {
499
+ task_token,
500
+ result: Some(result),
501
+ })
502
+ .await?;
503
+ Ok::<_, anyhow::Error>(())
504
+ });
505
+ }
506
+ Some(activity_task::Variant::Cancel(_)) => {
507
+ if let Some(ct) = self.task_tokens_to_cancels.get(&activity.task_token.into()) {
508
+ ct.cancel();
509
+ }
510
+ }
511
+ None => bail!("Undefined activity task variant"),
512
+ }
513
+ Ok(())
514
+ }
515
+ }
516
+
517
+ #[derive(Debug)]
518
+ enum UnblockEvent {
519
+ Timer(u32, TimerResult),
520
+ Activity(u32, Box<ActivityResolution>),
521
+ WorkflowStart(u32, Box<ChildWorkflowStartStatus>),
522
+ WorkflowComplete(u32, Box<ChildWorkflowResult>),
523
+ SignalExternal(u32, Option<Failure>),
524
+ CancelExternal(u32, Option<Failure>),
525
+ }
526
+
527
+ /// Result of awaiting on a timer
528
+ #[derive(Debug, Copy, Clone)]
529
+ pub enum TimerResult {
530
+ /// The timer was cancelled
531
+ Cancelled,
532
+ /// The timer elapsed and fired
533
+ Fired,
534
+ }
535
+
536
+ /// Successful result of sending a signal to an external workflow
537
+ pub struct SignalExternalOk;
538
+ /// Result of awaiting on sending a signal to an external workflow
539
+ pub type SignalExternalWfResult = Result<SignalExternalOk, Failure>;
540
+
541
+ /// Successful result of sending a cancel request to an external workflow
542
+ pub struct CancelExternalOk;
543
+ /// Result of awaiting on sending a cancel request to an external workflow
544
+ pub type CancelExternalWfResult = Result<CancelExternalOk, Failure>;
545
+
546
+ trait Unblockable {
547
+ type OtherDat;
548
+
549
+ fn unblock(ue: UnblockEvent, od: Self::OtherDat) -> Self;
550
+ }
551
+
552
+ impl Unblockable for TimerResult {
553
+ type OtherDat = ();
554
+ fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
555
+ match ue {
556
+ UnblockEvent::Timer(_, result) => result,
557
+ _ => panic!("Invalid unblock event for timer"),
558
+ }
559
+ }
560
+ }
561
+
562
+ impl Unblockable for ActivityResolution {
563
+ type OtherDat = ();
564
+ fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
565
+ match ue {
566
+ UnblockEvent::Activity(_, result) => *result,
567
+ _ => panic!("Invalid unblock event for activity"),
568
+ }
569
+ }
570
+ }
571
+
572
+ impl Unblockable for PendingChildWorkflow {
573
+ // Other data here is workflow id
574
+ type OtherDat = ChildWfCommon;
575
+ fn unblock(ue: UnblockEvent, od: Self::OtherDat) -> Self {
576
+ match ue {
577
+ UnblockEvent::WorkflowStart(_, result) => Self {
578
+ status: *result,
579
+ common: od,
580
+ },
581
+ _ => panic!("Invalid unblock event for child workflow start"),
582
+ }
583
+ }
584
+ }
585
+
586
+ impl Unblockable for ChildWorkflowResult {
587
+ type OtherDat = ();
588
+ fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
589
+ match ue {
590
+ UnblockEvent::WorkflowComplete(_, result) => *result,
591
+ _ => panic!("Invalid unblock event for child workflow complete"),
592
+ }
593
+ }
594
+ }
595
+
596
+ impl Unblockable for SignalExternalWfResult {
597
+ type OtherDat = ();
598
+ fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
599
+ match ue {
600
+ UnblockEvent::SignalExternal(_, maybefail) => {
601
+ maybefail.map_or(Ok(SignalExternalOk), Err)
602
+ }
603
+ _ => panic!("Invalid unblock event for signal external workflow result"),
604
+ }
605
+ }
606
+ }
607
+
608
+ impl Unblockable for CancelExternalWfResult {
609
+ type OtherDat = ();
610
+ fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
611
+ match ue {
612
+ UnblockEvent::CancelExternal(_, maybefail) => {
613
+ maybefail.map_or(Ok(CancelExternalOk), Err)
614
+ }
615
+ _ => panic!("Invalid unblock event for signal external workflow result"),
616
+ }
617
+ }
618
+ }
619
+
620
+ /// Identifier for cancellable operations
621
+ #[derive(Debug, Clone)]
622
+ pub enum CancellableID {
623
+ /// Timer sequence number
624
+ Timer(u32),
625
+ /// Activity sequence number
626
+ Activity(u32),
627
+ /// Activity sequence number
628
+ LocalActivity(u32),
629
+ /// Start child sequence number
630
+ ChildWorkflow(u32),
631
+ /// Signal workflow
632
+ SignalExternalWorkflow(u32),
633
+ /// An external workflow identifier as may have been created by a started child workflow
634
+ ExternalWorkflow {
635
+ /// Sequence number which will be used for the cancel command
636
+ seqnum: u32,
637
+ /// Identifying information about the workflow to be cancelled
638
+ execution: NamespacedWorkflowExecution,
639
+ /// Set to true if this workflow is a child of the issuing workflow
640
+ only_child: bool,
641
+ },
642
+ }
643
+
644
+ #[derive(derive_more::From)]
645
+ #[allow(clippy::large_enum_variant)]
646
+ enum RustWfCmd {
647
+ #[from(ignore)]
648
+ Cancel(CancellableID),
649
+ ForceWFTFailure(anyhow::Error),
650
+ NewCmd(CommandCreateRequest),
651
+ NewNonblockingCmd(workflow_command::Variant),
652
+ SubscribeChildWorkflowCompletion(CommandSubscribeChildWorkflowCompletion),
653
+ SubscribeSignal(String, UnboundedSender<SignalData>),
654
+ }
655
+
656
+ struct CommandCreateRequest {
657
+ cmd: workflow_command::Variant,
658
+ unblocker: oneshot::Sender<UnblockEvent>,
659
+ }
660
+
661
+ struct CommandSubscribeChildWorkflowCompletion {
662
+ seq: u32,
663
+ unblocker: oneshot::Sender<UnblockEvent>,
664
+ }
665
+
666
+ type WfFunc = dyn Fn(WfContext) -> BoxFuture<'static, WorkflowResult<()>> + Send + Sync + 'static;
667
+
668
+ /// The user's async function / workflow code
669
+ pub struct WorkflowFunction {
670
+ wf_func: Box<WfFunc>,
671
+ }
672
+
673
+ impl<F, Fut> From<F> for WorkflowFunction
674
+ where
675
+ F: Fn(WfContext) -> Fut + Send + Sync + 'static,
676
+ Fut: Future<Output = WorkflowResult<()>> + Send + 'static,
677
+ {
678
+ fn from(wf_func: F) -> Self {
679
+ Self::new(wf_func)
680
+ }
681
+ }
682
+
683
+ impl WorkflowFunction {
684
+ /// Build a workflow function from a closure or function pointer which accepts a [WfContext]
685
+ pub fn new<F, Fut>(wf_func: F) -> Self
686
+ where
687
+ F: Fn(WfContext) -> Fut + Send + Sync + 'static,
688
+ Fut: Future<Output = WorkflowResult<()>> + Send + 'static,
689
+ {
690
+ Self {
691
+ wf_func: Box::new(move |ctx: WfContext| wf_func(ctx).boxed()),
692
+ }
693
+ }
694
+ }
695
+
696
+ /// The result of running a workflow
697
+ pub type WorkflowResult<T> = Result<WfExitValue<T>, anyhow::Error>;
698
+
699
+ /// Workflow functions may return these values when exiting
700
+ #[derive(Debug, derive_more::From)]
701
+ pub enum WfExitValue<T: Debug> {
702
+ /// Continue the workflow as a new execution
703
+ #[from(ignore)]
704
+ ContinueAsNew(Box<ContinueAsNewWorkflowExecution>),
705
+ /// Confirm the workflow was cancelled (can be automatic in a more advanced iteration)
706
+ #[from(ignore)]
707
+ Cancelled,
708
+ /// The run was evicted
709
+ #[from(ignore)]
710
+ Evicted,
711
+ /// Finish with a result
712
+ Normal(T),
713
+ }
714
+
715
+ impl<T: Debug> WfExitValue<T> {
716
+ /// Construct a [WfExitValue::ContinueAsNew] variant (handles boxing)
717
+ pub fn continue_as_new(can: ContinueAsNewWorkflowExecution) -> Self {
718
+ Self::ContinueAsNew(Box::new(can))
719
+ }
720
+ }
721
+
722
+ /// Activity functions may return these values when exiting
723
+ #[derive(derive_more::From)]
724
+ pub enum ActExitValue<T: Debug> {
725
+ /// Completion requires an asynchronous callback
726
+ #[from(ignore)]
727
+ WillCompleteAsync,
728
+ /// Finish with a result
729
+ Normal(T),
730
+ }
731
+
732
+ type BoxActFn = Arc<
733
+ dyn Fn(ActContext, Payload) -> BoxFuture<'static, Result<ActExitValue<Payload>, anyhow::Error>>
734
+ + Send
735
+ + Sync,
736
+ >;
737
+
738
+ /// Container for user-defined activity functions
739
+ #[derive(Clone)]
740
+ pub struct ActivityFunction {
741
+ act_func: BoxActFn,
742
+ }
743
+
744
+ /// Return this error to indicate your activity is cancelling
745
+ #[derive(Debug, Default)]
746
+ pub struct ActivityCancelledError {
747
+ details: Option<Payload>,
748
+ }
749
+ impl std::error::Error for ActivityCancelledError {}
750
+ impl Display for ActivityCancelledError {
751
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
752
+ write!(f, "Activity cancelled")
753
+ }
754
+ }
755
+
756
+ /// Closures / functions which can be turned into activity functions implement this trait
757
+ pub trait IntoActivityFunc<Args, Res, Out> {
758
+ /// Consume the closure or fn pointer and turned it into a boxed activity function
759
+ fn into_activity_fn(self) -> BoxActFn;
760
+ }
761
+
762
+ impl<A, Rf, R, O, F> IntoActivityFunc<A, Rf, O> for F
763
+ where
764
+ F: (Fn(ActContext, A) -> Rf) + Sync + Send + 'static,
765
+ A: FromJsonPayloadExt + Send,
766
+ Rf: Future<Output = Result<R, anyhow::Error>> + Send + 'static,
767
+ R: Into<ActExitValue<O>>,
768
+ O: AsJsonPayloadExt + Debug,
769
+ {
770
+ fn into_activity_fn(self) -> BoxActFn {
771
+ let wrapper = move |ctx: ActContext, input: Payload| {
772
+ // Some minor gymnastics are required to avoid needing to clone the function
773
+ match A::from_json_payload(&input) {
774
+ Ok(deser) => (self)(ctx, deser)
775
+ .map(|r| {
776
+ r.and_then(|r| {
777
+ let exit_val: ActExitValue<O> = r.into();
778
+ Ok(match exit_val {
779
+ ActExitValue::WillCompleteAsync => ActExitValue::WillCompleteAsync,
780
+ ActExitValue::Normal(x) => {
781
+ ActExitValue::Normal(x.as_json_payload()?)
782
+ }
783
+ })
784
+ })
785
+ })
786
+ .boxed(),
787
+ Err(e) => async move { Err(e.into()) }.boxed(),
788
+ }
789
+ };
790
+ Arc::new(wrapper)
791
+ }
792
+ }