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,878 @@
1
+ use assert_matches::assert_matches;
2
+ use std::time::Duration;
3
+ use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowExecutionResult, WorkflowOptions};
4
+ use temporal_sdk::{
5
+ ActContext, ActExitValue, ActivityOptions, CancellableFuture, WfContext, WorkflowResult,
6
+ };
7
+ use temporal_sdk_core_protos::{
8
+ coresdk::{
9
+ activity_result::{
10
+ self, activity_resolution as act_res, ActivityExecutionResult, ActivityResolution,
11
+ },
12
+ activity_task::activity_task as act_task,
13
+ workflow_activation::{
14
+ workflow_activation_job, FireTimer, ResolveActivity, WorkflowActivationJob,
15
+ },
16
+ workflow_commands::{ActivityCancellationType, RequestCancelActivity, StartTimer},
17
+ workflow_completion::WorkflowActivationCompletion,
18
+ ActivityHeartbeat, ActivityTaskCompletion, AsJsonPayloadExt, FromJsonPayloadExt,
19
+ IntoCompletion,
20
+ },
21
+ temporal::api::{
22
+ common::v1::{ActivityType, Payload, Payloads},
23
+ enums::v1::RetryState,
24
+ failure::v1::{failure::FailureInfo, ActivityFailureInfo, Failure},
25
+ },
26
+ TaskToken,
27
+ };
28
+ use temporal_sdk_core_test_utils::{
29
+ init_core_and_create_wf, schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
30
+ };
31
+ use tokio::time::sleep;
32
+
33
+ pub async fn one_activity_wf(ctx: WfContext) -> WorkflowResult<()> {
34
+ ctx.activity(ActivityOptions {
35
+ activity_type: "echo_activity".to_string(),
36
+ start_to_close_timeout: Some(Duration::from_secs(5)),
37
+ input: "hi!".as_json_payload().expect("serializes fine"),
38
+ ..Default::default()
39
+ })
40
+ .await;
41
+ Ok(().into())
42
+ }
43
+
44
+ #[tokio::test]
45
+ async fn one_activity() {
46
+ let wf_name = "one_activity";
47
+ let mut starter = CoreWfStarter::new(wf_name);
48
+ let mut worker = starter.worker().await;
49
+ let client = starter.get_client().await;
50
+ worker.register_wf(wf_name.to_owned(), one_activity_wf);
51
+ worker.register_activity(
52
+ "echo_activity",
53
+ |_ctx: ActContext, echo_me: String| async move { Ok(echo_me) },
54
+ );
55
+
56
+ let run_id = worker
57
+ .submit_wf(
58
+ wf_name.to_owned(),
59
+ wf_name.to_owned(),
60
+ vec![],
61
+ WorkflowOptions::default(),
62
+ )
63
+ .await
64
+ .unwrap();
65
+ worker.run_until_done().await.unwrap();
66
+ let handle = client.get_untyped_workflow_handle(wf_name, run_id);
67
+ let res = handle
68
+ .get_workflow_result(Default::default())
69
+ .await
70
+ .unwrap();
71
+ assert_matches!(res, WorkflowExecutionResult::Succeeded(_));
72
+ }
73
+
74
+ #[tokio::test]
75
+ async fn activity_workflow() {
76
+ let mut starter = init_core_and_create_wf("activity_workflow").await;
77
+ let core = starter.get_worker().await;
78
+ let task_q = starter.get_task_queue();
79
+ let activity_id = "act-1";
80
+ let task = core.poll_workflow_activation().await.unwrap();
81
+ // Complete workflow task and schedule activity
82
+ core.complete_workflow_activation(
83
+ schedule_activity_cmd(
84
+ 0,
85
+ task_q,
86
+ activity_id,
87
+ ActivityCancellationType::TryCancel,
88
+ Duration::from_secs(60),
89
+ Duration::from_secs(60),
90
+ )
91
+ .into_completion(task.run_id),
92
+ )
93
+ .await
94
+ .unwrap();
95
+ // Poll activity and verify that it's been scheduled with correct parameters
96
+ let task = core.poll_activity_task().await.unwrap();
97
+ assert_matches!(
98
+ task.variant,
99
+ Some(act_task::Variant::Start(start_activity)) => {
100
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
101
+ }
102
+ );
103
+ let response_payload = Payload {
104
+ data: b"hello ".to_vec(),
105
+ metadata: Default::default(),
106
+ };
107
+ // Complete activity successfully.
108
+ core.complete_activity_task(ActivityTaskCompletion {
109
+ task_token: task.task_token,
110
+ result: Some(ActivityExecutionResult::ok(response_payload.clone())),
111
+ })
112
+ .await
113
+ .unwrap();
114
+ // Poll workflow task and verify that activity has succeeded.
115
+ let task = core.poll_workflow_activation().await.unwrap();
116
+ assert_matches!(
117
+ task.jobs.as_slice(),
118
+ [
119
+ WorkflowActivationJob {
120
+ variant: Some(workflow_activation_job::Variant::ResolveActivity(
121
+ ResolveActivity {seq, result: Some(ActivityResolution{
122
+ status: Some(
123
+ act_res::Status::Completed(activity_result::Success{result: Some(r)})),
124
+ ..
125
+ })}
126
+ )),
127
+ },
128
+ ] => {
129
+ assert_eq!(*seq, 0);
130
+ assert_eq!(r, &response_payload);
131
+ }
132
+ );
133
+ core.complete_execution(&task.run_id).await;
134
+ }
135
+
136
+ #[tokio::test]
137
+ async fn activity_non_retryable_failure() {
138
+ let mut starter = init_core_and_create_wf("activity_non_retryable_failure").await;
139
+ let core = starter.get_worker().await;
140
+ let task_q = starter.get_task_queue();
141
+ let activity_id = "act-1";
142
+ let task = core.poll_workflow_activation().await.unwrap();
143
+ // Complete workflow task and schedule activity
144
+ core.complete_workflow_activation(
145
+ schedule_activity_cmd(
146
+ 0,
147
+ task_q,
148
+ activity_id,
149
+ ActivityCancellationType::TryCancel,
150
+ Duration::from_secs(60),
151
+ Duration::from_secs(60),
152
+ )
153
+ .into_completion(task.run_id),
154
+ )
155
+ .await
156
+ .unwrap();
157
+ // Poll activity and verify that it's been scheduled with correct parameters
158
+ let task = core.poll_activity_task().await.unwrap();
159
+ assert_matches!(
160
+ task.variant,
161
+ Some(act_task::Variant::Start(start_activity)) => {
162
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
163
+ }
164
+ );
165
+ // Fail activity with non-retryable error
166
+ let failure = Failure::application_failure("activity failed".to_string(), true);
167
+ core.complete_activity_task(ActivityTaskCompletion {
168
+ task_token: task.task_token,
169
+ result: Some(ActivityExecutionResult::fail(failure.clone())),
170
+ })
171
+ .await
172
+ .unwrap();
173
+ // Poll workflow task and verify that activity has failed.
174
+ let task = core.poll_workflow_activation().await.unwrap();
175
+ assert_matches!(
176
+ task.jobs.as_slice(),
177
+ [
178
+ WorkflowActivationJob {
179
+ variant: Some(workflow_activation_job::Variant::ResolveActivity(
180
+ ResolveActivity {seq, result: Some(ActivityResolution{
181
+ status: Some(act_res::Status::Failed(activity_result::Failure{
182
+ failure: Some(f),
183
+ }))})}
184
+ )),
185
+ },
186
+ ] => {
187
+ assert_eq!(*seq, 0);
188
+ assert_eq!(f, &Failure{
189
+ message: "Activity task failed".to_owned(),
190
+ cause: Some(Box::new(failure)),
191
+ failure_info: Some(FailureInfo::ActivityFailureInfo(ActivityFailureInfo{
192
+ activity_id: "act-1".to_owned(),
193
+ activity_type: Some(ActivityType {
194
+ name: "test_activity".to_owned(),
195
+ }),
196
+ scheduled_event_id: 5,
197
+ started_event_id: 6,
198
+ identity: "integ_tester".to_owned(),
199
+ retry_state: RetryState::NonRetryableFailure as i32,
200
+ })),
201
+ ..Default::default()
202
+ });
203
+ }
204
+ );
205
+ core.complete_execution(&task.run_id).await;
206
+ }
207
+
208
+ #[tokio::test]
209
+ async fn activity_retry() {
210
+ let mut starter = init_core_and_create_wf("activity_retry").await;
211
+ let core = starter.get_worker().await;
212
+ let task_q = starter.get_task_queue();
213
+ let activity_id = "act-1";
214
+ let task = core.poll_workflow_activation().await.unwrap();
215
+ // Complete workflow task and schedule activity
216
+ core.complete_workflow_activation(
217
+ schedule_activity_cmd(
218
+ 0,
219
+ task_q,
220
+ activity_id,
221
+ ActivityCancellationType::TryCancel,
222
+ Duration::from_secs(60),
223
+ Duration::from_secs(60),
224
+ )
225
+ .into_completion(task.run_id),
226
+ )
227
+ .await
228
+ .unwrap();
229
+ // Poll activity 1st time
230
+ let task = core.poll_activity_task().await.unwrap();
231
+ assert_matches!(
232
+ task.variant,
233
+ Some(act_task::Variant::Start(start_activity)) => {
234
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
235
+ }
236
+ );
237
+ // Fail activity with retryable error
238
+ let failure = Failure::application_failure("activity failed".to_string(), false);
239
+ core.complete_activity_task(ActivityTaskCompletion {
240
+ task_token: task.task_token,
241
+ result: Some(ActivityExecutionResult::fail(failure)),
242
+ })
243
+ .await
244
+ .unwrap();
245
+ // Poll 2nd time
246
+ let task = core.poll_activity_task().await.unwrap();
247
+ assert_matches!(
248
+ task.variant,
249
+ Some(act_task::Variant::Start(start_activity)) => {
250
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
251
+ }
252
+ );
253
+ // Complete activity successfully
254
+ let response_payload = Payload {
255
+ data: b"hello ".to_vec(),
256
+ metadata: Default::default(),
257
+ };
258
+ core.complete_activity_task(ActivityTaskCompletion {
259
+ task_token: task.task_token,
260
+ result: Some(ActivityExecutionResult::ok(response_payload.clone())),
261
+ })
262
+ .await
263
+ .unwrap();
264
+ // Poll workflow task and verify activity has succeeded.
265
+ let task = core.poll_workflow_activation().await.unwrap();
266
+ assert_matches!(
267
+ task.jobs.as_slice(),
268
+ [
269
+ WorkflowActivationJob {
270
+ variant: Some(workflow_activation_job::Variant::ResolveActivity(
271
+ ResolveActivity {seq, result: Some(ActivityResolution{
272
+ status: Some(act_res::Status::Completed(activity_result::Success{result: Some(r)}))})}
273
+ )),
274
+ },
275
+ ] => {
276
+ assert_eq!(*seq, 0);
277
+ assert_eq!(r, &response_payload);
278
+ }
279
+ );
280
+ core.complete_execution(&task.run_id).await;
281
+ }
282
+
283
+ #[tokio::test]
284
+ async fn activity_cancellation_try_cancel() {
285
+ let mut starter = init_core_and_create_wf("activity_cancellation_try_cancel").await;
286
+ let core = starter.get_worker().await;
287
+ let task_q = starter.get_task_queue();
288
+ let activity_id = "act-1";
289
+ let task = core.poll_workflow_activation().await.unwrap();
290
+ // Complete workflow task and schedule activity and a timer that fires immediately
291
+ core.complete_workflow_activation(
292
+ vec![
293
+ schedule_activity_cmd(
294
+ 0,
295
+ task_q,
296
+ activity_id,
297
+ ActivityCancellationType::TryCancel,
298
+ Duration::from_secs(60),
299
+ Duration::from_secs(60),
300
+ ),
301
+ StartTimer {
302
+ seq: 1,
303
+ start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
304
+ }
305
+ .into(),
306
+ ]
307
+ .into_completion(task.run_id),
308
+ )
309
+ .await
310
+ .unwrap();
311
+ // Poll activity and verify that it's been scheduled with correct parameters, we don't expect to
312
+ // complete it in this test as activity is try-cancelled.
313
+ let activity_task = core.poll_activity_task().await.unwrap();
314
+ assert_matches!(
315
+ activity_task.variant,
316
+ Some(act_task::Variant::Start(start_activity)) => {
317
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
318
+ }
319
+ );
320
+ // Poll workflow task and verify that activity has failed.
321
+ let task = core.poll_workflow_activation().await.unwrap();
322
+ assert_matches!(
323
+ task.jobs.as_slice(),
324
+ [
325
+ WorkflowActivationJob {
326
+ variant: Some(workflow_activation_job::Variant::FireTimer(
327
+ FireTimer { seq }
328
+ )),
329
+ },
330
+ ] => {
331
+ assert_eq!(*seq, 1);
332
+ }
333
+ );
334
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
335
+ task.run_id,
336
+ vec![RequestCancelActivity { seq: 0 }.into()],
337
+ ))
338
+ .await
339
+ .unwrap();
340
+ let task = core.poll_workflow_activation().await.unwrap();
341
+ core.complete_execution(&task.run_id).await;
342
+ }
343
+
344
+ #[tokio::test]
345
+ async fn activity_cancellation_plus_complete_doesnt_double_resolve() {
346
+ let mut starter =
347
+ init_core_and_create_wf("activity_cancellation_plus_complete_doesnt_double_resolve").await;
348
+ let core = starter.get_worker().await;
349
+ let task_q = starter.get_task_queue();
350
+ let activity_id = "act-1";
351
+ let task = core.poll_workflow_activation().await.unwrap();
352
+ // Complete workflow task and schedule activity and a timer that fires immediately
353
+ core.complete_workflow_activation(
354
+ vec![
355
+ schedule_activity_cmd(
356
+ 0,
357
+ task_q,
358
+ activity_id,
359
+ ActivityCancellationType::TryCancel,
360
+ Duration::from_secs(60),
361
+ Duration::from_secs(60),
362
+ ),
363
+ StartTimer {
364
+ seq: 1,
365
+ start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
366
+ }
367
+ .into(),
368
+ ]
369
+ .into_completion(task.run_id),
370
+ )
371
+ .await
372
+ .unwrap();
373
+ let activity_task = core.poll_activity_task().await.unwrap();
374
+ assert_matches!(activity_task.variant, Some(act_task::Variant::Start(_)));
375
+ let task = core.poll_workflow_activation().await.unwrap();
376
+ assert_matches!(
377
+ task.jobs.as_slice(),
378
+ [WorkflowActivationJob {
379
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
380
+ }]
381
+ );
382
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
383
+ task.run_id,
384
+ vec![RequestCancelActivity { seq: 0 }.into()],
385
+ ))
386
+ .await
387
+ .unwrap();
388
+ let task = core.poll_workflow_activation().await.unwrap();
389
+ // Should get cancel task
390
+ assert_matches!(
391
+ task.jobs.as_slice(),
392
+ [WorkflowActivationJob {
393
+ variant: Some(workflow_activation_job::Variant::ResolveActivity(
394
+ ResolveActivity {
395
+ result: Some(ActivityResolution {
396
+ status: Some(act_res::Status::Cancelled(_))
397
+ }),
398
+ ..
399
+ }
400
+ )),
401
+ }]
402
+ );
403
+ // We need to complete the wf task to send the activity cancel command to the server, so start
404
+ // another short timer
405
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
406
+ task.run_id,
407
+ vec![StartTimer {
408
+ seq: 2,
409
+ start_to_fire_timeout: Some(prost_dur!(from_millis(100))),
410
+ }
411
+ .into()],
412
+ ))
413
+ .await
414
+ .unwrap();
415
+ // Now say the activity completes anyways
416
+ core.complete_activity_task(ActivityTaskCompletion {
417
+ task_token: activity_task.task_token,
418
+ result: Some(ActivityExecutionResult::ok([1].into())),
419
+ })
420
+ .await
421
+ .unwrap();
422
+ // Ensure we do not get a wakeup with the activity being resolved completed, and instead get
423
+ // the timer fired event (also wait for timer to fire)
424
+ sleep(Duration::from_secs(1)).await;
425
+ let task = core.poll_workflow_activation().await.unwrap();
426
+ assert_matches!(
427
+ task.jobs.as_slice(),
428
+ [WorkflowActivationJob {
429
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
430
+ }]
431
+ );
432
+ core.complete_execution(&task.run_id).await;
433
+ }
434
+
435
+ #[tokio::test]
436
+ async fn started_activity_timeout() {
437
+ let mut starter = init_core_and_create_wf("started_activity_timeout").await;
438
+ let core = starter.get_worker().await;
439
+ let task_q = starter.get_task_queue();
440
+ let activity_id = "act-1";
441
+ let task = core.poll_workflow_activation().await.unwrap();
442
+ // Complete workflow task and schedule activity that times out in 1 second.
443
+ core.complete_workflow_activation(
444
+ schedule_activity_cmd(
445
+ 0,
446
+ task_q,
447
+ activity_id,
448
+ ActivityCancellationType::TryCancel,
449
+ Duration::from_secs(1),
450
+ Duration::from_secs(60),
451
+ )
452
+ .into_completion(task.run_id),
453
+ )
454
+ .await
455
+ .unwrap();
456
+ // Poll activity and verify that it's been scheduled with correct parameters, we don't expect to
457
+ // complete it in this test as activity is timed out after 1 second.
458
+ let activity_task = core.poll_activity_task().await.unwrap();
459
+ assert_matches!(
460
+ activity_task.variant,
461
+ Some(act_task::Variant::Start(start_activity)) => {
462
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
463
+ }
464
+ );
465
+ let task = core.poll_workflow_activation().await.unwrap();
466
+ assert_matches!(
467
+ task.jobs.as_slice(),
468
+ [
469
+ WorkflowActivationJob {
470
+ variant: Some(workflow_activation_job::Variant::ResolveActivity(
471
+ ResolveActivity {
472
+ seq,
473
+ result: Some(ActivityResolution{
474
+ status: Some(
475
+ act_res::Status::Failed(
476
+ activity_result::Failure{failure: Some(_)}
477
+ )
478
+ ),
479
+ ..
480
+ })
481
+ }
482
+ )),
483
+ },
484
+ ] => {
485
+ assert_eq!(*seq, 0);
486
+ }
487
+ );
488
+ core.complete_execution(&task.run_id).await;
489
+ }
490
+
491
+ #[tokio::test]
492
+ async fn activity_cancellation_wait_cancellation_completed() {
493
+ let mut starter =
494
+ init_core_and_create_wf("activity_cancellation_wait_cancellation_completed").await;
495
+ let core = starter.get_worker().await;
496
+ let task_q = starter.get_task_queue();
497
+ let activity_id = "act-1";
498
+ let task = core.poll_workflow_activation().await.unwrap();
499
+ // Complete workflow task and schedule activity and a timer that fires immediately
500
+ core.complete_workflow_activation(
501
+ vec![
502
+ schedule_activity_cmd(
503
+ 0,
504
+ task_q,
505
+ activity_id,
506
+ ActivityCancellationType::WaitCancellationCompleted,
507
+ Duration::from_secs(60),
508
+ Duration::from_secs(60),
509
+ ),
510
+ StartTimer {
511
+ seq: 1,
512
+ start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
513
+ }
514
+ .into(),
515
+ ]
516
+ .into_completion(task.run_id),
517
+ )
518
+ .await
519
+ .unwrap();
520
+ // Poll activity and verify that it's been scheduled with correct parameters, we don't expect to
521
+ // complete it in this test as activity is wait-cancelled.
522
+ let activity_task = core.poll_activity_task().await.unwrap();
523
+ assert_matches!(
524
+ activity_task.variant,
525
+ Some(act_task::Variant::Start(start_activity)) => {
526
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
527
+ }
528
+ );
529
+ // Poll workflow task and verify that activity has failed.
530
+ let task = core.poll_workflow_activation().await.unwrap();
531
+ assert_matches!(
532
+ task.jobs.as_slice(),
533
+ [
534
+ WorkflowActivationJob {
535
+ variant: Some(workflow_activation_job::Variant::FireTimer(
536
+ FireTimer { seq }
537
+ )),
538
+ },
539
+ ] => {
540
+ assert_eq!(*seq, 1);
541
+ }
542
+ );
543
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
544
+ task.run_id,
545
+ vec![RequestCancelActivity { seq: 0 }.into()],
546
+ ))
547
+ .await
548
+ .unwrap();
549
+ core.complete_activity_task(ActivityTaskCompletion {
550
+ task_token: activity_task.task_token,
551
+ result: Some(ActivityExecutionResult::cancel_from_details(None)),
552
+ })
553
+ .await
554
+ .unwrap();
555
+ let task = core.poll_workflow_activation().await.unwrap();
556
+ core.complete_execution(&task.run_id).await;
557
+ }
558
+
559
+ #[tokio::test]
560
+ async fn activity_cancellation_abandon() {
561
+ let mut starter = init_core_and_create_wf("activity_cancellation_abandon").await;
562
+ let core = starter.get_worker().await;
563
+ let task_q = starter.get_task_queue();
564
+ let activity_id = "act-1";
565
+ let task = core.poll_workflow_activation().await.unwrap();
566
+ // Complete workflow task and schedule activity and a timer that fires immediately
567
+ core.complete_workflow_activation(
568
+ vec![
569
+ schedule_activity_cmd(
570
+ 0,
571
+ task_q,
572
+ activity_id,
573
+ ActivityCancellationType::Abandon,
574
+ Duration::from_secs(60),
575
+ Duration::from_secs(60),
576
+ ),
577
+ StartTimer {
578
+ seq: 1,
579
+ start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
580
+ }
581
+ .into(),
582
+ ]
583
+ .into_completion(task.run_id),
584
+ )
585
+ .await
586
+ .unwrap();
587
+ // Poll activity and verify that it's been scheduled with correct parameters, we don't expect to
588
+ // complete it in this test as activity is abandoned.
589
+ let activity_task = core.poll_activity_task().await.unwrap();
590
+ assert_matches!(
591
+ activity_task.variant,
592
+ Some(act_task::Variant::Start(start_activity)) => {
593
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
594
+ }
595
+ );
596
+ // Poll workflow task and verify that activity has failed.
597
+ let task = core.poll_workflow_activation().await.unwrap();
598
+ assert_matches!(
599
+ task.jobs.as_slice(),
600
+ [
601
+ WorkflowActivationJob {
602
+ variant: Some(workflow_activation_job::Variant::FireTimer(
603
+ FireTimer { seq }
604
+ )),
605
+ },
606
+ ] => {
607
+ assert_eq!(*seq, 1);
608
+ }
609
+ );
610
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
611
+ task.run_id,
612
+ vec![RequestCancelActivity { seq: 0 }.into()],
613
+ ))
614
+ .await
615
+ .unwrap();
616
+ // Poll workflow task expecting that activation has been created by the state machine
617
+ // immediately after the cancellation request.
618
+ let task = core.poll_workflow_activation().await.unwrap();
619
+ core.complete_execution(&task.run_id).await;
620
+ }
621
+
622
+ #[tokio::test]
623
+ async fn async_activity_completion_workflow() {
624
+ let mut starter = init_core_and_create_wf("async_activity_workflow").await;
625
+ let core = starter.get_worker().await;
626
+ let task_q = starter.get_task_queue();
627
+ let activity_id = "act-1";
628
+ let task = core.poll_workflow_activation().await.unwrap();
629
+ // Complete workflow task and schedule activity
630
+ core.complete_workflow_activation(
631
+ schedule_activity_cmd(
632
+ 0,
633
+ task_q,
634
+ activity_id,
635
+ ActivityCancellationType::TryCancel,
636
+ Duration::from_secs(60),
637
+ Duration::from_secs(60),
638
+ )
639
+ .into_completion(task.run_id),
640
+ )
641
+ .await
642
+ .unwrap();
643
+ // Poll activity and verify that it's been scheduled with correct parameters
644
+ let task = core.poll_activity_task().await.unwrap();
645
+ assert_matches!(
646
+ task.variant,
647
+ Some(act_task::Variant::Start(start_activity)) => {
648
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
649
+ }
650
+ );
651
+ let response_payload = Payload {
652
+ data: b"hello ".to_vec(),
653
+ metadata: Default::default(),
654
+ };
655
+ // Complete activity asynchronously.
656
+ core.complete_activity_task(ActivityTaskCompletion {
657
+ task_token: task.task_token.clone(),
658
+ result: Some(ActivityExecutionResult::will_complete_async()),
659
+ })
660
+ .await
661
+ .unwrap();
662
+ starter
663
+ .get_client()
664
+ .await
665
+ .complete_activity_task(
666
+ task.task_token.into(),
667
+ Some(Payloads {
668
+ payloads: vec![response_payload.clone()],
669
+ }),
670
+ )
671
+ .await
672
+ .unwrap();
673
+
674
+ // Poll workflow task and verify that activity has succeeded.
675
+ let task = core.poll_workflow_activation().await.unwrap();
676
+ assert_matches!(
677
+ task.jobs.as_slice(),
678
+ [
679
+ WorkflowActivationJob {
680
+ variant: Some(workflow_activation_job::Variant::ResolveActivity(
681
+ ResolveActivity {seq, result: Some(ActivityResolution {
682
+ status: Some(act_res::Status::Completed(activity_result::Success{result: Some(r)})),
683
+ ..})}
684
+ )),
685
+ },
686
+ ] => {
687
+ assert_eq!(*seq, 0);
688
+ assert_eq!(r, &response_payload);
689
+ }
690
+ );
691
+ core.complete_execution(&task.run_id).await;
692
+ }
693
+
694
+ #[tokio::test]
695
+ async fn activity_cancelled_after_heartbeat_times_out() {
696
+ let mut starter = init_core_and_create_wf("activity_cancelled_after_heartbeat_times_out").await;
697
+ let core = starter.get_worker().await;
698
+ let task_q = starter.get_task_queue().to_string();
699
+ let activity_id = "act-1";
700
+ let task = core.poll_workflow_activation().await.unwrap();
701
+ // Complete workflow task and schedule activity
702
+ core.complete_workflow_activation(
703
+ schedule_activity_cmd(
704
+ 0,
705
+ &task_q,
706
+ activity_id,
707
+ ActivityCancellationType::WaitCancellationCompleted,
708
+ Duration::from_secs(60),
709
+ Duration::from_secs(1),
710
+ )
711
+ .into_completion(task.run_id),
712
+ )
713
+ .await
714
+ .unwrap();
715
+ // Poll activity and verify that it's been scheduled with correct parameters
716
+ let task = core.poll_activity_task().await.unwrap();
717
+ assert_matches!(
718
+ task.variant,
719
+ Some(act_task::Variant::Start(start_activity)) => {
720
+ assert_eq!(start_activity.activity_type, "test_activity".to_string())
721
+ }
722
+ );
723
+ // Delay the heartbeat
724
+ sleep(Duration::from_secs(2)).await;
725
+ core.record_activity_heartbeat(ActivityHeartbeat {
726
+ task_token: task.task_token.clone(),
727
+ details: vec![],
728
+ });
729
+
730
+ // Verify activity got cancelled
731
+ let cancel_task = core.poll_activity_task().await.unwrap();
732
+ assert_eq!(cancel_task.task_token, task.task_token.clone());
733
+ assert_matches!(cancel_task.variant, Some(act_task::Variant::Cancel(_)));
734
+
735
+ // Complete activity with cancelled result
736
+ core.complete_activity_task(ActivityTaskCompletion {
737
+ task_token: task.task_token.clone(),
738
+ result: Some(ActivityExecutionResult::cancel_from_details(None)),
739
+ })
740
+ .await
741
+ .unwrap();
742
+
743
+ // Verify shutdown completes
744
+ core.shutdown().await;
745
+ // Cleanup just in case
746
+ starter
747
+ .get_client()
748
+ .await
749
+ .terminate_workflow_execution(task_q.clone(), None)
750
+ .await
751
+ .unwrap();
752
+ }
753
+
754
+ #[tokio::test]
755
+ async fn one_activity_abandon_cancelled_after_complete() {
756
+ let wf_name = "one_activity_abandon_cancelled_after_complete";
757
+ let mut starter = CoreWfStarter::new(wf_name);
758
+ let mut worker = starter.worker().await;
759
+ let client = starter.get_client().await;
760
+ worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
761
+ let act_fut = ctx.activity(ActivityOptions {
762
+ activity_type: "echo_activity".to_string(),
763
+ start_to_close_timeout: Some(Duration::from_secs(5)),
764
+ input: "hi!".as_json_payload().expect("serializes fine"),
765
+ cancellation_type: ActivityCancellationType::Abandon,
766
+ ..Default::default()
767
+ });
768
+ ctx.timer(Duration::from_secs(1)).await;
769
+ act_fut.cancel(&ctx);
770
+ ctx.timer(Duration::from_secs(3)).await;
771
+ act_fut.await;
772
+ Ok(().into())
773
+ });
774
+ worker.register_activity(
775
+ "echo_activity",
776
+ |_ctx: ActContext, echo_me: String| async move {
777
+ sleep(Duration::from_secs(2)).await;
778
+ Ok(echo_me)
779
+ },
780
+ );
781
+
782
+ let run_id = worker
783
+ .submit_wf(
784
+ wf_name.to_owned(),
785
+ wf_name.to_owned(),
786
+ vec![],
787
+ WorkflowOptions::default(),
788
+ )
789
+ .await
790
+ .unwrap();
791
+ worker.run_until_done().await.unwrap();
792
+ let handle = client.get_untyped_workflow_handle(wf_name, run_id);
793
+ let res = handle
794
+ .get_workflow_result(Default::default())
795
+ .await
796
+ .unwrap();
797
+ assert_matches!(res, WorkflowExecutionResult::Succeeded(_));
798
+ }
799
+
800
+ #[tokio::test]
801
+ async fn it_can_complete_async() {
802
+ use std::sync::Arc;
803
+ use tokio::sync::Mutex;
804
+
805
+ let wf_name = "it_can_complete_async".to_owned();
806
+ let mut starter = CoreWfStarter::new(&wf_name);
807
+ let mut worker = starter.worker().await;
808
+ let client = starter.get_client().await;
809
+ let async_response = "agence";
810
+ let shared_token: Arc<Mutex<Option<Vec<u8>>>> = Arc::new(Mutex::new(None));
811
+ worker.register_wf(wf_name.clone(), move |ctx: WfContext| async move {
812
+ let activity_resolution = ctx
813
+ .activity(ActivityOptions {
814
+ activity_type: "complete_async_activity".to_string(),
815
+ input: "hi".as_json_payload().expect("serializes fine"),
816
+ start_to_close_timeout: Some(Duration::from_secs(30)),
817
+ ..Default::default()
818
+ })
819
+ .await;
820
+
821
+ let res = match activity_resolution.status {
822
+ Some(act_res::Status::Completed(activity_result::Success { result })) => result
823
+ .map(|p| String::from_json_payload(&p).unwrap())
824
+ .unwrap(),
825
+ _ => panic!("activity task failed {:?}", activity_resolution),
826
+ };
827
+
828
+ assert_eq!(&res, async_response);
829
+ Ok(().into())
830
+ });
831
+
832
+ let shared_token_ref = shared_token.clone();
833
+ worker.register_activity(
834
+ "complete_async_activity",
835
+ move |ctx: ActContext, _: String| {
836
+ let shared_token_ref = shared_token_ref.clone();
837
+ async move {
838
+ // set the `activity_task_token`
839
+ let activity_info = ctx.get_info();
840
+ let task_token = &activity_info.task_token;
841
+ let mut shared = shared_token_ref.lock().await;
842
+ *shared = Some(task_token.clone());
843
+ Ok::<ActExitValue<()>, _>(ActExitValue::WillCompleteAsync)
844
+ }
845
+ },
846
+ );
847
+
848
+ let shared_token_ref2 = shared_token.clone();
849
+ tokio::spawn(async move {
850
+ loop {
851
+ let mut shared = shared_token_ref2.lock().await;
852
+ let maybe_token = shared.take();
853
+
854
+ if let Some(task_token) = maybe_token {
855
+ client
856
+ .complete_activity_task(
857
+ TaskToken(task_token),
858
+ Some(async_response.as_json_payload().unwrap().into()),
859
+ )
860
+ .await
861
+ .unwrap();
862
+ return;
863
+ }
864
+ }
865
+ });
866
+
867
+ let _run_id = worker
868
+ .submit_wf(
869
+ wf_name.to_owned(),
870
+ wf_name.to_owned(),
871
+ vec![],
872
+ WorkflowOptions::default(),
873
+ )
874
+ .await
875
+ .unwrap();
876
+
877
+ worker.run_until_done().await.unwrap();
878
+ }