temporalio 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (316) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +130 -0
  3. data/bridge/Cargo.lock +2865 -0
  4. data/bridge/Cargo.toml +26 -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 +107 -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/bridge-ffi/Cargo.toml +24 -0
  15. data/bridge/sdk-core/bridge-ffi/LICENSE.txt +23 -0
  16. data/bridge/sdk-core/bridge-ffi/build.rs +25 -0
  17. data/bridge/sdk-core/bridge-ffi/include/sdk-core-bridge.h +249 -0
  18. data/bridge/sdk-core/bridge-ffi/src/lib.rs +825 -0
  19. data/bridge/sdk-core/bridge-ffi/src/wrappers.rs +211 -0
  20. data/bridge/sdk-core/client/Cargo.toml +40 -0
  21. data/bridge/sdk-core/client/LICENSE.txt +23 -0
  22. data/bridge/sdk-core/client/src/lib.rs +1294 -0
  23. data/bridge/sdk-core/client/src/metrics.rs +165 -0
  24. data/bridge/sdk-core/client/src/raw.rs +931 -0
  25. data/bridge/sdk-core/client/src/retry.rs +674 -0
  26. data/bridge/sdk-core/client/src/workflow_handle/mod.rs +185 -0
  27. data/bridge/sdk-core/core/Cargo.toml +116 -0
  28. data/bridge/sdk-core/core/LICENSE.txt +23 -0
  29. data/bridge/sdk-core/core/benches/workflow_replay.rs +73 -0
  30. data/bridge/sdk-core/core/src/abstractions.rs +166 -0
  31. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +911 -0
  32. data/bridge/sdk-core/core/src/core_tests/child_workflows.rs +221 -0
  33. data/bridge/sdk-core/core/src/core_tests/determinism.rs +107 -0
  34. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +515 -0
  35. data/bridge/sdk-core/core/src/core_tests/mod.rs +100 -0
  36. data/bridge/sdk-core/core/src/core_tests/queries.rs +736 -0
  37. data/bridge/sdk-core/core/src/core_tests/replay_flag.rs +65 -0
  38. data/bridge/sdk-core/core/src/core_tests/workers.rs +259 -0
  39. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +124 -0
  40. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +2070 -0
  41. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +515 -0
  42. data/bridge/sdk-core/core/src/lib.rs +175 -0
  43. data/bridge/sdk-core/core/src/log_export.rs +62 -0
  44. data/bridge/sdk-core/core/src/pollers/mod.rs +54 -0
  45. data/bridge/sdk-core/core/src/pollers/poll_buffer.rs +297 -0
  46. data/bridge/sdk-core/core/src/protosext/mod.rs +428 -0
  47. data/bridge/sdk-core/core/src/replay/mod.rs +71 -0
  48. data/bridge/sdk-core/core/src/retry_logic.rs +202 -0
  49. data/bridge/sdk-core/core/src/telemetry/metrics.rs +383 -0
  50. data/bridge/sdk-core/core/src/telemetry/mod.rs +412 -0
  51. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +77 -0
  52. data/bridge/sdk-core/core/src/test_help/mod.rs +875 -0
  53. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +580 -0
  54. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +1042 -0
  55. data/bridge/sdk-core/core/src/worker/activities.rs +464 -0
  56. data/bridge/sdk-core/core/src/worker/client/mocks.rs +87 -0
  57. data/bridge/sdk-core/core/src/worker/client.rs +347 -0
  58. data/bridge/sdk-core/core/src/worker/mod.rs +566 -0
  59. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +37 -0
  60. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +110 -0
  61. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +458 -0
  62. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +911 -0
  63. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +298 -0
  64. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +171 -0
  65. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +860 -0
  66. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +140 -0
  67. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +161 -0
  68. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +133 -0
  69. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +1448 -0
  70. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +342 -0
  71. data/bridge/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +127 -0
  72. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +712 -0
  73. data/bridge/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +71 -0
  74. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +443 -0
  75. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +439 -0
  76. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +169 -0
  77. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +246 -0
  78. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +96 -0
  79. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +1184 -0
  80. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +277 -0
  81. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +198 -0
  82. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +647 -0
  83. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +1143 -0
  84. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +145 -0
  85. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +88 -0
  86. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +940 -0
  87. data/bridge/sdk-core/core-api/Cargo.toml +31 -0
  88. data/bridge/sdk-core/core-api/LICENSE.txt +23 -0
  89. data/bridge/sdk-core/core-api/src/errors.rs +95 -0
  90. data/bridge/sdk-core/core-api/src/lib.rs +151 -0
  91. data/bridge/sdk-core/core-api/src/worker.rs +135 -0
  92. data/bridge/sdk-core/etc/deps.svg +187 -0
  93. data/bridge/sdk-core/etc/dynamic-config.yaml +2 -0
  94. data/bridge/sdk-core/etc/otel-collector-config.yaml +36 -0
  95. data/bridge/sdk-core/etc/prometheus.yaml +6 -0
  96. data/bridge/sdk-core/fsm/Cargo.toml +18 -0
  97. data/bridge/sdk-core/fsm/LICENSE.txt +23 -0
  98. data/bridge/sdk-core/fsm/README.md +3 -0
  99. data/bridge/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +27 -0
  100. data/bridge/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +23 -0
  101. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +647 -0
  102. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +8 -0
  103. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.rs +18 -0
  104. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +12 -0
  105. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dynamic_dest_pass.rs +41 -0
  106. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.rs +14 -0
  107. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.stderr +11 -0
  108. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_arg_pass.rs +32 -0
  109. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_pass.rs +31 -0
  110. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/medium_complex_pass.rs +46 -0
  111. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.rs +29 -0
  112. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +12 -0
  113. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/simple_pass.rs +32 -0
  114. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.rs +18 -0
  115. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +5 -0
  116. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.rs +11 -0
  117. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +5 -0
  118. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.rs +11 -0
  119. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +5 -0
  120. data/bridge/sdk-core/fsm/rustfsm_trait/Cargo.toml +14 -0
  121. data/bridge/sdk-core/fsm/rustfsm_trait/LICENSE.txt +23 -0
  122. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +249 -0
  123. data/bridge/sdk-core/fsm/src/lib.rs +2 -0
  124. data/bridge/sdk-core/histories/fail_wf_task.bin +0 -0
  125. data/bridge/sdk-core/histories/timer_workflow_history.bin +0 -0
  126. data/bridge/sdk-core/integ-with-otel.sh +7 -0
  127. data/bridge/sdk-core/protos/api_upstream/README.md +9 -0
  128. data/bridge/sdk-core/protos/api_upstream/api-linter.yaml +40 -0
  129. data/bridge/sdk-core/protos/api_upstream/buf.yaml +12 -0
  130. data/bridge/sdk-core/protos/api_upstream/dependencies/gogoproto/gogo.proto +141 -0
  131. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +86 -0
  132. data/bridge/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +83 -0
  133. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +259 -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 +46 -0
  136. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/cluster.proto +40 -0
  137. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +57 -0
  138. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +55 -0
  139. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +168 -0
  140. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +97 -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 +51 -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 +751 -0
  152. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +97 -0
  153. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +161 -0
  154. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +99 -0
  155. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +61 -0
  156. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +55 -0
  157. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +300 -0
  158. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +108 -0
  159. data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +46 -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 +145 -0
  162. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +1124 -0
  163. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +401 -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/bridge/bridge.proto +210 -0
  168. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +77 -0
  169. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +15 -0
  170. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +30 -0
  171. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
  172. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +261 -0
  173. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +297 -0
  174. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +29 -0
  175. data/bridge/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
  176. data/bridge/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
  177. data/bridge/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
  178. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
  179. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
  180. data/bridge/sdk-core/rustfmt.toml +1 -0
  181. data/bridge/sdk-core/sdk/Cargo.toml +47 -0
  182. data/bridge/sdk-core/sdk/LICENSE.txt +23 -0
  183. data/bridge/sdk-core/sdk/src/activity_context.rs +230 -0
  184. data/bridge/sdk-core/sdk/src/app_data.rs +37 -0
  185. data/bridge/sdk-core/sdk/src/conversions.rs +8 -0
  186. data/bridge/sdk-core/sdk/src/interceptors.rs +17 -0
  187. data/bridge/sdk-core/sdk/src/lib.rs +792 -0
  188. data/bridge/sdk-core/sdk/src/payload_converter.rs +11 -0
  189. data/bridge/sdk-core/sdk/src/workflow_context/options.rs +295 -0
  190. data/bridge/sdk-core/sdk/src/workflow_context.rs +683 -0
  191. data/bridge/sdk-core/sdk/src/workflow_future.rs +503 -0
  192. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +30 -0
  193. data/bridge/sdk-core/sdk-core-protos/LICENSE.txt +23 -0
  194. data/bridge/sdk-core/sdk-core-protos/build.rs +108 -0
  195. data/bridge/sdk-core/sdk-core-protos/src/constants.rs +7 -0
  196. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +497 -0
  197. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +230 -0
  198. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +1910 -0
  199. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
  200. data/bridge/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  201. data/bridge/sdk-core/test-utils/Cargo.toml +35 -0
  202. data/bridge/sdk-core/test-utils/src/canned_histories.rs +1579 -0
  203. data/bridge/sdk-core/test-utils/src/histfetch.rs +28 -0
  204. data/bridge/sdk-core/test-utils/src/lib.rs +598 -0
  205. data/bridge/sdk-core/tests/integ_tests/client_tests.rs +36 -0
  206. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +128 -0
  207. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +218 -0
  208. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +146 -0
  209. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +437 -0
  210. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
  211. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +878 -0
  212. data/bridge/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +61 -0
  213. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +59 -0
  214. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +58 -0
  215. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +50 -0
  216. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +60 -0
  217. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +54 -0
  218. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +634 -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 +137 -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 +587 -0
  227. data/bridge/sdk-core/tests/load_tests.rs +191 -0
  228. data/bridge/sdk-core/tests/main.rs +111 -0
  229. data/bridge/sdk-core/tests/runner.rs +93 -0
  230. data/bridge/src/connection.rs +167 -0
  231. data/bridge/src/lib.rs +180 -0
  232. data/bridge/src/runtime.rs +47 -0
  233. data/bridge/src/worker.rs +73 -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 +48 -0
  238. data/lib/gen/temporal/api/cluster/v1/message_pb.rb +67 -0
  239. data/lib/gen/temporal/api/command/v1/message_pb.rb +166 -0
  240. data/lib/gen/temporal/api/common/v1/message_pb.rb +69 -0
  241. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +32 -0
  242. data/lib/gen/temporal/api/enums/v1/cluster_pb.rb +26 -0
  243. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +37 -0
  244. data/lib/gen/temporal/api/enums/v1/common_pb.rb +41 -0
  245. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +67 -0
  246. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +71 -0
  247. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +37 -0
  248. data/lib/gen/temporal/api/enums/v1/query_pb.rb +31 -0
  249. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +24 -0
  250. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +28 -0
  251. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +30 -0
  252. data/lib/gen/temporal/api/enums/v1/update_pb.rb +28 -0
  253. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +89 -0
  254. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +84 -0
  255. data/lib/gen/temporal/api/failure/v1/message_pb.rb +83 -0
  256. data/lib/gen/temporal/api/filter/v1/message_pb.rb +40 -0
  257. data/lib/gen/temporal/api/history/v1/message_pb.rb +489 -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 +125 -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 +128 -0
  264. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +73 -0
  265. data/lib/gen/temporal/api/update/v1/message_pb.rb +26 -0
  266. data/lib/gen/temporal/api/version/v1/message_pb.rb +41 -0
  267. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +110 -0
  268. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +771 -0
  269. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +20 -0
  270. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +58 -0
  271. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +57 -0
  272. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +222 -0
  273. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +57 -0
  274. data/lib/gen/temporal/sdk/core/common/common_pb.rb +22 -0
  275. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +34 -0
  276. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +27 -0
  277. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +164 -0
  278. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +192 -0
  279. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +34 -0
  280. data/lib/temporal/bridge.rb +14 -0
  281. data/lib/temporal/client/implementation.rb +339 -0
  282. data/lib/temporal/client/workflow_handle.rb +243 -0
  283. data/lib/temporal/client.rb +144 -0
  284. data/lib/temporal/connection.rb +736 -0
  285. data/lib/temporal/data_converter.rb +150 -0
  286. data/lib/temporal/error/failure.rb +194 -0
  287. data/lib/temporal/error/workflow_failure.rb +17 -0
  288. data/lib/temporal/errors.rb +22 -0
  289. data/lib/temporal/failure_converter/base.rb +26 -0
  290. data/lib/temporal/failure_converter/basic.rb +313 -0
  291. data/lib/temporal/failure_converter.rb +8 -0
  292. data/lib/temporal/interceptor/chain.rb +27 -0
  293. data/lib/temporal/interceptor/client.rb +102 -0
  294. data/lib/temporal/payload_codec/base.rb +32 -0
  295. data/lib/temporal/payload_converter/base.rb +24 -0
  296. data/lib/temporal/payload_converter/bytes.rb +26 -0
  297. data/lib/temporal/payload_converter/composite.rb +47 -0
  298. data/lib/temporal/payload_converter/encoding_base.rb +35 -0
  299. data/lib/temporal/payload_converter/json.rb +25 -0
  300. data/lib/temporal/payload_converter/nil.rb +25 -0
  301. data/lib/temporal/payload_converter.rb +14 -0
  302. data/lib/temporal/retry_policy.rb +82 -0
  303. data/lib/temporal/retry_state.rb +35 -0
  304. data/lib/temporal/runtime.rb +22 -0
  305. data/lib/temporal/timeout_type.rb +29 -0
  306. data/lib/temporal/version.rb +1 -1
  307. data/lib/temporal/workflow/execution_info.rb +54 -0
  308. data/lib/temporal/workflow/execution_status.rb +36 -0
  309. data/lib/temporal/workflow/id_reuse_policy.rb +36 -0
  310. data/lib/temporal/workflow/query_reject_condition.rb +33 -0
  311. data/lib/temporal.rb +4 -0
  312. data/lib/temporalio.rb +3 -1
  313. data/lib/thermite_patch.rb +23 -0
  314. data/temporalio.gemspec +41 -0
  315. metadata +543 -9
  316. data/temporal.gemspec +0 -20
@@ -0,0 +1,736 @@
1
+ use crate::{
2
+ test_help::{
3
+ build_mock_pollers, canned_histories, hist_to_poll_resp, mock_worker, single_hist_mock_sg,
4
+ MockPollCfg, ResponseType, TEST_Q,
5
+ },
6
+ worker::{client::mocks::mock_workflow_client, LEGACY_QUERY_ID},
7
+ };
8
+ use std::{
9
+ collections::{HashMap, VecDeque},
10
+ time::Duration,
11
+ };
12
+ use temporal_sdk_core_api::Worker as WorkerTrait;
13
+ use temporal_sdk_core_protos::{
14
+ coresdk::{
15
+ workflow_activation::{
16
+ remove_from_cache::EvictionReason, workflow_activation_job, WorkflowActivationJob,
17
+ },
18
+ workflow_commands::{
19
+ ActivityCancellationType, CompleteWorkflowExecution, ContinueAsNewWorkflowExecution,
20
+ QueryResult, QuerySuccess, RequestCancelActivity,
21
+ },
22
+ workflow_completion::WorkflowActivationCompletion,
23
+ },
24
+ temporal::api::{
25
+ common::v1::Payload,
26
+ failure::v1::Failure,
27
+ history::v1::History,
28
+ query::v1::WorkflowQuery,
29
+ workflowservice::v1::{
30
+ GetWorkflowExecutionHistoryResponse, RespondWorkflowTaskCompletedResponse,
31
+ },
32
+ },
33
+ };
34
+ use temporal_sdk_core_test_utils::{schedule_activity_cmd, start_timer_cmd};
35
+
36
+ #[rstest::rstest]
37
+ #[case::with_history(true)]
38
+ #[case::without_history(false)]
39
+ #[tokio::test]
40
+ async fn legacy_query(#[case] include_history: bool) {
41
+ let wfid = "fake_wf_id";
42
+ let query_resp = "response";
43
+ let t = canned_histories::single_timer("1");
44
+ let mut header = HashMap::new();
45
+ header.insert("head".to_string(), Payload::from(b"er"));
46
+ let tasks = [
47
+ hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string()),
48
+ {
49
+ let mut pr = hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string());
50
+ pr.query = Some(WorkflowQuery {
51
+ query_type: "query-type".to_string(),
52
+ query_args: Some(b"hi".into()),
53
+ header: Some(header.into()),
54
+ });
55
+ if !include_history {
56
+ pr.history = Some(History { events: vec![] });
57
+ }
58
+ pr
59
+ },
60
+ hist_to_poll_resp(&t, wfid.to_owned(), 2.into(), TEST_Q.to_string()),
61
+ ];
62
+ let mut mock = MockPollCfg::from_resp_batches(wfid, t, tasks, mock_workflow_client());
63
+ mock.num_expected_legacy_query_resps = 1;
64
+ let mut mock = build_mock_pollers(mock);
65
+ if !include_history {
66
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
67
+ }
68
+ let worker = mock_worker(mock);
69
+
70
+ let first_wft = || async {
71
+ let task = worker.poll_workflow_activation().await.unwrap();
72
+ worker
73
+ .complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
74
+ task.run_id,
75
+ start_timer_cmd(1, Duration::from_secs(1)),
76
+ ))
77
+ .await
78
+ .unwrap();
79
+ };
80
+ let clear_eviction = || async {
81
+ let t = worker.poll_workflow_activation().await.unwrap();
82
+ assert_matches!(
83
+ t.jobs[0].variant,
84
+ Some(workflow_activation_job::Variant::RemoveFromCache(_))
85
+ );
86
+ worker
87
+ .complete_workflow_activation(WorkflowActivationCompletion::empty(t.run_id))
88
+ .await
89
+ .unwrap();
90
+ };
91
+
92
+ first_wft().await;
93
+
94
+ if include_history {
95
+ clear_eviction().await;
96
+ first_wft().await;
97
+ }
98
+
99
+ let task = worker.poll_workflow_activation().await.unwrap();
100
+ // Poll again, and we end up getting a `query` field query response
101
+ let query = assert_matches!(
102
+ task.jobs.as_slice(),
103
+ [WorkflowActivationJob {
104
+ variant: Some(workflow_activation_job::Variant::QueryWorkflow(q)),
105
+ }] => q
106
+ );
107
+ assert_eq!(query.headers.get("head").unwrap(), &b"er".into());
108
+ // Complete the query
109
+ worker
110
+ .complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
111
+ task.run_id,
112
+ QueryResult {
113
+ query_id: query.query_id.clone(),
114
+ variant: Some(
115
+ QuerySuccess {
116
+ response: Some(query_resp.into()),
117
+ }
118
+ .into(),
119
+ ),
120
+ }
121
+ .into(),
122
+ ))
123
+ .await
124
+ .unwrap();
125
+
126
+ if include_history {
127
+ clear_eviction().await;
128
+ first_wft().await;
129
+ }
130
+
131
+ let task = worker.poll_workflow_activation().await.unwrap();
132
+ assert_matches!(
133
+ task.jobs.as_slice(),
134
+ [WorkflowActivationJob {
135
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
136
+ }]
137
+ );
138
+ worker
139
+ .complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
140
+ task.run_id,
141
+ vec![CompleteWorkflowExecution { result: None }.into()],
142
+ ))
143
+ .await
144
+ .unwrap();
145
+ worker.shutdown().await;
146
+ }
147
+
148
+ #[rstest::rstest]
149
+ #[case::one_query(1)]
150
+ #[case::multiple_queries(3)]
151
+ #[tokio::test]
152
+ async fn new_queries(#[case] num_queries: usize) {
153
+ let wfid = "fake_wf_id";
154
+ let query_resp = "response";
155
+ let t = canned_histories::single_timer("1");
156
+ let mut header = HashMap::new();
157
+ header.insert("head".to_string(), Payload::from(b"er"));
158
+ let tasks = VecDeque::from(vec![
159
+ hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string()),
160
+ {
161
+ let mut pr = hist_to_poll_resp(
162
+ &t,
163
+ wfid.to_owned(),
164
+ ResponseType::OneTask(2),
165
+ TEST_Q.to_string(),
166
+ );
167
+ pr.queries = HashMap::new();
168
+ for i in 1..=num_queries {
169
+ pr.queries.insert(
170
+ format!("q{}", i),
171
+ WorkflowQuery {
172
+ query_type: "query-type".to_string(),
173
+ query_args: Some(b"hi".into()),
174
+ header: Some(header.clone().into()),
175
+ },
176
+ );
177
+ }
178
+ pr
179
+ },
180
+ ]);
181
+ let mut mock_client = mock_workflow_client();
182
+ mock_client.expect_respond_legacy_query().times(0);
183
+ let mut mock = single_hist_mock_sg(wfid, t, tasks, mock_client, true);
184
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
185
+ let core = mock_worker(mock);
186
+
187
+ let task = core.poll_workflow_activation().await.unwrap();
188
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
189
+ task.run_id,
190
+ start_timer_cmd(1, Duration::from_secs(1)),
191
+ ))
192
+ .await
193
+ .unwrap();
194
+
195
+ let task = core.poll_workflow_activation().await.unwrap();
196
+ assert_matches!(
197
+ task.jobs[0],
198
+ WorkflowActivationJob {
199
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
200
+ }
201
+ );
202
+ for i in 1..=num_queries {
203
+ assert_matches!(
204
+ task.jobs[i],
205
+ WorkflowActivationJob {
206
+ variant: Some(workflow_activation_job::Variant::QueryWorkflow(ref q)),
207
+ } => {
208
+ assert_eq!(q.headers.get("head").unwrap(), &b"er".into());
209
+ }
210
+ );
211
+ }
212
+ let mut qresults: Vec<_> = (1..=num_queries)
213
+ .map(|i| {
214
+ QueryResult {
215
+ query_id: format!("q{}", i),
216
+ variant: Some(
217
+ QuerySuccess {
218
+ response: Some(query_resp.into()),
219
+ }
220
+ .into(),
221
+ ),
222
+ }
223
+ .into()
224
+ })
225
+ .collect();
226
+ qresults.push(CompleteWorkflowExecution { result: None }.into());
227
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
228
+ task.run_id,
229
+ qresults,
230
+ ))
231
+ .await
232
+ .unwrap();
233
+ core.shutdown().await;
234
+ }
235
+
236
+ #[tokio::test]
237
+ async fn legacy_query_failure_on_wft_failure() {
238
+ let wfid = "fake_wf_id";
239
+ let t = canned_histories::single_timer("1");
240
+ let tasks = VecDeque::from(vec![
241
+ hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string()),
242
+ {
243
+ let mut pr = hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string());
244
+ pr.query = Some(WorkflowQuery {
245
+ query_type: "query-type".to_string(),
246
+ query_args: Some(b"hi".into()),
247
+ header: None,
248
+ });
249
+ pr.history = Some(History { events: vec![] });
250
+ pr
251
+ },
252
+ ]);
253
+ let mut mock = MockPollCfg::from_resp_batches(wfid, t, tasks, mock_workflow_client());
254
+ mock.num_expected_legacy_query_resps = 1;
255
+ let mut mock = build_mock_pollers(mock);
256
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
257
+ let core = mock_worker(mock);
258
+
259
+ let task = core.poll_workflow_activation().await.unwrap();
260
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
261
+ task.run_id,
262
+ start_timer_cmd(1, Duration::from_secs(1)),
263
+ ))
264
+ .await
265
+ .unwrap();
266
+
267
+ let task = core.poll_workflow_activation().await.unwrap();
268
+ // Poll again, and we end up getting a `query` field query response
269
+ assert_matches!(
270
+ task.jobs.as_slice(),
271
+ [WorkflowActivationJob {
272
+ variant: Some(workflow_activation_job::Variant::QueryWorkflow(q)),
273
+ }] => q
274
+ );
275
+ // Fail wft which should result in query being failed
276
+ core.complete_workflow_activation(WorkflowActivationCompletion::fail(
277
+ task.run_id,
278
+ Failure {
279
+ message: "Ahh i broke".to_string(),
280
+ ..Default::default()
281
+ },
282
+ ))
283
+ .await
284
+ .unwrap();
285
+
286
+ core.shutdown().await;
287
+ }
288
+
289
+ #[rstest::rstest]
290
+ #[tokio::test]
291
+ async fn query_failure_because_nondeterminism(#[values(true, false)] legacy: bool) {
292
+ let wfid = "fake_wf_id";
293
+ let t = canned_histories::single_timer("1");
294
+ let tasks = [{
295
+ let mut pr = hist_to_poll_resp(
296
+ &t,
297
+ wfid.to_owned(),
298
+ ResponseType::AllHistory,
299
+ TEST_Q.to_string(),
300
+ );
301
+ if legacy {
302
+ pr.query = Some(WorkflowQuery {
303
+ query_type: "query-type".to_string(),
304
+ query_args: Some(b"hi".into()),
305
+ header: None,
306
+ });
307
+ } else {
308
+ pr.queries = HashMap::new();
309
+ pr.queries.insert(
310
+ "q1".to_string(),
311
+ WorkflowQuery {
312
+ query_type: "query-type".to_string(),
313
+ query_args: Some(b"hi".into()),
314
+ header: None,
315
+ },
316
+ );
317
+ }
318
+ pr
319
+ }];
320
+ let mut mock = MockPollCfg::from_resp_batches(wfid, t, tasks, mock_workflow_client());
321
+ if legacy {
322
+ mock.num_expected_legacy_query_resps = 1;
323
+ } else {
324
+ mock.num_expected_fails = 1;
325
+ }
326
+ let mut mock = build_mock_pollers(mock);
327
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
328
+ let core = mock_worker(mock);
329
+
330
+ let task = core.poll_workflow_activation().await.unwrap();
331
+ // Nondeterminism, should result in WFT/query being failed
332
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
333
+ .await
334
+ .unwrap();
335
+ let task = core.poll_workflow_activation().await.unwrap();
336
+ assert_matches!(
337
+ task.jobs[0].variant,
338
+ Some(workflow_activation_job::Variant::RemoveFromCache(_))
339
+ );
340
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
341
+ .await
342
+ .unwrap();
343
+
344
+ core.shutdown().await;
345
+ }
346
+
347
+ #[rstest::rstest]
348
+ #[tokio::test]
349
+ async fn legacy_query_after_complete(#[values(false, true)] full_history: bool) {
350
+ let wfid = "fake_wf_id";
351
+ let t = if full_history {
352
+ canned_histories::single_timer_wf_completes("1")
353
+ } else {
354
+ let mut t = canned_histories::single_timer("1");
355
+ t.add_workflow_task_completed();
356
+ t
357
+ };
358
+ let query_with_hist_task = {
359
+ let mut pr = hist_to_poll_resp(
360
+ &t,
361
+ wfid.to_owned(),
362
+ ResponseType::AllHistory,
363
+ TEST_Q.to_string(),
364
+ );
365
+ pr.query = Some(WorkflowQuery {
366
+ query_type: "query-type".to_string(),
367
+ query_args: Some(b"hi".into()),
368
+ header: None,
369
+ });
370
+ pr.resp
371
+ };
372
+ // Server would never send us a workflow task *without* a query that goes all the way to
373
+ // execution completed. So, don't do that. It messes with the mock unlocking the next
374
+ // task since we (appropriately) won't respond to server in that situation.
375
+ let mut tasks = if full_history {
376
+ vec![]
377
+ } else {
378
+ vec![
379
+ hist_to_poll_resp(
380
+ &t,
381
+ wfid.to_owned(),
382
+ ResponseType::AllHistory,
383
+ TEST_Q.to_string(),
384
+ )
385
+ .resp,
386
+ ]
387
+ };
388
+ tasks.extend([query_with_hist_task.clone(), query_with_hist_task]);
389
+
390
+ let mut mock = MockPollCfg::from_resp_batches(wfid, t, tasks, mock_workflow_client());
391
+ mock.num_expected_legacy_query_resps = 2;
392
+ let mut mock = build_mock_pollers(mock);
393
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
394
+ let core = mock_worker(mock);
395
+
396
+ let task = core.poll_workflow_activation().await.unwrap();
397
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
398
+ task.run_id,
399
+ start_timer_cmd(1, Duration::from_secs(1)),
400
+ ))
401
+ .await
402
+ .unwrap();
403
+ let task = core.poll_workflow_activation().await.unwrap();
404
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
405
+ task.run_id,
406
+ vec![CompleteWorkflowExecution { result: None }.into()],
407
+ ))
408
+ .await
409
+ .unwrap();
410
+
411
+ // We should get queries two times
412
+ for _ in 1..=2 {
413
+ let task = core.poll_workflow_activation().await.unwrap();
414
+ let query = assert_matches!(
415
+ task.jobs.as_slice(),
416
+ [WorkflowActivationJob {
417
+ variant: Some(workflow_activation_job::Variant::QueryWorkflow(q)),
418
+ }] => q
419
+ );
420
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
421
+ task.run_id,
422
+ QueryResult {
423
+ query_id: query.query_id.clone(),
424
+ variant: Some(
425
+ QuerySuccess {
426
+ response: Some("whatever".into()),
427
+ }
428
+ .into(),
429
+ ),
430
+ }
431
+ .into(),
432
+ ))
433
+ .await
434
+ .unwrap();
435
+ }
436
+
437
+ core.shutdown().await;
438
+ }
439
+
440
+ enum QueryHists {
441
+ Empty,
442
+ Full,
443
+ Partial,
444
+ }
445
+ #[rstest::rstest]
446
+ #[tokio::test]
447
+ async fn query_cache_miss_causes_page_fetch_dont_reply_wft_too_early(
448
+ #[values(QueryHists::Empty, QueryHists::Full, QueryHists::Partial)] hist_type: QueryHists,
449
+ ) {
450
+ let wfid = "fake_wf_id";
451
+ let query_resp = "response";
452
+ let t = canned_histories::single_timer("1");
453
+ let full_hist = t.get_full_history_info().unwrap();
454
+ let tasks = VecDeque::from(vec![{
455
+ let mut pr = match hist_type {
456
+ QueryHists::Empty => {
457
+ // Create a no-history poll response. This happens to be easiest to do by just ripping
458
+ // out the history after making a normal one.
459
+ let mut pr = hist_to_poll_resp(
460
+ &t,
461
+ wfid.to_owned(),
462
+ ResponseType::AllHistory,
463
+ TEST_Q.to_string(),
464
+ );
465
+ pr.history = Some(Default::default());
466
+ pr
467
+ }
468
+ QueryHists::Full => hist_to_poll_resp(
469
+ &t,
470
+ wfid.to_owned(),
471
+ ResponseType::AllHistory,
472
+ TEST_Q.to_string(),
473
+ ),
474
+ QueryHists::Partial => {
475
+ // Create a partial task
476
+ hist_to_poll_resp(
477
+ &t,
478
+ wfid.to_owned(),
479
+ ResponseType::OneTask(2),
480
+ TEST_Q.to_string(),
481
+ )
482
+ }
483
+ };
484
+ pr.queries = HashMap::new();
485
+ pr.queries.insert(
486
+ "the-query".to_string(),
487
+ WorkflowQuery {
488
+ query_type: "query-type".to_string(),
489
+ query_args: Some(b"hi".into()),
490
+ header: None,
491
+ },
492
+ );
493
+ pr
494
+ }]);
495
+ let mut mock_client = mock_workflow_client();
496
+ if !matches!(hist_type, QueryHists::Full) {
497
+ mock_client
498
+ .expect_get_workflow_execution_history()
499
+ .returning(move |_, _, _| {
500
+ Ok(GetWorkflowExecutionHistoryResponse {
501
+ history: Some(full_hist.clone().into()),
502
+ ..Default::default()
503
+ })
504
+ });
505
+ }
506
+ mock_client
507
+ .expect_complete_workflow_task()
508
+ .times(1)
509
+ .returning(|resp| {
510
+ // Verify both the complete command and the query response are sent
511
+ assert_eq!(resp.commands.len(), 1);
512
+ assert_eq!(resp.query_responses.len(), 1);
513
+
514
+ Ok(RespondWorkflowTaskCompletedResponse::default())
515
+ });
516
+
517
+ let mut mock = single_hist_mock_sg(wfid, t, tasks, mock_client, true);
518
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
519
+ let core = mock_worker(mock);
520
+ let task = core.poll_workflow_activation().await.unwrap();
521
+ // The first task should *only* start the workflow. It should *not* have a query in it, which
522
+ // was the bug. Query should only appear after we have caught up on replay.
523
+ assert_matches!(
524
+ task.jobs.as_slice(),
525
+ [WorkflowActivationJob {
526
+ variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
527
+ }]
528
+ );
529
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
530
+ task.run_id,
531
+ start_timer_cmd(1, Duration::from_secs(1)),
532
+ ))
533
+ .await
534
+ .unwrap();
535
+
536
+ let task = core.poll_workflow_activation().await.unwrap();
537
+ assert_matches!(
538
+ task.jobs.as_slice(),
539
+ [WorkflowActivationJob {
540
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
541
+ }]
542
+ );
543
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
544
+ task.run_id,
545
+ CompleteWorkflowExecution { result: None }.into(),
546
+ ))
547
+ .await
548
+ .unwrap();
549
+
550
+ // Now the query shall arrive
551
+ let task = core.poll_workflow_activation().await.unwrap();
552
+ assert_matches!(
553
+ task.jobs[0],
554
+ WorkflowActivationJob {
555
+ variant: Some(workflow_activation_job::Variant::QueryWorkflow(_)),
556
+ }
557
+ );
558
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
559
+ task.run_id,
560
+ QueryResult {
561
+ query_id: "the-query".to_string(),
562
+ variant: Some(
563
+ QuerySuccess {
564
+ response: Some(query_resp.into()),
565
+ }
566
+ .into(),
567
+ ),
568
+ }
569
+ .into(),
570
+ ))
571
+ .await
572
+ .unwrap();
573
+
574
+ core.shutdown().await;
575
+ }
576
+
577
+ #[tokio::test]
578
+ async fn query_replay_with_continue_as_new_doesnt_reply_empty_command() {
579
+ let wfid = "fake_wf_id";
580
+ let t = canned_histories::single_timer("1");
581
+ let query_with_hist_task = {
582
+ let mut pr = hist_to_poll_resp(
583
+ &t,
584
+ wfid.to_owned(),
585
+ ResponseType::ToTaskNum(1),
586
+ TEST_Q.to_string(),
587
+ );
588
+ pr.queries = HashMap::new();
589
+ pr.queries.insert(
590
+ "the-query".to_string(),
591
+ WorkflowQuery {
592
+ query_type: "query-type".to_string(),
593
+ query_args: Some(b"hi".into()),
594
+ header: None,
595
+ },
596
+ );
597
+ pr
598
+ };
599
+ let tasks = VecDeque::from(vec![query_with_hist_task]);
600
+ let mut mock_client = mock_workflow_client();
601
+ mock_client
602
+ .expect_complete_workflow_task()
603
+ .times(1)
604
+ .returning(|resp| {
605
+ // Verify both the complete command and the query response are sent
606
+ assert_eq!(resp.commands.len(), 1);
607
+ assert_eq!(resp.query_responses.len(), 1);
608
+ Ok(RespondWorkflowTaskCompletedResponse::default())
609
+ });
610
+
611
+ let mut mock = single_hist_mock_sg(wfid, t, tasks, mock_client, true);
612
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
613
+ let core = mock_worker(mock);
614
+
615
+ let task = core.poll_workflow_activation().await.unwrap();
616
+ // Scheduling and immediately canceling an activity produces another activation which is
617
+ // important in this repro
618
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
619
+ task.run_id,
620
+ vec![
621
+ schedule_activity_cmd(
622
+ 0,
623
+ "whatever",
624
+ "act-id",
625
+ ActivityCancellationType::TryCancel,
626
+ Duration::from_secs(60),
627
+ Duration::from_secs(60),
628
+ ),
629
+ RequestCancelActivity { seq: 0 }.into(),
630
+ ContinueAsNewWorkflowExecution {
631
+ ..Default::default()
632
+ }
633
+ .into(),
634
+ ],
635
+ ))
636
+ .await
637
+ .unwrap();
638
+
639
+ // Activity unblocked
640
+ let task = core.poll_workflow_activation().await.unwrap();
641
+ assert_matches!(
642
+ task.jobs.as_slice(),
643
+ [WorkflowActivationJob {
644
+ variant: Some(workflow_activation_job::Variant::ResolveActivity(_)),
645
+ }]
646
+ );
647
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
648
+ .await
649
+ .unwrap();
650
+
651
+ let task = core.poll_workflow_activation().await.unwrap();
652
+ let query = assert_matches!(
653
+ task.jobs.as_slice(),
654
+ [WorkflowActivationJob {
655
+ variant: Some(workflow_activation_job::Variant::QueryWorkflow(q)),
656
+ }] => q
657
+ );
658
+ // Throw an evict in there. Repro required a pending eviction during complete.
659
+ core.request_wf_eviction(&task.run_id, "I said so", EvictionReason::LangRequested);
660
+
661
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
662
+ task.run_id,
663
+ QueryResult {
664
+ query_id: query.query_id.clone(),
665
+ variant: Some(
666
+ QuerySuccess {
667
+ response: Some("whatever".into()),
668
+ }
669
+ .into(),
670
+ ),
671
+ }
672
+ .into(),
673
+ ))
674
+ .await
675
+ .unwrap();
676
+
677
+ core.shutdown().await;
678
+ }
679
+
680
+ #[tokio::test]
681
+ async fn legacy_query_response_gets_not_found_not_fatal() {
682
+ let wfid = "fake_wf_id";
683
+ let t = canned_histories::single_timer("1");
684
+ let tasks = [{
685
+ let mut pr = hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string());
686
+ pr.query = Some(WorkflowQuery {
687
+ query_type: "query-type".to_string(),
688
+ query_args: Some(b"hi".into()),
689
+ header: None,
690
+ });
691
+ pr
692
+ }];
693
+ let mut mock = mock_workflow_client();
694
+ mock.expect_respond_legacy_query()
695
+ .times(1)
696
+ .returning(move |_, _| Err(tonic::Status::not_found("Query gone boi")));
697
+ let mock = MockPollCfg::from_resp_batches(wfid, t, tasks, mock);
698
+ let mut mock = build_mock_pollers(mock);
699
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
700
+ let core = mock_worker(mock);
701
+
702
+ let task = core.poll_workflow_activation().await.unwrap();
703
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
704
+ task.run_id,
705
+ start_timer_cmd(1, Duration::from_secs(1)),
706
+ ))
707
+ .await
708
+ .unwrap();
709
+
710
+ let task = core.poll_workflow_activation().await.unwrap();
711
+ // Poll again, and we end up getting a `query` field query response
712
+ assert_matches!(
713
+ task.jobs.as_slice(),
714
+ [WorkflowActivationJob {
715
+ variant: Some(workflow_activation_job::Variant::QueryWorkflow(q)),
716
+ }] => q
717
+ );
718
+ // Fail wft which should result in query being failed
719
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
720
+ task.run_id,
721
+ QueryResult {
722
+ query_id: LEGACY_QUERY_ID.to_string(),
723
+ variant: Some(
724
+ QuerySuccess {
725
+ response: Some("hi".into()),
726
+ }
727
+ .into(),
728
+ ),
729
+ }
730
+ .into(),
731
+ ))
732
+ .await
733
+ .unwrap();
734
+
735
+ core.shutdown().await;
736
+ }