temporalio 0.0.0 → 0.0.2

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 (327) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +301 -0
  3. data/bridge/Cargo.lock +2888 -0
  4. data/bridge/Cargo.toml +27 -0
  5. data/bridge/sdk-core/ARCHITECTURE.md +76 -0
  6. data/bridge/sdk-core/Cargo.lock +2606 -0
  7. data/bridge/sdk-core/Cargo.toml +2 -0
  8. data/bridge/sdk-core/LICENSE.txt +23 -0
  9. data/bridge/sdk-core/README.md +104 -0
  10. data/bridge/sdk-core/arch_docs/diagrams/README.md +10 -0
  11. data/bridge/sdk-core/arch_docs/diagrams/sticky_queues.puml +40 -0
  12. data/bridge/sdk-core/arch_docs/diagrams/workflow_internals.svg +1 -0
  13. data/bridge/sdk-core/arch_docs/sticky_queues.md +51 -0
  14. data/bridge/sdk-core/client/Cargo.toml +40 -0
  15. data/bridge/sdk-core/client/LICENSE.txt +23 -0
  16. data/bridge/sdk-core/client/src/lib.rs +1286 -0
  17. data/bridge/sdk-core/client/src/metrics.rs +165 -0
  18. data/bridge/sdk-core/client/src/raw.rs +932 -0
  19. data/bridge/sdk-core/client/src/retry.rs +751 -0
  20. data/bridge/sdk-core/client/src/workflow_handle/mod.rs +185 -0
  21. data/bridge/sdk-core/core/Cargo.toml +116 -0
  22. data/bridge/sdk-core/core/LICENSE.txt +23 -0
  23. data/bridge/sdk-core/core/benches/workflow_replay.rs +76 -0
  24. data/bridge/sdk-core/core/src/abstractions.rs +166 -0
  25. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +1014 -0
  26. data/bridge/sdk-core/core/src/core_tests/child_workflows.rs +221 -0
  27. data/bridge/sdk-core/core/src/core_tests/determinism.rs +107 -0
  28. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +925 -0
  29. data/bridge/sdk-core/core/src/core_tests/mod.rs +100 -0
  30. data/bridge/sdk-core/core/src/core_tests/queries.rs +894 -0
  31. data/bridge/sdk-core/core/src/core_tests/replay_flag.rs +65 -0
  32. data/bridge/sdk-core/core/src/core_tests/workers.rs +259 -0
  33. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +124 -0
  34. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +2090 -0
  35. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +515 -0
  36. data/bridge/sdk-core/core/src/lib.rs +282 -0
  37. data/bridge/sdk-core/core/src/pollers/mod.rs +54 -0
  38. data/bridge/sdk-core/core/src/pollers/poll_buffer.rs +297 -0
  39. data/bridge/sdk-core/core/src/protosext/mod.rs +428 -0
  40. data/bridge/sdk-core/core/src/replay/mod.rs +215 -0
  41. data/bridge/sdk-core/core/src/retry_logic.rs +202 -0
  42. data/bridge/sdk-core/core/src/telemetry/log_export.rs +190 -0
  43. data/bridge/sdk-core/core/src/telemetry/metrics.rs +428 -0
  44. data/bridge/sdk-core/core/src/telemetry/mod.rs +407 -0
  45. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +78 -0
  46. data/bridge/sdk-core/core/src/test_help/mod.rs +889 -0
  47. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +580 -0
  48. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +1048 -0
  49. data/bridge/sdk-core/core/src/worker/activities.rs +481 -0
  50. data/bridge/sdk-core/core/src/worker/client/mocks.rs +87 -0
  51. data/bridge/sdk-core/core/src/worker/client.rs +373 -0
  52. data/bridge/sdk-core/core/src/worker/mod.rs +570 -0
  53. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +37 -0
  54. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +101 -0
  55. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +532 -0
  56. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +907 -0
  57. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +294 -0
  58. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +167 -0
  59. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +858 -0
  60. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +136 -0
  61. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +157 -0
  62. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +129 -0
  63. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +1450 -0
  64. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +316 -0
  65. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +178 -0
  66. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +708 -0
  67. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +439 -0
  68. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +435 -0
  69. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +175 -0
  70. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +242 -0
  71. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +96 -0
  72. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +1200 -0
  73. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +272 -0
  74. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +198 -0
  75. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +655 -0
  76. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +1200 -0
  77. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +145 -0
  78. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +88 -0
  79. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +985 -0
  80. data/bridge/sdk-core/core-api/Cargo.toml +32 -0
  81. data/bridge/sdk-core/core-api/LICENSE.txt +23 -0
  82. data/bridge/sdk-core/core-api/src/errors.rs +95 -0
  83. data/bridge/sdk-core/core-api/src/lib.rs +109 -0
  84. data/bridge/sdk-core/core-api/src/telemetry.rs +147 -0
  85. data/bridge/sdk-core/core-api/src/worker.rs +148 -0
  86. data/bridge/sdk-core/etc/deps.svg +162 -0
  87. data/bridge/sdk-core/etc/dynamic-config.yaml +2 -0
  88. data/bridge/sdk-core/etc/otel-collector-config.yaml +36 -0
  89. data/bridge/sdk-core/etc/prometheus.yaml +6 -0
  90. data/bridge/sdk-core/etc/regen-depgraph.sh +5 -0
  91. data/bridge/sdk-core/fsm/Cargo.toml +18 -0
  92. data/bridge/sdk-core/fsm/LICENSE.txt +23 -0
  93. data/bridge/sdk-core/fsm/README.md +3 -0
  94. data/bridge/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +27 -0
  95. data/bridge/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +23 -0
  96. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +647 -0
  97. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +8 -0
  98. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.rs +18 -0
  99. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +12 -0
  100. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dynamic_dest_pass.rs +41 -0
  101. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.rs +14 -0
  102. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.stderr +11 -0
  103. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_arg_pass.rs +32 -0
  104. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_pass.rs +31 -0
  105. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/medium_complex_pass.rs +46 -0
  106. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.rs +29 -0
  107. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +12 -0
  108. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/simple_pass.rs +32 -0
  109. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.rs +18 -0
  110. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +5 -0
  111. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.rs +11 -0
  112. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +5 -0
  113. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.rs +11 -0
  114. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +5 -0
  115. data/bridge/sdk-core/fsm/rustfsm_trait/Cargo.toml +14 -0
  116. data/bridge/sdk-core/fsm/rustfsm_trait/LICENSE.txt +23 -0
  117. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +249 -0
  118. data/bridge/sdk-core/fsm/src/lib.rs +2 -0
  119. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  120. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  121. data/bridge/sdk-core/histories/fail_wf_task.bin +0 -0
  122. data/bridge/sdk-core/histories/timer_workflow_history.bin +0 -0
  123. data/bridge/sdk-core/integ-with-otel.sh +7 -0
  124. data/bridge/sdk-core/protos/api_upstream/README.md +9 -0
  125. data/bridge/sdk-core/protos/api_upstream/api-linter.yaml +40 -0
  126. data/bridge/sdk-core/protos/api_upstream/buf.yaml +9 -0
  127. data/bridge/sdk-core/protos/api_upstream/build/go.mod +7 -0
  128. data/bridge/sdk-core/protos/api_upstream/build/go.sum +5 -0
  129. data/bridge/sdk-core/protos/api_upstream/build/tools.go +29 -0
  130. data/bridge/sdk-core/protos/api_upstream/dependencies/gogoproto/gogo.proto +141 -0
  131. data/bridge/sdk-core/protos/api_upstream/go.mod +6 -0
  132. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +89 -0
  133. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +260 -0
  134. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +112 -0
  135. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +47 -0
  136. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +57 -0
  137. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +56 -0
  138. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +170 -0
  139. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +118 -0
  140. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/interaction_type.proto +39 -0
  141. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +51 -0
  142. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +50 -0
  143. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +41 -0
  144. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +60 -0
  145. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +59 -0
  146. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +40 -0
  147. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +122 -0
  148. data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +108 -0
  149. data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +114 -0
  150. data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +56 -0
  151. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +758 -0
  152. data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +87 -0
  153. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +97 -0
  154. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +121 -0
  155. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +80 -0
  156. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +61 -0
  157. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +55 -0
  158. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +379 -0
  159. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +108 -0
  160. data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +59 -0
  161. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +146 -0
  162. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +1168 -0
  163. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +415 -0
  164. data/bridge/sdk-core/protos/grpc/health/v1/health.proto +63 -0
  165. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
  166. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +79 -0
  167. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +77 -0
  168. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +15 -0
  169. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +30 -0
  170. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
  171. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +263 -0
  172. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +304 -0
  173. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +29 -0
  174. data/bridge/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
  175. data/bridge/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
  176. data/bridge/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
  177. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
  178. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
  179. data/bridge/sdk-core/rustfmt.toml +1 -0
  180. data/bridge/sdk-core/sdk/Cargo.toml +47 -0
  181. data/bridge/sdk-core/sdk/LICENSE.txt +23 -0
  182. data/bridge/sdk-core/sdk/src/activity_context.rs +230 -0
  183. data/bridge/sdk-core/sdk/src/app_data.rs +37 -0
  184. data/bridge/sdk-core/sdk/src/interceptors.rs +50 -0
  185. data/bridge/sdk-core/sdk/src/lib.rs +794 -0
  186. data/bridge/sdk-core/sdk/src/payload_converter.rs +11 -0
  187. data/bridge/sdk-core/sdk/src/workflow_context/options.rs +295 -0
  188. data/bridge/sdk-core/sdk/src/workflow_context.rs +694 -0
  189. data/bridge/sdk-core/sdk/src/workflow_future.rs +499 -0
  190. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +30 -0
  191. data/bridge/sdk-core/sdk-core-protos/LICENSE.txt +23 -0
  192. data/bridge/sdk-core/sdk-core-protos/build.rs +107 -0
  193. data/bridge/sdk-core/sdk-core-protos/src/constants.rs +7 -0
  194. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +544 -0
  195. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +230 -0
  196. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +1970 -0
  197. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
  198. data/bridge/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  199. data/bridge/sdk-core/test-utils/Cargo.toml +36 -0
  200. data/bridge/sdk-core/test-utils/src/canned_histories.rs +1579 -0
  201. data/bridge/sdk-core/test-utils/src/histfetch.rs +28 -0
  202. data/bridge/sdk-core/test-utils/src/lib.rs +650 -0
  203. data/bridge/sdk-core/tests/integ_tests/client_tests.rs +36 -0
  204. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +128 -0
  205. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +221 -0
  206. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +37 -0
  207. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +133 -0
  208. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +437 -0
  209. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
  210. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +878 -0
  211. data/bridge/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +61 -0
  212. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +59 -0
  213. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +58 -0
  214. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +50 -0
  215. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +60 -0
  216. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +54 -0
  217. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +788 -0
  218. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +53 -0
  219. data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +113 -0
  220. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +223 -0
  221. data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +93 -0
  222. data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +167 -0
  223. data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +99 -0
  224. data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +131 -0
  225. data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +75 -0
  226. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +597 -0
  227. data/bridge/sdk-core/tests/load_tests.rs +191 -0
  228. data/bridge/sdk-core/tests/main.rs +113 -0
  229. data/bridge/sdk-core/tests/runner.rs +93 -0
  230. data/bridge/src/connection.rs +186 -0
  231. data/bridge/src/lib.rs +239 -0
  232. data/bridge/src/runtime.rs +54 -0
  233. data/bridge/src/worker.rs +124 -0
  234. data/ext/Rakefile +9 -0
  235. data/lib/bridge.so +0 -0
  236. data/lib/gen/dependencies/gogoproto/gogo_pb.rb +14 -0
  237. data/lib/gen/temporal/api/batch/v1/message_pb.rb +50 -0
  238. data/lib/gen/temporal/api/command/v1/message_pb.rb +174 -0
  239. data/lib/gen/temporal/api/common/v1/message_pb.rb +69 -0
  240. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +33 -0
  241. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +39 -0
  242. data/lib/gen/temporal/api/enums/v1/common_pb.rb +42 -0
  243. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +68 -0
  244. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +77 -0
  245. data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +25 -0
  246. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +37 -0
  247. data/lib/gen/temporal/api/enums/v1/query_pb.rb +31 -0
  248. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +24 -0
  249. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +28 -0
  250. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +30 -0
  251. data/lib/gen/temporal/api/enums/v1/update_pb.rb +23 -0
  252. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +89 -0
  253. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +84 -0
  254. data/lib/gen/temporal/api/failure/v1/message_pb.rb +83 -0
  255. data/lib/gen/temporal/api/filter/v1/message_pb.rb +40 -0
  256. data/lib/gen/temporal/api/history/v1/message_pb.rb +490 -0
  257. data/lib/gen/temporal/api/interaction/v1/message_pb.rb +49 -0
  258. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +63 -0
  259. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +85 -0
  260. data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +20 -0
  261. data/lib/gen/temporal/api/query/v1/message_pb.rb +38 -0
  262. data/lib/gen/temporal/api/replication/v1/message_pb.rb +37 -0
  263. data/lib/gen/temporal/api/schedule/v1/message_pb.rb +149 -0
  264. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +73 -0
  265. data/lib/gen/temporal/api/version/v1/message_pb.rb +41 -0
  266. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +111 -0
  267. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +788 -0
  268. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +20 -0
  269. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +58 -0
  270. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +57 -0
  271. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +222 -0
  272. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +57 -0
  273. data/lib/gen/temporal/sdk/core/common/common_pb.rb +22 -0
  274. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +34 -0
  275. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +27 -0
  276. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +165 -0
  277. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +196 -0
  278. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +34 -0
  279. data/lib/temporalio/activity/context.rb +97 -0
  280. data/lib/temporalio/activity/info.rb +67 -0
  281. data/lib/temporalio/activity.rb +85 -0
  282. data/lib/temporalio/bridge/error.rb +8 -0
  283. data/lib/temporalio/bridge.rb +14 -0
  284. data/lib/temporalio/client/implementation.rb +340 -0
  285. data/lib/temporalio/client/workflow_handle.rb +243 -0
  286. data/lib/temporalio/client.rb +131 -0
  287. data/lib/temporalio/connection.rb +751 -0
  288. data/lib/temporalio/data_converter.rb +191 -0
  289. data/lib/temporalio/error/failure.rb +194 -0
  290. data/lib/temporalio/error/workflow_failure.rb +19 -0
  291. data/lib/temporalio/errors.rb +40 -0
  292. data/lib/temporalio/failure_converter/base.rb +26 -0
  293. data/lib/temporalio/failure_converter/basic.rb +319 -0
  294. data/lib/temporalio/failure_converter.rb +7 -0
  295. data/lib/temporalio/interceptor/chain.rb +28 -0
  296. data/lib/temporalio/interceptor/client.rb +123 -0
  297. data/lib/temporalio/payload_codec/base.rb +32 -0
  298. data/lib/temporalio/payload_converter/base.rb +24 -0
  299. data/lib/temporalio/payload_converter/bytes.rb +27 -0
  300. data/lib/temporalio/payload_converter/composite.rb +49 -0
  301. data/lib/temporalio/payload_converter/encoding_base.rb +35 -0
  302. data/lib/temporalio/payload_converter/json.rb +26 -0
  303. data/lib/temporalio/payload_converter/nil.rb +26 -0
  304. data/lib/temporalio/payload_converter.rb +14 -0
  305. data/lib/temporalio/retry_policy.rb +82 -0
  306. data/lib/temporalio/retry_state.rb +35 -0
  307. data/lib/temporalio/runtime.rb +25 -0
  308. data/lib/temporalio/timeout_type.rb +29 -0
  309. data/lib/temporalio/version.rb +3 -0
  310. data/lib/temporalio/worker/activity_runner.rb +92 -0
  311. data/lib/temporalio/worker/activity_worker.rb +138 -0
  312. data/lib/temporalio/worker/reactor.rb +46 -0
  313. data/lib/temporalio/worker/runner.rb +63 -0
  314. data/lib/temporalio/worker/sync_worker.rb +88 -0
  315. data/lib/temporalio/worker/thread_pool_executor.rb +51 -0
  316. data/lib/temporalio/worker.rb +198 -0
  317. data/lib/temporalio/workflow/execution_info.rb +54 -0
  318. data/lib/temporalio/workflow/execution_status.rb +36 -0
  319. data/lib/temporalio/workflow/id_reuse_policy.rb +36 -0
  320. data/lib/temporalio/workflow/query_reject_condition.rb +33 -0
  321. data/lib/temporalio.rb +12 -1
  322. data/lib/thermite_patch.rb +23 -0
  323. data/temporalio.gemspec +45 -0
  324. metadata +566 -9
  325. data/lib/temporal/version.rb +0 -3
  326. data/lib/temporal.rb +0 -4
  327. data/temporal.gemspec +0 -20
@@ -0,0 +1,1970 @@
1
+ //! Contains the protobuf definitions used as arguments to and return values from interactions with
2
+ //! the Temporal Core SDK. Language SDK authors can generate structs using the proto definitions
3
+ //! that will match the generated structs in this module.
4
+
5
+ pub mod constants;
6
+ pub mod utilities;
7
+
8
+ #[cfg(feature = "history_builders")]
9
+ mod history_builder;
10
+ #[cfg(feature = "history_builders")]
11
+ mod history_info;
12
+ mod task_token;
13
+
14
+ #[cfg(feature = "history_builders")]
15
+ pub use history_builder::{default_wes_attribs, TestHistoryBuilder, DEFAULT_WORKFLOW_TYPE};
16
+ #[cfg(feature = "history_builders")]
17
+ pub use history_info::HistoryInfo;
18
+ pub use task_token::TaskToken;
19
+
20
+ #[allow(clippy::large_enum_variant, clippy::derive_partial_eq_without_eq)]
21
+ // I'd prefer not to do this, but there are some generated things that just don't need it.
22
+ #[allow(missing_docs)]
23
+ pub mod coresdk {
24
+ //! Contains all protobufs relating to communication between core and lang-specific SDKs
25
+
26
+ tonic::include_proto!("coresdk");
27
+
28
+ use crate::temporal::api::{
29
+ common::v1::{ActivityType, Payload, Payloads, WorkflowExecution},
30
+ failure::v1::{failure::FailureInfo, ApplicationFailureInfo, Failure},
31
+ workflowservice::v1::PollActivityTaskQueueResponse,
32
+ };
33
+ use activity_task::ActivityTask;
34
+ use serde::{Deserialize, Serialize};
35
+ use std::{
36
+ collections::HashMap,
37
+ convert::TryFrom,
38
+ fmt::{Display, Formatter},
39
+ iter::FromIterator,
40
+ };
41
+ use workflow_activation::{workflow_activation_job, WorkflowActivationJob};
42
+ use workflow_commands::{workflow_command, workflow_command::Variant, WorkflowCommand};
43
+ use workflow_completion::{workflow_activation_completion, WorkflowActivationCompletion};
44
+
45
+ #[allow(clippy::module_inception)]
46
+ pub mod activity_task {
47
+ use crate::{coresdk::ActivityTaskCompletion, task_token::fmt_tt};
48
+ use std::fmt::{Display, Formatter};
49
+ tonic::include_proto!("coresdk.activity_task");
50
+
51
+ impl ActivityTask {
52
+ pub fn cancel_from_ids(task_token: Vec<u8>, reason: ActivityCancelReason) -> Self {
53
+ Self {
54
+ task_token,
55
+ variant: Some(activity_task::Variant::Cancel(Cancel {
56
+ reason: reason as i32,
57
+ })),
58
+ }
59
+ }
60
+ }
61
+
62
+ impl Display for ActivityTaskCompletion {
63
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
64
+ write!(
65
+ f,
66
+ "ActivityTaskCompletion(token: {}",
67
+ fmt_tt(&self.task_token),
68
+ )?;
69
+ if let Some(r) = self.result.as_ref().and_then(|r| r.status.as_ref()) {
70
+ write!(f, ", {}", r)?;
71
+ } else {
72
+ write!(f, ", missing result")?;
73
+ }
74
+ write!(f, ")")
75
+ }
76
+ }
77
+ }
78
+ #[allow(clippy::module_inception)]
79
+ pub mod activity_result {
80
+ tonic::include_proto!("coresdk.activity_result");
81
+ use super::super::temporal::api::{
82
+ common::v1::Payload,
83
+ failure::v1::{failure, CanceledFailureInfo, Failure as APIFailure},
84
+ };
85
+ use crate::temporal::api::{enums::v1::TimeoutType, failure::v1::TimeoutFailureInfo};
86
+ use activity_execution_result as aer;
87
+ use std::fmt::{Display, Formatter};
88
+
89
+ impl ActivityExecutionResult {
90
+ pub const fn ok(result: Payload) -> Self {
91
+ Self {
92
+ status: Some(aer::Status::Completed(Success {
93
+ result: Some(result),
94
+ })),
95
+ }
96
+ }
97
+
98
+ pub fn fail(fail: APIFailure) -> Self {
99
+ Self {
100
+ status: Some(aer::Status::Failed(Failure {
101
+ failure: Some(fail),
102
+ })),
103
+ }
104
+ }
105
+
106
+ pub fn cancel_from_details(payload: Option<Payload>) -> Self {
107
+ Self {
108
+ status: Some(aer::Status::Cancelled(Cancellation::from_details(payload))),
109
+ }
110
+ }
111
+
112
+ pub const fn will_complete_async() -> Self {
113
+ Self {
114
+ status: Some(aer::Status::WillCompleteAsync(WillCompleteAsync {})),
115
+ }
116
+ }
117
+
118
+ pub fn is_cancelled(&self) -> bool {
119
+ matches!(self.status, Some(aer::Status::Cancelled(_)))
120
+ }
121
+ }
122
+
123
+ impl Display for aer::Status {
124
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
125
+ write!(f, "ActivityExecutionResult(")?;
126
+ match self {
127
+ aer::Status::Completed(v) => {
128
+ write!(f, "{})", v)
129
+ }
130
+ aer::Status::Failed(v) => {
131
+ write!(f, "{})", v)
132
+ }
133
+ aer::Status::Cancelled(v) => {
134
+ write!(f, "{})", v)
135
+ }
136
+ aer::Status::WillCompleteAsync(_) => {
137
+ write!(f, "Will complete async)")
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ impl Display for Success {
144
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
145
+ write!(f, "Success(")?;
146
+ if let Some(ref v) = self.result {
147
+ write!(f, "{}", v)?;
148
+ }
149
+ write!(f, ")")
150
+ }
151
+ }
152
+
153
+ impl Display for Failure {
154
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
155
+ write!(f, "Failure(")?;
156
+ if let Some(ref v) = self.failure {
157
+ write!(f, "{}", v)?;
158
+ }
159
+ write!(f, ")")
160
+ }
161
+ }
162
+
163
+ impl Display for Cancellation {
164
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
165
+ write!(f, "Cancellation(")?;
166
+ if let Some(ref v) = self.failure {
167
+ write!(f, "{}", v)?;
168
+ }
169
+ write!(f, ")")
170
+ }
171
+ }
172
+
173
+ impl From<Result<Payload, APIFailure>> for ActivityExecutionResult {
174
+ fn from(r: Result<Payload, APIFailure>) -> Self {
175
+ Self {
176
+ status: match r {
177
+ Ok(p) => Some(aer::Status::Completed(Success { result: Some(p) })),
178
+ Err(f) => Some(aer::Status::Failed(Failure { failure: Some(f) })),
179
+ },
180
+ }
181
+ }
182
+ }
183
+
184
+ impl ActivityResolution {
185
+ pub fn unwrap_ok_payload(self) -> Payload {
186
+ match self.status.unwrap() {
187
+ activity_resolution::Status::Completed(c) => c.result.unwrap(),
188
+ _ => panic!("Activity was not successful"),
189
+ }
190
+ }
191
+
192
+ pub fn completed_ok(&self) -> bool {
193
+ matches!(self.status, Some(activity_resolution::Status::Completed(_)))
194
+ }
195
+
196
+ pub fn failed(&self) -> bool {
197
+ matches!(self.status, Some(activity_resolution::Status::Failed(_)))
198
+ }
199
+
200
+ pub fn timed_out(&self) -> Option<crate::temporal::api::enums::v1::TimeoutType> {
201
+ match self.status {
202
+ Some(activity_resolution::Status::Failed(Failure {
203
+ failure: Some(ref f),
204
+ })) => f
205
+ .is_timeout()
206
+ .or_else(|| f.cause.as_ref().and_then(|c| c.is_timeout())),
207
+ _ => None,
208
+ }
209
+ }
210
+
211
+ pub fn cancelled(&self) -> bool {
212
+ matches!(self.status, Some(activity_resolution::Status::Cancelled(_)))
213
+ }
214
+ }
215
+
216
+ impl Cancellation {
217
+ pub fn from_details(payload: Option<Payload>) -> Self {
218
+ Cancellation {
219
+ failure: Some(APIFailure {
220
+ message: "Activity cancelled".to_string(),
221
+ failure_info: Some(failure::FailureInfo::CanceledFailureInfo(
222
+ CanceledFailureInfo {
223
+ details: payload.map(Into::into),
224
+ },
225
+ )),
226
+ ..Default::default()
227
+ }),
228
+ }
229
+ }
230
+ }
231
+
232
+ impl Failure {
233
+ pub fn timeout(timeout_type: TimeoutType) -> Self {
234
+ Failure {
235
+ failure: Some(APIFailure {
236
+ message: "Activity timed out".to_string(),
237
+ failure_info: Some(failure::FailureInfo::TimeoutFailureInfo(
238
+ TimeoutFailureInfo {
239
+ timeout_type: timeout_type as i32,
240
+ last_heartbeat_details: None,
241
+ },
242
+ )),
243
+ ..Default::default()
244
+ }),
245
+ }
246
+ }
247
+ }
248
+ }
249
+
250
+ pub mod common {
251
+ tonic::include_proto!("coresdk.common");
252
+ use super::external_data::LocalActivityMarkerData;
253
+ use crate::{
254
+ coresdk::{AsJsonPayloadExt, IntoPayloadsExt},
255
+ temporal::api::common::v1::{Payload, Payloads},
256
+ };
257
+ use std::collections::HashMap;
258
+
259
+ pub fn build_has_change_marker_details(
260
+ patch_id: &str,
261
+ deprecated: bool,
262
+ ) -> HashMap<String, Payloads> {
263
+ let mut hm = HashMap::new();
264
+ hm.insert("patch_id".to_string(), patch_id.as_bytes().into());
265
+ let deprecated = deprecated as u8;
266
+ hm.insert("deprecated".to_string(), (&[deprecated]).into());
267
+ hm
268
+ }
269
+
270
+ pub fn decode_change_marker_details(
271
+ details: &HashMap<String, Payloads>,
272
+ ) -> Option<(String, bool)> {
273
+ let name =
274
+ std::str::from_utf8(&details.get("patch_id")?.payloads.first()?.data).ok()?;
275
+ let deprecated = *details.get("deprecated")?.payloads.first()?.data.first()? != 0;
276
+ Some((name.to_string(), deprecated))
277
+ }
278
+
279
+ pub fn build_local_activity_marker_details(
280
+ metadata: LocalActivityMarkerData,
281
+ result: Option<Payload>,
282
+ ) -> HashMap<String, Payloads> {
283
+ let mut hm = HashMap::new();
284
+ // It would be more efficient for this to be proto binary, but then it shows up as
285
+ // meaningless in the Temporal UI...
286
+ if let Some(jsonified) = metadata.as_json_payload().into_payloads() {
287
+ hm.insert("data".to_string(), jsonified);
288
+ }
289
+ if let Some(res) = result {
290
+ hm.insert("result".to_string(), res.into());
291
+ }
292
+ hm
293
+ }
294
+
295
+ /// Given a marker detail map, returns just the local activity info, but not the payload.
296
+ /// This is fairly inexpensive. Deserializing the whole payload may not be.
297
+ pub fn extract_local_activity_marker_data(
298
+ details: &HashMap<String, Payloads>,
299
+ ) -> Option<LocalActivityMarkerData> {
300
+ details
301
+ .get("data")
302
+ .and_then(|p| p.payloads.get(0))
303
+ .and_then(|p| std::str::from_utf8(&p.data).ok())
304
+ .and_then(|s| serde_json::from_str(s).ok())
305
+ }
306
+
307
+ /// Given a marker detail map, returns the local activity info and the result payload
308
+ /// if they are found and the marker data is well-formed. This removes the data from the
309
+ /// map.
310
+ pub fn extract_local_activity_marker_details(
311
+ details: &mut HashMap<String, Payloads>,
312
+ ) -> (Option<LocalActivityMarkerData>, Option<Payload>) {
313
+ let data = extract_local_activity_marker_data(details);
314
+ let result = details.remove("result").and_then(|mut p| p.payloads.pop());
315
+ (data, result)
316
+ }
317
+ }
318
+
319
+ pub mod external_data {
320
+ use prost_types::{Duration, Timestamp};
321
+ use serde::{Deserialize, Deserializer, Serialize, Serializer};
322
+ tonic::include_proto!("coresdk.external_data");
323
+
324
+ // Buncha hullaballoo because prost types aren't serde compat.
325
+ // See https://github.com/tokio-rs/prost/issues/75 which hilariously Chad opened ages ago
326
+
327
+ #[derive(Serialize, Deserialize)]
328
+ #[serde(remote = "Timestamp")]
329
+ struct TimestampDef {
330
+ pub seconds: i64,
331
+ pub nanos: i32,
332
+ }
333
+ mod opt_timestamp {
334
+ use super::*;
335
+
336
+ pub fn serialize<S>(value: &Option<Timestamp>, serializer: S) -> Result<S::Ok, S::Error>
337
+ where
338
+ S: Serializer,
339
+ {
340
+ #[derive(Serialize)]
341
+ struct Helper<'a>(#[serde(with = "TimestampDef")] &'a Timestamp);
342
+
343
+ value.as_ref().map(Helper).serialize(serializer)
344
+ }
345
+
346
+ pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Timestamp>, D::Error>
347
+ where
348
+ D: Deserializer<'de>,
349
+ {
350
+ #[derive(Deserialize)]
351
+ struct Helper(#[serde(with = "TimestampDef")] Timestamp);
352
+
353
+ let helper = Option::deserialize(deserializer)?;
354
+ Ok(helper.map(|Helper(external)| external))
355
+ }
356
+ }
357
+
358
+ // Luckily Duration is also stored the exact same way
359
+ #[derive(Serialize, Deserialize)]
360
+ #[serde(remote = "Duration")]
361
+ struct DurationDef {
362
+ pub seconds: i64,
363
+ pub nanos: i32,
364
+ }
365
+ mod opt_duration {
366
+ use super::*;
367
+
368
+ pub fn serialize<S>(value: &Option<Duration>, serializer: S) -> Result<S::Ok, S::Error>
369
+ where
370
+ S: Serializer,
371
+ {
372
+ #[derive(Serialize)]
373
+ struct Helper<'a>(#[serde(with = "DurationDef")] &'a Duration);
374
+
375
+ value.as_ref().map(Helper).serialize(serializer)
376
+ }
377
+
378
+ pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
379
+ where
380
+ D: Deserializer<'de>,
381
+ {
382
+ #[derive(Deserialize)]
383
+ struct Helper(#[serde(with = "DurationDef")] Duration);
384
+
385
+ let helper = Option::deserialize(deserializer)?;
386
+ Ok(helper.map(|Helper(external)| external))
387
+ }
388
+ }
389
+ }
390
+
391
+ pub mod workflow_activation {
392
+ use crate::{
393
+ coresdk::{
394
+ common::NamespacedWorkflowExecution,
395
+ workflow_activation::remove_from_cache::EvictionReason, FromPayloadsExt,
396
+ },
397
+ temporal::api::{
398
+ common::v1::Header,
399
+ history::v1::{
400
+ WorkflowExecutionCancelRequestedEventAttributes,
401
+ WorkflowExecutionSignaledEventAttributes,
402
+ WorkflowExecutionStartedEventAttributes,
403
+ },
404
+ query::v1::WorkflowQuery,
405
+ },
406
+ };
407
+ use prost_types::Timestamp;
408
+ use std::{
409
+ collections::HashMap,
410
+ fmt::{Display, Formatter},
411
+ };
412
+
413
+ tonic::include_proto!("coresdk.workflow_activation");
414
+
415
+ pub fn create_evict_activation(
416
+ run_id: String,
417
+ message: String,
418
+ reason: EvictionReason,
419
+ ) -> WorkflowActivation {
420
+ WorkflowActivation {
421
+ timestamp: None,
422
+ run_id,
423
+ is_replaying: false,
424
+ history_length: 0,
425
+ jobs: vec![WorkflowActivationJob::from(
426
+ workflow_activation_job::Variant::RemoveFromCache(RemoveFromCache {
427
+ message,
428
+ reason: reason as i32,
429
+ }),
430
+ )],
431
+ }
432
+ }
433
+
434
+ pub fn query_to_job(id: String, q: WorkflowQuery) -> QueryWorkflow {
435
+ QueryWorkflow {
436
+ query_id: id,
437
+ query_type: q.query_type,
438
+ arguments: Vec::from_payloads(q.query_args),
439
+ headers: q.header.map(|h| h.into()).unwrap_or_default(),
440
+ }
441
+ }
442
+
443
+ impl WorkflowActivation {
444
+ /// Returns the index of the eviction job if this activation contains one. If present
445
+ /// it should always be the last job in the list.
446
+ pub fn eviction_index(&self) -> Option<usize> {
447
+ self.jobs.iter().position(|j| {
448
+ matches!(
449
+ j,
450
+ WorkflowActivationJob {
451
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_))
452
+ }
453
+ )
454
+ })
455
+ }
456
+
457
+ /// Returns true if the only job is eviction
458
+ pub fn is_only_eviction(&self) -> bool {
459
+ self.jobs.len() == 1 && self.eviction_index().is_some()
460
+ }
461
+
462
+ /// Returns eviction reason if this activation has an evict job
463
+ pub fn eviction_reason(&self) -> Option<EvictionReason> {
464
+ self.jobs.iter().find_map(|j| {
465
+ if let Some(workflow_activation_job::Variant::RemoveFromCache(ref rj)) =
466
+ j.variant
467
+ {
468
+ EvictionReason::from_i32(rj.reason)
469
+ } else {
470
+ None
471
+ }
472
+ })
473
+ }
474
+
475
+ /// Append an eviction job to the joblist
476
+ pub fn append_evict_job(&mut self, evict_job: RemoveFromCache) {
477
+ if let Some(last_job) = self.jobs.last() {
478
+ if matches!(
479
+ last_job.variant,
480
+ Some(workflow_activation_job::Variant::RemoveFromCache(_))
481
+ ) {
482
+ return;
483
+ }
484
+ }
485
+ let evict_job = WorkflowActivationJob::from(
486
+ workflow_activation_job::Variant::RemoveFromCache(evict_job),
487
+ );
488
+ self.jobs.push(evict_job);
489
+ }
490
+ }
491
+
492
+ impl Display for EvictionReason {
493
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
494
+ write!(f, "{:?}", self)
495
+ }
496
+ }
497
+
498
+ impl Display for WorkflowActivation {
499
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
500
+ write!(f, "WorkflowActivation(")?;
501
+ write!(f, "run_id: {}, ", self.run_id)?;
502
+ write!(f, "is_replaying: {}, ", self.is_replaying)?;
503
+ write!(
504
+ f,
505
+ "jobs: {})",
506
+ self.jobs
507
+ .iter()
508
+ .map(ToString::to_string)
509
+ .collect::<Vec<_>>()
510
+ .as_slice()
511
+ .join(", ")
512
+ )
513
+ }
514
+ }
515
+
516
+ impl Display for WorkflowActivationJob {
517
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
518
+ match &self.variant {
519
+ None => write!(f, "empty"),
520
+ Some(v) => write!(f, "{}", v),
521
+ }
522
+ }
523
+ }
524
+
525
+ impl Display for workflow_activation_job::Variant {
526
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
527
+ match self {
528
+ workflow_activation_job::Variant::StartWorkflow(_) => {
529
+ write!(f, "StartWorkflow")
530
+ }
531
+ workflow_activation_job::Variant::FireTimer(t) => {
532
+ write!(f, "FireTimer({})", t.seq)
533
+ }
534
+ workflow_activation_job::Variant::UpdateRandomSeed(_) => {
535
+ write!(f, "UpdateRandomSeed")
536
+ }
537
+ workflow_activation_job::Variant::QueryWorkflow(_) => {
538
+ write!(f, "QueryWorkflow")
539
+ }
540
+ workflow_activation_job::Variant::CancelWorkflow(_) => {
541
+ write!(f, "CancelWorkflow")
542
+ }
543
+ workflow_activation_job::Variant::SignalWorkflow(_) => {
544
+ write!(f, "SignalWorkflow")
545
+ }
546
+ workflow_activation_job::Variant::ResolveActivity(r) => {
547
+ write!(f, "ResolveActivity({})", r.seq)
548
+ }
549
+ workflow_activation_job::Variant::NotifyHasPatch(_) => {
550
+ write!(f, "NotifyHasPatch")
551
+ }
552
+ workflow_activation_job::Variant::ResolveChildWorkflowExecutionStart(_) => {
553
+ write!(f, "ResolveChildWorkflowExecutionStart")
554
+ }
555
+ workflow_activation_job::Variant::ResolveChildWorkflowExecution(_) => {
556
+ write!(f, "ResolveChildWorkflowExecution")
557
+ }
558
+ workflow_activation_job::Variant::ResolveSignalExternalWorkflow(_) => {
559
+ write!(f, "ResolveSignalExternalWorkflow")
560
+ }
561
+ workflow_activation_job::Variant::RemoveFromCache(_) => {
562
+ write!(f, "RemoveFromCache")
563
+ }
564
+ workflow_activation_job::Variant::ResolveRequestCancelExternalWorkflow(_) => {
565
+ write!(f, "ResolveRequestCancelExternalWorkflow")
566
+ }
567
+ }
568
+ }
569
+ }
570
+
571
+ impl Display for QueryWorkflow {
572
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
573
+ write!(
574
+ f,
575
+ "QueryWorkflow(id: {}, type: {})",
576
+ self.query_id, self.query_type
577
+ )
578
+ }
579
+ }
580
+
581
+ impl From<WorkflowExecutionSignaledEventAttributes> for SignalWorkflow {
582
+ fn from(a: WorkflowExecutionSignaledEventAttributes) -> Self {
583
+ Self {
584
+ signal_name: a.signal_name,
585
+ input: Vec::from_payloads(a.input),
586
+ identity: a.identity,
587
+ headers: a.header.map(Into::into).unwrap_or_default(),
588
+ }
589
+ }
590
+ }
591
+
592
+ impl From<WorkflowExecutionCancelRequestedEventAttributes> for CancelWorkflow {
593
+ fn from(_a: WorkflowExecutionCancelRequestedEventAttributes) -> Self {
594
+ Self { details: vec![] }
595
+ }
596
+ }
597
+
598
+ /// Create a [StartWorkflow] job from corresponding event attributes
599
+ pub fn start_workflow_from_attribs(
600
+ attrs: WorkflowExecutionStartedEventAttributes,
601
+ workflow_id: String,
602
+ randomness_seed: u64,
603
+ start_time: Timestamp,
604
+ ) -> StartWorkflow {
605
+ StartWorkflow {
606
+ workflow_type: attrs.workflow_type.map(|wt| wt.name).unwrap_or_default(),
607
+ workflow_id,
608
+ arguments: Vec::from_payloads(attrs.input),
609
+ randomness_seed,
610
+ headers: match attrs.header {
611
+ None => HashMap::new(),
612
+ Some(Header { fields }) => fields,
613
+ },
614
+ identity: attrs.identity,
615
+ parent_workflow_info: attrs.parent_workflow_execution.map(|pe| {
616
+ NamespacedWorkflowExecution {
617
+ namespace: attrs.parent_workflow_namespace,
618
+ run_id: pe.run_id,
619
+ workflow_id: pe.workflow_id,
620
+ }
621
+ }),
622
+ workflow_execution_timeout: attrs.workflow_execution_timeout,
623
+ workflow_run_timeout: attrs.workflow_run_timeout,
624
+ workflow_task_timeout: attrs.workflow_task_timeout,
625
+ continued_from_execution_run_id: attrs.continued_execution_run_id,
626
+ continued_initiator: attrs.initiator,
627
+ continued_failure: attrs.continued_failure,
628
+ last_completion_result: attrs.last_completion_result,
629
+ first_execution_run_id: attrs.first_execution_run_id,
630
+ retry_policy: attrs.retry_policy,
631
+ attempt: attrs.attempt,
632
+ cron_schedule: attrs.cron_schedule,
633
+ workflow_execution_expiration_time: attrs.workflow_execution_expiration_time,
634
+ cron_schedule_to_schedule_interval: attrs.first_workflow_task_backoff,
635
+ memo: attrs.memo,
636
+ search_attributes: attrs.search_attributes,
637
+ start_time: Some(start_time),
638
+ }
639
+ }
640
+ }
641
+
642
+ pub mod workflow_completion {
643
+ use crate::temporal::api::failure;
644
+ tonic::include_proto!("coresdk.workflow_completion");
645
+
646
+ impl workflow_activation_completion::Status {
647
+ pub const fn is_success(&self) -> bool {
648
+ match &self {
649
+ Self::Successful(_) => true,
650
+ Self::Failed(_) => false,
651
+ }
652
+ }
653
+ }
654
+
655
+ impl From<failure::v1::Failure> for Failure {
656
+ fn from(f: failure::v1::Failure) -> Self {
657
+ Failure { failure: Some(f) }
658
+ }
659
+ }
660
+ }
661
+
662
+ pub mod child_workflow {
663
+ tonic::include_proto!("coresdk.child_workflow");
664
+ }
665
+
666
+ pub mod workflow_commands {
667
+ tonic::include_proto!("coresdk.workflow_commands");
668
+
669
+ use crate::temporal::api::{common::v1::Payloads, enums::v1::QueryResultType};
670
+ use std::fmt::{Display, Formatter};
671
+
672
+ impl Display for WorkflowCommand {
673
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
674
+ match &self.variant {
675
+ None => write!(f, "Empty"),
676
+ Some(v) => write!(f, "{}", v),
677
+ }
678
+ }
679
+ }
680
+
681
+ impl Display for StartTimer {
682
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
683
+ write!(f, "StartTimer({})", self.seq)
684
+ }
685
+ }
686
+
687
+ impl Display for ScheduleActivity {
688
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
689
+ write!(f, "ScheduleActivity({}, {})", self.seq, self.activity_type)
690
+ }
691
+ }
692
+
693
+ impl Display for ScheduleLocalActivity {
694
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
695
+ write!(
696
+ f,
697
+ "ScheduleLocalActivity({}, {})",
698
+ self.seq, self.activity_type
699
+ )
700
+ }
701
+ }
702
+
703
+ impl Display for QueryResult {
704
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
705
+ write!(f, "RespondToQuery({})", self.query_id)
706
+ }
707
+ }
708
+
709
+ impl Display for RequestCancelActivity {
710
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
711
+ write!(f, "RequestCancelActivity({})", self.seq)
712
+ }
713
+ }
714
+
715
+ impl Display for RequestCancelLocalActivity {
716
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
717
+ write!(f, "RequestCancelLocalActivity({})", self.seq)
718
+ }
719
+ }
720
+
721
+ impl Display for CancelTimer {
722
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
723
+ write!(f, "CancelTimer({})", self.seq)
724
+ }
725
+ }
726
+
727
+ impl Display for CompleteWorkflowExecution {
728
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
729
+ write!(f, "CompleteWorkflowExecution")
730
+ }
731
+ }
732
+
733
+ impl Display for FailWorkflowExecution {
734
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
735
+ write!(f, "FailWorkflowExecution")
736
+ }
737
+ }
738
+
739
+ impl Display for ContinueAsNewWorkflowExecution {
740
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
741
+ write!(f, "ContinueAsNewWorkflowExecution")
742
+ }
743
+ }
744
+
745
+ impl Display for CancelWorkflowExecution {
746
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
747
+ write!(f, "CancelWorkflowExecution")
748
+ }
749
+ }
750
+
751
+ impl Display for SetPatchMarker {
752
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
753
+ write!(f, "SetPatchMarker({})", self.patch_id)
754
+ }
755
+ }
756
+
757
+ impl Display for StartChildWorkflowExecution {
758
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
759
+ write!(
760
+ f,
761
+ "StartChildWorkflowExecution({}, {})",
762
+ self.seq, self.workflow_type
763
+ )
764
+ }
765
+ }
766
+
767
+ impl Display for RequestCancelExternalWorkflowExecution {
768
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
769
+ write!(f, "RequestCancelExternalWorkflowExecution({})", self.seq)
770
+ }
771
+ }
772
+
773
+ impl Display for UpsertWorkflowSearchAttributes {
774
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
775
+ write!(
776
+ f,
777
+ "UpsertWorkflowSearchAttributes({:?})",
778
+ self.search_attributes.keys()
779
+ )
780
+ }
781
+ }
782
+
783
+ impl Display for SignalExternalWorkflowExecution {
784
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
785
+ write!(f, "SignalExternalWorkflowExecution({})", self.seq)
786
+ }
787
+ }
788
+
789
+ impl Display for CancelSignalWorkflow {
790
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
791
+ write!(f, "CancelSignalWorkflow({})", self.seq)
792
+ }
793
+ }
794
+
795
+ impl Display for CancelChildWorkflowExecution {
796
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
797
+ write!(
798
+ f,
799
+ "CancelChildWorkflowExecution({})",
800
+ self.child_workflow_seq
801
+ )
802
+ }
803
+ }
804
+
805
+ impl Display for ModifyWorkflowProperties {
806
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
807
+ write!(
808
+ f,
809
+ "ModifyWorkflowProperties(upserted memo keys: {:?})",
810
+ self.upserted_memo.as_ref().map(|m| m.fields.keys())
811
+ )
812
+ }
813
+ }
814
+
815
+ impl QueryResult {
816
+ /// Helper to construct the Temporal API query result types.
817
+ pub fn into_components(self) -> (String, QueryResultType, Option<Payloads>, String) {
818
+ match self {
819
+ QueryResult {
820
+ variant: Some(query_result::Variant::Succeeded(qs)),
821
+ query_id,
822
+ } => (
823
+ query_id,
824
+ QueryResultType::Answered,
825
+ qs.response.map(Into::into),
826
+ "".to_string(),
827
+ ),
828
+ QueryResult {
829
+ variant: Some(query_result::Variant::Failed(err)),
830
+ query_id,
831
+ } => (query_id, QueryResultType::Failed, None, err.message),
832
+ QueryResult {
833
+ variant: None,
834
+ query_id,
835
+ } => (
836
+ query_id,
837
+ QueryResultType::Failed,
838
+ None,
839
+ "Query response was empty".to_string(),
840
+ ),
841
+ }
842
+ }
843
+ }
844
+ }
845
+
846
+ pub type HistoryEventId = i64;
847
+
848
+ impl From<workflow_activation_job::Variant> for WorkflowActivationJob {
849
+ fn from(a: workflow_activation_job::Variant) -> Self {
850
+ Self { variant: Some(a) }
851
+ }
852
+ }
853
+
854
+ impl From<Vec<WorkflowCommand>> for workflow_completion::Success {
855
+ fn from(v: Vec<WorkflowCommand>) -> Self {
856
+ Self { commands: v }
857
+ }
858
+ }
859
+
860
+ impl From<workflow_command::Variant> for WorkflowCommand {
861
+ fn from(v: workflow_command::Variant) -> Self {
862
+ Self { variant: Some(v) }
863
+ }
864
+ }
865
+
866
+ impl workflow_completion::Success {
867
+ pub fn from_variants(cmds: Vec<Variant>) -> Self {
868
+ let cmds: Vec<_> = cmds
869
+ .into_iter()
870
+ .map(|c| WorkflowCommand { variant: Some(c) })
871
+ .collect();
872
+ cmds.into()
873
+ }
874
+ }
875
+
876
+ impl WorkflowActivationCompletion {
877
+ /// Create a successful activation with no commands in it
878
+ pub fn empty(run_id: impl Into<String>) -> Self {
879
+ let success = workflow_completion::Success::from_variants(vec![]);
880
+ Self {
881
+ run_id: run_id.into(),
882
+ status: Some(workflow_activation_completion::Status::Successful(success)),
883
+ }
884
+ }
885
+
886
+ /// Create a successful activation from a list of commands
887
+ pub fn from_cmds(run_id: impl Into<String>, cmds: Vec<workflow_command::Variant>) -> Self {
888
+ let success = workflow_completion::Success::from_variants(cmds);
889
+ Self {
890
+ run_id: run_id.into(),
891
+ status: Some(workflow_activation_completion::Status::Successful(success)),
892
+ }
893
+ }
894
+
895
+ /// Create a successful activation from just one command
896
+ pub fn from_cmd(run_id: impl Into<String>, cmd: workflow_command::Variant) -> Self {
897
+ let success = workflow_completion::Success::from_variants(vec![cmd]);
898
+ Self {
899
+ run_id: run_id.into(),
900
+ status: Some(workflow_activation_completion::Status::Successful(success)),
901
+ }
902
+ }
903
+
904
+ pub fn fail(run_id: impl Into<String>, failure: Failure) -> Self {
905
+ Self {
906
+ run_id: run_id.into(),
907
+ status: Some(workflow_activation_completion::Status::Failed(
908
+ workflow_completion::Failure {
909
+ failure: Some(failure),
910
+ },
911
+ )),
912
+ }
913
+ }
914
+
915
+ /// Returns true if the activation has either a fail, continue, cancel, or complete workflow
916
+ /// execution command in it.
917
+ pub fn has_execution_ending(&self) -> bool {
918
+ self.has_complete_workflow_execution()
919
+ || self.has_fail_execution()
920
+ || self.has_continue_as_new()
921
+ || self.has_cancel_workflow_execution()
922
+ }
923
+
924
+ /// Returns true if the activation contains a fail workflow execution command
925
+ pub fn has_fail_execution(&self) -> bool {
926
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
927
+ return s.commands.iter().any(|wfc| {
928
+ matches!(
929
+ wfc,
930
+ WorkflowCommand {
931
+ variant: Some(workflow_command::Variant::FailWorkflowExecution(_)),
932
+ }
933
+ )
934
+ });
935
+ }
936
+ false
937
+ }
938
+
939
+ /// Returns true if the activation contains a cancel workflow execution command
940
+ pub fn has_cancel_workflow_execution(&self) -> bool {
941
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
942
+ return s.commands.iter().any(|wfc| {
943
+ matches!(
944
+ wfc,
945
+ WorkflowCommand {
946
+ variant: Some(workflow_command::Variant::CancelWorkflowExecution(_)),
947
+ }
948
+ )
949
+ });
950
+ }
951
+ false
952
+ }
953
+
954
+ /// Returns true if the activation contains a continue as new workflow execution command
955
+ pub fn has_continue_as_new(&self) -> bool {
956
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
957
+ return s.commands.iter().any(|wfc| {
958
+ matches!(
959
+ wfc,
960
+ WorkflowCommand {
961
+ variant: Some(
962
+ workflow_command::Variant::ContinueAsNewWorkflowExecution(_)
963
+ ),
964
+ }
965
+ )
966
+ });
967
+ }
968
+ false
969
+ }
970
+
971
+ /// Returns true if the activation contains a complete workflow execution command
972
+ pub fn has_complete_workflow_execution(&self) -> bool {
973
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
974
+ return s.commands.iter().any(|wfc| {
975
+ matches!(
976
+ wfc,
977
+ WorkflowCommand {
978
+ variant: Some(workflow_command::Variant::CompleteWorkflowExecution(_)),
979
+ }
980
+ )
981
+ });
982
+ }
983
+ false
984
+ }
985
+
986
+ /// Returns true if the activation completion is a success with no commands
987
+ pub fn is_empty(&self) -> bool {
988
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
989
+ return s.commands.is_empty();
990
+ }
991
+ false
992
+ }
993
+ }
994
+
995
+ /// Makes converting outgoing lang commands into [WorkflowActivationCompletion]s easier
996
+ pub trait IntoCompletion {
997
+ /// The conversion function
998
+ fn into_completion(self, run_id: String) -> WorkflowActivationCompletion;
999
+ }
1000
+
1001
+ impl IntoCompletion for workflow_command::Variant {
1002
+ fn into_completion(self, run_id: String) -> WorkflowActivationCompletion {
1003
+ WorkflowActivationCompletion::from_cmd(run_id, self)
1004
+ }
1005
+ }
1006
+
1007
+ impl<I, V> IntoCompletion for I
1008
+ where
1009
+ I: IntoIterator<Item = V>,
1010
+ V: Into<WorkflowCommand>,
1011
+ {
1012
+ fn into_completion(self, run_id: String) -> WorkflowActivationCompletion {
1013
+ let success = self.into_iter().map(Into::into).collect::<Vec<_>>().into();
1014
+ WorkflowActivationCompletion {
1015
+ run_id,
1016
+ status: Some(workflow_activation_completion::Status::Successful(success)),
1017
+ }
1018
+ }
1019
+ }
1020
+
1021
+ impl Display for WorkflowActivationCompletion {
1022
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1023
+ write!(
1024
+ f,
1025
+ "WorkflowActivationCompletion(run_id: {}, status: ",
1026
+ &self.run_id
1027
+ )?;
1028
+ match &self.status {
1029
+ None => write!(f, "empty")?,
1030
+ Some(s) => write!(f, "{}", s)?,
1031
+ };
1032
+ write!(f, ")")
1033
+ }
1034
+ }
1035
+
1036
+ impl Display for workflow_activation_completion::Status {
1037
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1038
+ match self {
1039
+ workflow_activation_completion::Status::Successful(
1040
+ workflow_completion::Success { commands },
1041
+ ) => {
1042
+ write!(f, "Success(")?;
1043
+ let mut written = 0;
1044
+ for c in commands {
1045
+ write!(f, "{} ", c)?;
1046
+ written += 1;
1047
+ if written >= 10 && written < commands.len() {
1048
+ write!(f, "... {} more", commands.len() - written)?;
1049
+ break;
1050
+ }
1051
+ }
1052
+ write!(f, ")")
1053
+ }
1054
+ workflow_activation_completion::Status::Failed(_) => {
1055
+ write!(f, "Failed")
1056
+ }
1057
+ }
1058
+ }
1059
+ }
1060
+
1061
+ impl ActivityTask {
1062
+ pub fn start_from_poll_resp(r: PollActivityTaskQueueResponse) -> Self {
1063
+ let (workflow_id, run_id) = r
1064
+ .workflow_execution
1065
+ .map(|we| (we.workflow_id, we.run_id))
1066
+ .unwrap_or_default();
1067
+ Self {
1068
+ task_token: r.task_token,
1069
+ variant: Some(activity_task::activity_task::Variant::Start(
1070
+ activity_task::Start {
1071
+ workflow_namespace: r.workflow_namespace,
1072
+ workflow_type: r.workflow_type.map_or_else(|| "".to_string(), |wt| wt.name),
1073
+ workflow_execution: Some(WorkflowExecution {
1074
+ workflow_id,
1075
+ run_id,
1076
+ }),
1077
+ activity_id: r.activity_id,
1078
+ activity_type: r.activity_type.map_or_else(|| "".to_string(), |at| at.name),
1079
+ header_fields: r.header.map(Into::into).unwrap_or_default(),
1080
+ input: Vec::from_payloads(r.input),
1081
+ heartbeat_details: Vec::from_payloads(r.heartbeat_details),
1082
+ scheduled_time: r.scheduled_time,
1083
+ current_attempt_scheduled_time: r.current_attempt_scheduled_time,
1084
+ started_time: r.started_time,
1085
+ attempt: r.attempt as u32,
1086
+ schedule_to_close_timeout: r.schedule_to_close_timeout,
1087
+ start_to_close_timeout: r.start_to_close_timeout,
1088
+ heartbeat_timeout: r.heartbeat_timeout,
1089
+ retry_policy: r.retry_policy.map(Into::into),
1090
+ is_local: false,
1091
+ },
1092
+ )),
1093
+ }
1094
+ }
1095
+ }
1096
+
1097
+ impl From<String> for ActivityType {
1098
+ fn from(name: String) -> Self {
1099
+ Self { name }
1100
+ }
1101
+ }
1102
+
1103
+ impl From<ActivityType> for String {
1104
+ fn from(at: ActivityType) -> Self {
1105
+ at.name
1106
+ }
1107
+ }
1108
+
1109
+ impl Failure {
1110
+ pub fn is_timeout(&self) -> Option<crate::temporal::api::enums::v1::TimeoutType> {
1111
+ match &self.failure_info {
1112
+ Some(FailureInfo::TimeoutFailureInfo(ti)) => Some(ti.timeout_type()),
1113
+ _ => None,
1114
+ }
1115
+ }
1116
+
1117
+ pub fn application_failure(message: String, non_retryable: bool) -> Self {
1118
+ Self {
1119
+ message,
1120
+ failure_info: Some(FailureInfo::ApplicationFailureInfo(
1121
+ ApplicationFailureInfo {
1122
+ non_retryable,
1123
+ ..Default::default()
1124
+ },
1125
+ )),
1126
+ ..Default::default()
1127
+ }
1128
+ }
1129
+
1130
+ /// Extracts an ApplicationFailureInfo from a Failure instance if it exists
1131
+ pub fn maybe_application_failure(&self) -> Option<&ApplicationFailureInfo> {
1132
+ if let Failure {
1133
+ failure_info: Some(FailureInfo::ApplicationFailureInfo(f)),
1134
+ ..
1135
+ } = self
1136
+ {
1137
+ Some(f)
1138
+ } else {
1139
+ None
1140
+ }
1141
+ }
1142
+ }
1143
+
1144
+ impl Display for Failure {
1145
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1146
+ write!(f, "Failure({}, ", self.message)?;
1147
+ match self.failure_info.as_ref() {
1148
+ None => write!(f, "missing info")?,
1149
+ Some(FailureInfo::TimeoutFailureInfo(v)) => {
1150
+ write!(f, "Timeout: {:?}", v.timeout_type())?;
1151
+ }
1152
+ Some(FailureInfo::ApplicationFailureInfo(v)) => {
1153
+ write!(f, "Application Failure: {}", v.r#type)?;
1154
+ }
1155
+ Some(FailureInfo::CanceledFailureInfo(_)) => {
1156
+ write!(f, "Cancelled")?;
1157
+ }
1158
+ Some(FailureInfo::TerminatedFailureInfo(_)) => {
1159
+ write!(f, "Terminated")?;
1160
+ }
1161
+ Some(FailureInfo::ServerFailureInfo(_)) => {
1162
+ write!(f, "Server Failure")?;
1163
+ }
1164
+ Some(FailureInfo::ResetWorkflowFailureInfo(_)) => {
1165
+ write!(f, "Reset Workflow")?;
1166
+ }
1167
+ Some(FailureInfo::ActivityFailureInfo(v)) => {
1168
+ write!(
1169
+ f,
1170
+ "Activity Failure: scheduled_event_id: {}",
1171
+ v.scheduled_event_id
1172
+ )?;
1173
+ }
1174
+ Some(FailureInfo::ChildWorkflowExecutionFailureInfo(v)) => {
1175
+ write!(
1176
+ f,
1177
+ "Child Workflow: started_event_id: {}",
1178
+ v.started_event_id
1179
+ )?;
1180
+ }
1181
+ }
1182
+ write!(f, ")")
1183
+ }
1184
+ }
1185
+
1186
+ impl From<&str> for Failure {
1187
+ fn from(v: &str) -> Self {
1188
+ Failure::application_failure(v.to_string(), false)
1189
+ }
1190
+ }
1191
+
1192
+ impl From<String> for Failure {
1193
+ fn from(v: String) -> Self {
1194
+ Failure::application_failure(v, false)
1195
+ }
1196
+ }
1197
+
1198
+ impl From<anyhow::Error> for Failure {
1199
+ fn from(ae: anyhow::Error) -> Self {
1200
+ Self {
1201
+ failure_info: Some(FailureInfo::ApplicationFailureInfo(
1202
+ ApplicationFailureInfo {
1203
+ ..Default::default()
1204
+ },
1205
+ )),
1206
+ ..ae.chain()
1207
+ .rfold(None, |cause, e| {
1208
+ Some(Self {
1209
+ message: e.to_string(),
1210
+ cause: cause.map(Box::new),
1211
+ ..Default::default()
1212
+ })
1213
+ })
1214
+ .unwrap_or_default()
1215
+ }
1216
+ }
1217
+ }
1218
+
1219
+ pub trait FromPayloadsExt {
1220
+ fn from_payloads(p: Option<Payloads>) -> Self;
1221
+ }
1222
+ impl<T> FromPayloadsExt for T
1223
+ where
1224
+ T: FromIterator<Payload>,
1225
+ {
1226
+ fn from_payloads(p: Option<Payloads>) -> Self {
1227
+ match p {
1228
+ None => std::iter::empty().collect(),
1229
+ Some(p) => p.payloads.into_iter().map(Into::into).collect(),
1230
+ }
1231
+ }
1232
+ }
1233
+
1234
+ pub trait IntoPayloadsExt {
1235
+ fn into_payloads(self) -> Option<Payloads>;
1236
+ }
1237
+ impl<T> IntoPayloadsExt for T
1238
+ where
1239
+ T: IntoIterator<Item = Payload>,
1240
+ {
1241
+ fn into_payloads(self) -> Option<Payloads> {
1242
+ let mut iterd = self.into_iter().peekable();
1243
+ if iterd.peek().is_none() {
1244
+ None
1245
+ } else {
1246
+ Some(Payloads {
1247
+ payloads: iterd.map(Into::into).collect(),
1248
+ })
1249
+ }
1250
+ }
1251
+ }
1252
+
1253
+ impl From<Payload> for Payloads {
1254
+ fn from(p: Payload) -> Self {
1255
+ Self { payloads: vec![p] }
1256
+ }
1257
+ }
1258
+
1259
+ impl<T> From<T> for Payloads
1260
+ where
1261
+ T: AsRef<[u8]>,
1262
+ {
1263
+ fn from(v: T) -> Self {
1264
+ Self {
1265
+ payloads: vec![v.into()],
1266
+ }
1267
+ }
1268
+ }
1269
+
1270
+ #[derive(thiserror::Error, Debug)]
1271
+ pub enum PayloadDeserializeErr {
1272
+ /// This deserializer does not handle this type of payload. Allows composing multiple
1273
+ /// deserializers.
1274
+ #[error("This deserializer does not understand this payload")]
1275
+ DeserializerDoesNotHandle,
1276
+ #[error("Error during deserialization: {0}")]
1277
+ DeserializeErr(#[from] anyhow::Error),
1278
+ }
1279
+
1280
+ // TODO: Once the prototype SDK is un-prototyped this serialization will need to be compat with
1281
+ // other SDKs (given they might execute an activity).
1282
+ pub trait AsJsonPayloadExt {
1283
+ fn as_json_payload(&self) -> anyhow::Result<Payload>;
1284
+ }
1285
+ impl<T> AsJsonPayloadExt for T
1286
+ where
1287
+ T: Serialize,
1288
+ {
1289
+ fn as_json_payload(&self) -> anyhow::Result<Payload> {
1290
+ let as_json = serde_json::to_string(self)?;
1291
+ let mut metadata = HashMap::new();
1292
+ metadata.insert("encoding".to_string(), b"json/plain".to_vec());
1293
+ Ok(Payload {
1294
+ metadata,
1295
+ data: as_json.into_bytes(),
1296
+ })
1297
+ }
1298
+ }
1299
+
1300
+ pub trait FromJsonPayloadExt: Sized {
1301
+ fn from_json_payload(payload: &Payload) -> Result<Self, PayloadDeserializeErr>;
1302
+ }
1303
+ impl<T> FromJsonPayloadExt for T
1304
+ where
1305
+ T: for<'de> Deserialize<'de>,
1306
+ {
1307
+ fn from_json_payload(payload: &Payload) -> Result<Self, PayloadDeserializeErr> {
1308
+ if !matches!(
1309
+ payload.metadata.get("encoding").map(|v| v.as_slice()),
1310
+ Some(b"json/plain")
1311
+ ) {
1312
+ return Err(PayloadDeserializeErr::DeserializerDoesNotHandle);
1313
+ }
1314
+ let payload_str = std::str::from_utf8(&payload.data).map_err(anyhow::Error::from)?;
1315
+ Ok(serde_json::from_str(payload_str).map_err(anyhow::Error::from)?)
1316
+ }
1317
+ }
1318
+
1319
+ /// Errors when converting from a [Payloads] api proto to our internal [Payload]
1320
+ #[derive(derive_more::Display, Debug)]
1321
+ pub enum PayloadsToPayloadError {
1322
+ MoreThanOnePayload,
1323
+ NoPayload,
1324
+ }
1325
+ impl TryFrom<Payloads> for Payload {
1326
+ type Error = PayloadsToPayloadError;
1327
+
1328
+ fn try_from(mut v: Payloads) -> Result<Self, Self::Error> {
1329
+ match v.payloads.pop() {
1330
+ None => Err(PayloadsToPayloadError::NoPayload),
1331
+ Some(p) => {
1332
+ if v.payloads.is_empty() {
1333
+ Ok(p)
1334
+ } else {
1335
+ Err(PayloadsToPayloadError::MoreThanOnePayload)
1336
+ }
1337
+ }
1338
+ }
1339
+ }
1340
+ }
1341
+ }
1342
+
1343
+ // No need to lint these
1344
+ #[allow(
1345
+ clippy::all,
1346
+ missing_docs,
1347
+ rustdoc::broken_intra_doc_links,
1348
+ rustdoc::bare_urls
1349
+ )]
1350
+ // This is disgusting, but unclear to me how to avoid it. TODO: Discuss w/ prost maintainer
1351
+ pub mod temporal {
1352
+ pub mod api {
1353
+ pub mod batch {
1354
+ pub mod v1 {
1355
+ tonic::include_proto!("temporal.api.batch.v1");
1356
+ }
1357
+ }
1358
+ pub mod command {
1359
+ pub mod v1 {
1360
+ tonic::include_proto!("temporal.api.command.v1");
1361
+
1362
+ use crate::{
1363
+ coresdk::{workflow_commands, IntoPayloadsExt},
1364
+ temporal::api::{
1365
+ common::v1::{ActivityType, WorkflowType},
1366
+ enums::v1::CommandType,
1367
+ },
1368
+ };
1369
+ use command::Attributes;
1370
+ use std::fmt::{Display, Formatter};
1371
+
1372
+ impl From<command::Attributes> for Command {
1373
+ fn from(c: command::Attributes) -> Self {
1374
+ match c {
1375
+ a @ Attributes::StartTimerCommandAttributes(_) => Self {
1376
+ command_type: CommandType::StartTimer as i32,
1377
+ attributes: Some(a),
1378
+ },
1379
+ a @ Attributes::CancelTimerCommandAttributes(_) => Self {
1380
+ command_type: CommandType::CancelTimer as i32,
1381
+ attributes: Some(a),
1382
+ },
1383
+ a @ Attributes::CompleteWorkflowExecutionCommandAttributes(_) => Self {
1384
+ command_type: CommandType::CompleteWorkflowExecution as i32,
1385
+ attributes: Some(a),
1386
+ },
1387
+ a @ Attributes::FailWorkflowExecutionCommandAttributes(_) => Self {
1388
+ command_type: CommandType::FailWorkflowExecution as i32,
1389
+ attributes: Some(a),
1390
+ },
1391
+ a @ Attributes::ScheduleActivityTaskCommandAttributes(_) => Self {
1392
+ command_type: CommandType::ScheduleActivityTask as i32,
1393
+ attributes: Some(a),
1394
+ },
1395
+ a @ Attributes::RequestCancelActivityTaskCommandAttributes(_) => Self {
1396
+ command_type: CommandType::RequestCancelActivityTask as i32,
1397
+ attributes: Some(a),
1398
+ },
1399
+ a @ Attributes::ContinueAsNewWorkflowExecutionCommandAttributes(_) => {
1400
+ Self {
1401
+ command_type: CommandType::ContinueAsNewWorkflowExecution
1402
+ as i32,
1403
+ attributes: Some(a),
1404
+ }
1405
+ }
1406
+ a @ Attributes::CancelWorkflowExecutionCommandAttributes(_) => Self {
1407
+ command_type: CommandType::CancelWorkflowExecution as i32,
1408
+ attributes: Some(a),
1409
+ },
1410
+ _ => unimplemented!(),
1411
+ }
1412
+ }
1413
+ }
1414
+
1415
+ impl Display for Command {
1416
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1417
+ let ct = CommandType::from_i32(self.command_type)
1418
+ .unwrap_or(CommandType::Unspecified);
1419
+ write!(f, "{:?}", ct)
1420
+ }
1421
+ }
1422
+
1423
+ impl From<workflow_commands::StartTimer> for command::Attributes {
1424
+ fn from(s: workflow_commands::StartTimer) -> Self {
1425
+ Self::StartTimerCommandAttributes(StartTimerCommandAttributes {
1426
+ timer_id: s.seq.to_string(),
1427
+ start_to_fire_timeout: s.start_to_fire_timeout,
1428
+ })
1429
+ }
1430
+ }
1431
+
1432
+ impl From<workflow_commands::UpsertWorkflowSearchAttributes> for command::Attributes {
1433
+ fn from(s: workflow_commands::UpsertWorkflowSearchAttributes) -> Self {
1434
+ Self::UpsertWorkflowSearchAttributesCommandAttributes(
1435
+ UpsertWorkflowSearchAttributesCommandAttributes {
1436
+ search_attributes: Some(s.search_attributes.into()),
1437
+ },
1438
+ )
1439
+ }
1440
+ }
1441
+
1442
+ impl From<workflow_commands::ModifyWorkflowProperties> for command::Attributes {
1443
+ fn from(s: workflow_commands::ModifyWorkflowProperties) -> Self {
1444
+ Self::ModifyWorkflowPropertiesCommandAttributes(
1445
+ ModifyWorkflowPropertiesCommandAttributes {
1446
+ upserted_memo: s.upserted_memo.map(Into::into),
1447
+ },
1448
+ )
1449
+ }
1450
+ }
1451
+
1452
+ impl From<workflow_commands::CancelTimer> for command::Attributes {
1453
+ fn from(s: workflow_commands::CancelTimer) -> Self {
1454
+ Self::CancelTimerCommandAttributes(CancelTimerCommandAttributes {
1455
+ timer_id: s.seq.to_string(),
1456
+ })
1457
+ }
1458
+ }
1459
+
1460
+ impl From<workflow_commands::ScheduleActivity> for command::Attributes {
1461
+ fn from(s: workflow_commands::ScheduleActivity) -> Self {
1462
+ Self::ScheduleActivityTaskCommandAttributes(
1463
+ ScheduleActivityTaskCommandAttributes {
1464
+ activity_id: s.activity_id,
1465
+ activity_type: Some(ActivityType {
1466
+ name: s.activity_type,
1467
+ }),
1468
+ task_queue: Some(s.task_queue.into()),
1469
+ header: Some(s.headers.into()),
1470
+ input: s.arguments.into_payloads(),
1471
+ schedule_to_close_timeout: s.schedule_to_close_timeout,
1472
+ schedule_to_start_timeout: s.schedule_to_start_timeout,
1473
+ start_to_close_timeout: s.start_to_close_timeout,
1474
+ heartbeat_timeout: s.heartbeat_timeout,
1475
+ retry_policy: s.retry_policy.map(Into::into),
1476
+ request_eager_execution: !s.do_not_eagerly_execute,
1477
+ },
1478
+ )
1479
+ }
1480
+ }
1481
+
1482
+ impl From<workflow_commands::StartChildWorkflowExecution> for command::Attributes {
1483
+ fn from(s: workflow_commands::StartChildWorkflowExecution) -> Self {
1484
+ Self::StartChildWorkflowExecutionCommandAttributes(
1485
+ StartChildWorkflowExecutionCommandAttributes {
1486
+ workflow_id: s.workflow_id,
1487
+ workflow_type: Some(WorkflowType {
1488
+ name: s.workflow_type,
1489
+ }),
1490
+ control: "".into(),
1491
+ namespace: s.namespace,
1492
+ task_queue: Some(s.task_queue.into()),
1493
+ header: Some(s.headers.into()),
1494
+ memo: Some(s.memo.into()),
1495
+ search_attributes: Some(s.search_attributes.into()),
1496
+ input: s.input.into_payloads(),
1497
+ workflow_id_reuse_policy: s.workflow_id_reuse_policy,
1498
+ workflow_execution_timeout: s.workflow_execution_timeout,
1499
+ workflow_run_timeout: s.workflow_run_timeout,
1500
+ workflow_task_timeout: s.workflow_task_timeout,
1501
+ retry_policy: s.retry_policy.map(Into::into),
1502
+ cron_schedule: s.cron_schedule.clone(),
1503
+ parent_close_policy: s.parent_close_policy,
1504
+ },
1505
+ )
1506
+ }
1507
+ }
1508
+
1509
+ impl From<workflow_commands::CompleteWorkflowExecution> for command::Attributes {
1510
+ fn from(c: workflow_commands::CompleteWorkflowExecution) -> Self {
1511
+ Self::CompleteWorkflowExecutionCommandAttributes(
1512
+ CompleteWorkflowExecutionCommandAttributes {
1513
+ result: c.result.map(Into::into),
1514
+ },
1515
+ )
1516
+ }
1517
+ }
1518
+
1519
+ impl From<workflow_commands::FailWorkflowExecution> for command::Attributes {
1520
+ fn from(c: workflow_commands::FailWorkflowExecution) -> Self {
1521
+ Self::FailWorkflowExecutionCommandAttributes(
1522
+ FailWorkflowExecutionCommandAttributes {
1523
+ failure: c.failure.map(Into::into),
1524
+ },
1525
+ )
1526
+ }
1527
+ }
1528
+
1529
+ impl From<workflow_commands::ContinueAsNewWorkflowExecution> for command::Attributes {
1530
+ fn from(c: workflow_commands::ContinueAsNewWorkflowExecution) -> Self {
1531
+ Self::ContinueAsNewWorkflowExecutionCommandAttributes(
1532
+ ContinueAsNewWorkflowExecutionCommandAttributes {
1533
+ workflow_type: Some(c.workflow_type.into()),
1534
+ task_queue: Some(c.task_queue.into()),
1535
+ input: c.arguments.into_payloads(),
1536
+ workflow_run_timeout: c.workflow_run_timeout,
1537
+ workflow_task_timeout: c.workflow_task_timeout,
1538
+ memo: if c.memo.is_empty() {
1539
+ None
1540
+ } else {
1541
+ Some(c.memo.into())
1542
+ },
1543
+ header: if c.headers.is_empty() {
1544
+ None
1545
+ } else {
1546
+ Some(c.headers.into())
1547
+ },
1548
+ retry_policy: c.retry_policy,
1549
+ search_attributes: if c.search_attributes.is_empty() {
1550
+ None
1551
+ } else {
1552
+ Some(c.search_attributes.into())
1553
+ },
1554
+ ..Default::default()
1555
+ },
1556
+ )
1557
+ }
1558
+ }
1559
+
1560
+ impl From<workflow_commands::CancelWorkflowExecution> for command::Attributes {
1561
+ fn from(_c: workflow_commands::CancelWorkflowExecution) -> Self {
1562
+ Self::CancelWorkflowExecutionCommandAttributes(
1563
+ CancelWorkflowExecutionCommandAttributes { details: None },
1564
+ )
1565
+ }
1566
+ }
1567
+ }
1568
+ }
1569
+ pub mod common {
1570
+ pub mod v1 {
1571
+ use std::{
1572
+ collections::HashMap,
1573
+ fmt::{Display, Formatter},
1574
+ };
1575
+ tonic::include_proto!("temporal.api.common.v1");
1576
+
1577
+ impl<T> From<T> for Payload
1578
+ where
1579
+ T: AsRef<[u8]>,
1580
+ {
1581
+ fn from(v: T) -> Self {
1582
+ // TODO: Set better encodings, whole data converter deal. Setting anything
1583
+ // for now at least makes it show up in the web UI.
1584
+ let mut metadata = HashMap::new();
1585
+ metadata.insert("encoding".to_string(), b"binary/plain".to_vec());
1586
+ Self {
1587
+ metadata,
1588
+ data: v.as_ref().to_vec(),
1589
+ }
1590
+ }
1591
+ }
1592
+
1593
+ impl Payload {
1594
+ // Is its own function b/c asref causes implementation conflicts
1595
+ pub fn as_slice(&self) -> &[u8] {
1596
+ self.data.as_slice()
1597
+ }
1598
+ }
1599
+
1600
+ impl Display for Payload {
1601
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1602
+ if self.data.len() > 64 {
1603
+ let mut windows = self.data.as_slice().windows(32);
1604
+ write!(
1605
+ f,
1606
+ "[{}..{}]",
1607
+ base64::encode(windows.next().unwrap_or_default()),
1608
+ base64::encode(windows.next_back().unwrap_or_default())
1609
+ )
1610
+ } else {
1611
+ write!(f, "[{}]", base64::encode(&self.data))
1612
+ }
1613
+ }
1614
+ }
1615
+
1616
+ impl Display for Header {
1617
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1618
+ write!(f, "Header(")?;
1619
+ for kv in &self.fields {
1620
+ write!(f, "{}: ", kv.0)?;
1621
+ write!(f, "{}, ", kv.1)?;
1622
+ }
1623
+ write!(f, ")")
1624
+ }
1625
+ }
1626
+
1627
+ impl From<Header> for HashMap<String, Payload> {
1628
+ fn from(h: Header) -> Self {
1629
+ h.fields.into_iter().map(|(k, v)| (k, v.into())).collect()
1630
+ }
1631
+ }
1632
+
1633
+ impl From<Memo> for HashMap<String, Payload> {
1634
+ fn from(h: Memo) -> Self {
1635
+ h.fields.into_iter().map(|(k, v)| (k, v.into())).collect()
1636
+ }
1637
+ }
1638
+
1639
+ impl From<SearchAttributes> for HashMap<String, Payload> {
1640
+ fn from(h: SearchAttributes) -> Self {
1641
+ h.indexed_fields
1642
+ .into_iter()
1643
+ .map(|(k, v)| (k, v.into()))
1644
+ .collect()
1645
+ }
1646
+ }
1647
+
1648
+ impl From<HashMap<String, Payload>> for SearchAttributes {
1649
+ fn from(h: HashMap<String, Payload>) -> Self {
1650
+ Self {
1651
+ indexed_fields: h.into_iter().map(|(k, v)| (k, v.into())).collect(),
1652
+ }
1653
+ }
1654
+ }
1655
+ }
1656
+ }
1657
+ pub mod enums {
1658
+ pub mod v1 {
1659
+ tonic::include_proto!("temporal.api.enums.v1");
1660
+ }
1661
+ }
1662
+ pub mod failure {
1663
+ pub mod v1 {
1664
+ tonic::include_proto!("temporal.api.failure.v1");
1665
+ }
1666
+ }
1667
+ pub mod filter {
1668
+ pub mod v1 {
1669
+ tonic::include_proto!("temporal.api.filter.v1");
1670
+ }
1671
+ }
1672
+ pub mod history {
1673
+ pub mod v1 {
1674
+ use crate::temporal::api::{
1675
+ enums::v1::EventType, history::v1::history_event::Attributes,
1676
+ };
1677
+ use anyhow::bail;
1678
+ use prost::alloc::fmt::Formatter;
1679
+ use std::fmt::Display;
1680
+
1681
+ tonic::include_proto!("temporal.api.history.v1");
1682
+
1683
+ impl History {
1684
+ pub fn extract_run_id_from_start(&self) -> Result<&str, anyhow::Error> {
1685
+ extract_original_run_id_from_events(&self.events)
1686
+ }
1687
+
1688
+ /// Returns the event id of the final event in the history. Will return 0 if
1689
+ /// there are no events.
1690
+ pub fn last_event_id(&self) -> i64 {
1691
+ self.events.last().map(|e| e.event_id).unwrap_or_default()
1692
+ }
1693
+ }
1694
+
1695
+ pub fn extract_original_run_id_from_events(
1696
+ events: &[HistoryEvent],
1697
+ ) -> Result<&str, anyhow::Error> {
1698
+ if let Some(Attributes::WorkflowExecutionStartedEventAttributes(wes)) =
1699
+ events.get(0).and_then(|x| x.attributes.as_ref())
1700
+ {
1701
+ Ok(&wes.original_execution_run_id)
1702
+ } else {
1703
+ bail!("First event is not WorkflowExecutionStarted?!?")
1704
+ }
1705
+ }
1706
+
1707
+ impl HistoryEvent {
1708
+ /// Returns true if this is an event created to mirror a command
1709
+ pub fn is_command_event(&self) -> bool {
1710
+ EventType::from_i32(self.event_type).map_or(false, |et| match et {
1711
+ EventType::ActivityTaskScheduled
1712
+ | EventType::ActivityTaskCancelRequested
1713
+ | EventType::MarkerRecorded
1714
+ | EventType::RequestCancelExternalWorkflowExecutionInitiated
1715
+ | EventType::SignalExternalWorkflowExecutionInitiated
1716
+ | EventType::StartChildWorkflowExecutionInitiated
1717
+ | EventType::TimerCanceled
1718
+ | EventType::TimerStarted
1719
+ | EventType::UpsertWorkflowSearchAttributes
1720
+ | EventType::WorkflowExecutionCanceled
1721
+ | EventType::WorkflowExecutionCompleted
1722
+ | EventType::WorkflowExecutionContinuedAsNew
1723
+ | EventType::WorkflowExecutionFailed => true,
1724
+ _ => false,
1725
+ })
1726
+ }
1727
+
1728
+ /// Returns the command's initiating event id, if present. This is the id of the
1729
+ /// event which "started" the command. Usually, the "scheduled" event for the
1730
+ /// command.
1731
+ pub fn get_initial_command_event_id(&self) -> Option<i64> {
1732
+ self.attributes.as_ref().and_then(|a| {
1733
+ // Fun! Not really any way to make this better w/o incompatibly changing
1734
+ // protos.
1735
+ match a {
1736
+ Attributes::ActivityTaskStartedEventAttributes(a) =>
1737
+ Some(a.scheduled_event_id),
1738
+ Attributes::ActivityTaskCompletedEventAttributes(a) =>
1739
+ Some(a.scheduled_event_id),
1740
+ Attributes::ActivityTaskFailedEventAttributes(a) => Some(a.scheduled_event_id),
1741
+ Attributes::ActivityTaskTimedOutEventAttributes(a) => Some(a.scheduled_event_id),
1742
+ Attributes::ActivityTaskCancelRequestedEventAttributes(a) => Some(a.scheduled_event_id),
1743
+ Attributes::ActivityTaskCanceledEventAttributes(a) => Some(a.scheduled_event_id),
1744
+ Attributes::TimerFiredEventAttributes(a) => Some(a.started_event_id),
1745
+ Attributes::TimerCanceledEventAttributes(a) => Some(a.started_event_id),
1746
+ Attributes::RequestCancelExternalWorkflowExecutionFailedEventAttributes(a) => Some(a.initiated_event_id),
1747
+ Attributes::ExternalWorkflowExecutionCancelRequestedEventAttributes(a) => Some(a.initiated_event_id),
1748
+ Attributes::StartChildWorkflowExecutionFailedEventAttributes(a) => Some(a.initiated_event_id),
1749
+ Attributes::ChildWorkflowExecutionStartedEventAttributes(a) => Some(a.initiated_event_id),
1750
+ Attributes::ChildWorkflowExecutionCompletedEventAttributes(a) => Some(a.initiated_event_id),
1751
+ Attributes::ChildWorkflowExecutionFailedEventAttributes(a) => Some(a.initiated_event_id),
1752
+ Attributes::ChildWorkflowExecutionCanceledEventAttributes(a) => Some(a.initiated_event_id),
1753
+ Attributes::ChildWorkflowExecutionTimedOutEventAttributes(a) => Some(a.initiated_event_id),
1754
+ Attributes::ChildWorkflowExecutionTerminatedEventAttributes(a) => Some(a.initiated_event_id),
1755
+ Attributes::SignalExternalWorkflowExecutionFailedEventAttributes(a) => Some(a.initiated_event_id),
1756
+ Attributes::ExternalWorkflowExecutionSignaledEventAttributes(a) => Some(a.initiated_event_id),
1757
+ Attributes::WorkflowTaskStartedEventAttributes(a) => Some(a.scheduled_event_id),
1758
+ Attributes::WorkflowTaskCompletedEventAttributes(a) => Some(a.scheduled_event_id),
1759
+ Attributes::WorkflowTaskTimedOutEventAttributes(a) => Some(a.scheduled_event_id),
1760
+ Attributes::WorkflowTaskFailedEventAttributes(a) => Some(a.scheduled_event_id),
1761
+ _ => None
1762
+ }
1763
+ })
1764
+ }
1765
+
1766
+ /// Returns true if the event is one which would end a workflow
1767
+ pub fn is_final_wf_execution_event(&self) -> bool {
1768
+ match self.event_type() {
1769
+ EventType::WorkflowExecutionCompleted => true,
1770
+ EventType::WorkflowExecutionCanceled => true,
1771
+ EventType::WorkflowExecutionFailed => true,
1772
+ EventType::WorkflowExecutionTimedOut => true,
1773
+ EventType::WorkflowExecutionContinuedAsNew => true,
1774
+ EventType::WorkflowExecutionTerminated => true,
1775
+ _ => false,
1776
+ }
1777
+ }
1778
+ }
1779
+
1780
+ impl Display for HistoryEvent {
1781
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1782
+ write!(
1783
+ f,
1784
+ "HistoryEvent(id: {}, {:?})",
1785
+ self.event_id,
1786
+ EventType::from_i32(self.event_type)
1787
+ )
1788
+ }
1789
+ }
1790
+ }
1791
+ }
1792
+ pub mod interaction {
1793
+ pub mod v1 {
1794
+ tonic::include_proto!("temporal.api.interaction.v1");
1795
+ }
1796
+ }
1797
+ pub mod namespace {
1798
+ pub mod v1 {
1799
+ tonic::include_proto!("temporal.api.namespace.v1");
1800
+ }
1801
+ }
1802
+ pub mod operatorservice {
1803
+ pub mod v1 {
1804
+ tonic::include_proto!("temporal.api.operatorservice.v1");
1805
+ }
1806
+ }
1807
+ pub mod query {
1808
+ pub mod v1 {
1809
+ tonic::include_proto!("temporal.api.query.v1");
1810
+ }
1811
+ }
1812
+ pub mod replication {
1813
+ pub mod v1 {
1814
+ tonic::include_proto!("temporal.api.replication.v1");
1815
+ }
1816
+ }
1817
+ pub mod schedule {
1818
+ pub mod v1 {
1819
+ tonic::include_proto!("temporal.api.schedule.v1");
1820
+ }
1821
+ }
1822
+ pub mod taskqueue {
1823
+ pub mod v1 {
1824
+ use crate::temporal::api::enums::v1::TaskQueueKind;
1825
+ tonic::include_proto!("temporal.api.taskqueue.v1");
1826
+
1827
+ impl From<String> for TaskQueue {
1828
+ fn from(name: String) -> Self {
1829
+ Self {
1830
+ name,
1831
+ kind: TaskQueueKind::Normal as i32,
1832
+ }
1833
+ }
1834
+ }
1835
+ }
1836
+ }
1837
+ pub mod testservice {
1838
+ pub mod v1 {
1839
+ tonic::include_proto!("temporal.api.testservice.v1");
1840
+ }
1841
+ }
1842
+ pub mod version {
1843
+ pub mod v1 {
1844
+ tonic::include_proto!("temporal.api.version.v1");
1845
+ }
1846
+ }
1847
+ pub mod workflow {
1848
+ pub mod v1 {
1849
+ tonic::include_proto!("temporal.api.workflow.v1");
1850
+ }
1851
+ }
1852
+ pub mod workflowservice {
1853
+ pub mod v1 {
1854
+ use std::{
1855
+ convert::TryInto,
1856
+ fmt::{Display, Formatter},
1857
+ time::{Duration, SystemTime},
1858
+ };
1859
+
1860
+ tonic::include_proto!("temporal.api.workflowservice.v1");
1861
+
1862
+ macro_rules! sched_to_start_impl {
1863
+ ($sched_field:ident) => {
1864
+ /// Return the duration of the task schedule time (current attempt) to its
1865
+ /// start time if both are set and time went forward.
1866
+ pub fn sched_to_start(&self) -> Option<Duration> {
1867
+ if let Some((sch, st)) =
1868
+ self.$sched_field.clone().zip(self.started_time.clone())
1869
+ {
1870
+ let sch: Result<SystemTime, _> = sch.try_into();
1871
+ let st: Result<SystemTime, _> = st.try_into();
1872
+ if let (Ok(sch), Ok(st)) = (sch, st) {
1873
+ return st.duration_since(sch).ok();
1874
+ }
1875
+ }
1876
+ None
1877
+ }
1878
+ };
1879
+ }
1880
+
1881
+ impl PollWorkflowTaskQueueResponse {
1882
+ sched_to_start_impl!(scheduled_time);
1883
+ }
1884
+
1885
+ impl Display for PollWorkflowTaskQueueResponse {
1886
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1887
+ let last_event = self
1888
+ .history
1889
+ .as_ref()
1890
+ .and_then(|h| h.events.last().map(|he| he.event_id))
1891
+ .unwrap_or(0);
1892
+ write!(
1893
+ f,
1894
+ "PollWFTQResp(run_id: {}, attempt: {}, last_event: {})",
1895
+ self.workflow_execution
1896
+ .as_ref()
1897
+ .map_or("", |we| we.run_id.as_str()),
1898
+ self.attempt,
1899
+ last_event
1900
+ )
1901
+ }
1902
+ }
1903
+
1904
+ /// Can be used while debugging to avoid filling up a whole screen with poll resps
1905
+ pub struct CompactHist<'a>(pub &'a PollWorkflowTaskQueueResponse);
1906
+ impl Display for CompactHist<'_> {
1907
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1908
+ writeln!(
1909
+ f,
1910
+ "PollWorkflowTaskQueueResponse (prev_started: {}, started: {})",
1911
+ self.0.previous_started_event_id, self.0.started_event_id
1912
+ )?;
1913
+ if let Some(h) = self.0.history.as_ref() {
1914
+ for event in &h.events {
1915
+ writeln!(f, "{}", event)?;
1916
+ }
1917
+ }
1918
+ writeln!(f, "query: {:#?}", self.0.query)?;
1919
+ writeln!(f, "queries: {:#?}", self.0.queries)
1920
+ }
1921
+ }
1922
+
1923
+ impl PollActivityTaskQueueResponse {
1924
+ sched_to_start_impl!(current_attempt_scheduled_time);
1925
+ }
1926
+
1927
+ impl QueryWorkflowResponse {
1928
+ /// Unwrap a successful response as vec of payloads
1929
+ pub fn unwrap(self) -> Vec<crate::temporal::api::common::v1::Payload> {
1930
+ self.query_result.unwrap().payloads
1931
+ }
1932
+ }
1933
+ }
1934
+ }
1935
+ }
1936
+ }
1937
+
1938
+ #[allow(
1939
+ clippy::all,
1940
+ missing_docs,
1941
+ rustdoc::broken_intra_doc_links,
1942
+ rustdoc::bare_urls
1943
+ )]
1944
+ pub mod grpc {
1945
+ pub mod health {
1946
+ pub mod v1 {
1947
+ tonic::include_proto!("grpc.health.v1");
1948
+ }
1949
+ }
1950
+ }
1951
+
1952
+ #[cfg(test)]
1953
+ mod tests {
1954
+ use crate::temporal::api::failure::v1::Failure;
1955
+ use anyhow::anyhow;
1956
+
1957
+ #[test]
1958
+ fn anyhow_to_failure_conversion() {
1959
+ let no_causes: Failure = anyhow!("no causes").into();
1960
+ assert_eq!(no_causes.cause, None);
1961
+ assert_eq!(no_causes.message, "no causes");
1962
+ let orig = anyhow!("fail 1");
1963
+ let mid = orig.context("fail 2");
1964
+ let top = mid.context("fail 3");
1965
+ let as_fail: Failure = top.into();
1966
+ assert_eq!(as_fail.message, "fail 3");
1967
+ assert_eq!(as_fail.cause.as_ref().unwrap().message, "fail 2");
1968
+ assert_eq!(as_fail.cause.unwrap().cause.unwrap().message, "fail 1");
1969
+ }
1970
+ }