temporalio 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +301 -0
  3. data/bridge/Cargo.lock +2888 -0
  4. data/bridge/Cargo.toml +27 -0
  5. data/bridge/sdk-core/ARCHITECTURE.md +76 -0
  6. data/bridge/sdk-core/Cargo.lock +2606 -0
  7. data/bridge/sdk-core/Cargo.toml +2 -0
  8. data/bridge/sdk-core/LICENSE.txt +23 -0
  9. data/bridge/sdk-core/README.md +104 -0
  10. data/bridge/sdk-core/arch_docs/diagrams/README.md +10 -0
  11. data/bridge/sdk-core/arch_docs/diagrams/sticky_queues.puml +40 -0
  12. data/bridge/sdk-core/arch_docs/diagrams/workflow_internals.svg +1 -0
  13. data/bridge/sdk-core/arch_docs/sticky_queues.md +51 -0
  14. data/bridge/sdk-core/client/Cargo.toml +40 -0
  15. data/bridge/sdk-core/client/LICENSE.txt +23 -0
  16. data/bridge/sdk-core/client/src/lib.rs +1286 -0
  17. data/bridge/sdk-core/client/src/metrics.rs +165 -0
  18. data/bridge/sdk-core/client/src/raw.rs +932 -0
  19. data/bridge/sdk-core/client/src/retry.rs +751 -0
  20. data/bridge/sdk-core/client/src/workflow_handle/mod.rs +185 -0
  21. data/bridge/sdk-core/core/Cargo.toml +116 -0
  22. data/bridge/sdk-core/core/LICENSE.txt +23 -0
  23. data/bridge/sdk-core/core/benches/workflow_replay.rs +76 -0
  24. data/bridge/sdk-core/core/src/abstractions.rs +166 -0
  25. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +1014 -0
  26. data/bridge/sdk-core/core/src/core_tests/child_workflows.rs +221 -0
  27. data/bridge/sdk-core/core/src/core_tests/determinism.rs +107 -0
  28. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +925 -0
  29. data/bridge/sdk-core/core/src/core_tests/mod.rs +100 -0
  30. data/bridge/sdk-core/core/src/core_tests/queries.rs +894 -0
  31. data/bridge/sdk-core/core/src/core_tests/replay_flag.rs +65 -0
  32. data/bridge/sdk-core/core/src/core_tests/workers.rs +259 -0
  33. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +124 -0
  34. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +2090 -0
  35. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +515 -0
  36. data/bridge/sdk-core/core/src/lib.rs +282 -0
  37. data/bridge/sdk-core/core/src/pollers/mod.rs +54 -0
  38. data/bridge/sdk-core/core/src/pollers/poll_buffer.rs +297 -0
  39. data/bridge/sdk-core/core/src/protosext/mod.rs +428 -0
  40. data/bridge/sdk-core/core/src/replay/mod.rs +215 -0
  41. data/bridge/sdk-core/core/src/retry_logic.rs +202 -0
  42. data/bridge/sdk-core/core/src/telemetry/log_export.rs +190 -0
  43. data/bridge/sdk-core/core/src/telemetry/metrics.rs +428 -0
  44. data/bridge/sdk-core/core/src/telemetry/mod.rs +407 -0
  45. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +78 -0
  46. data/bridge/sdk-core/core/src/test_help/mod.rs +889 -0
  47. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +580 -0
  48. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +1048 -0
  49. data/bridge/sdk-core/core/src/worker/activities.rs +481 -0
  50. data/bridge/sdk-core/core/src/worker/client/mocks.rs +87 -0
  51. data/bridge/sdk-core/core/src/worker/client.rs +373 -0
  52. data/bridge/sdk-core/core/src/worker/mod.rs +570 -0
  53. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +37 -0
  54. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +101 -0
  55. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +532 -0
  56. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +907 -0
  57. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +294 -0
  58. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +167 -0
  59. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +858 -0
  60. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +136 -0
  61. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +157 -0
  62. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +129 -0
  63. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +1450 -0
  64. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +316 -0
  65. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +178 -0
  66. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +708 -0
  67. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +439 -0
  68. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +435 -0
  69. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +175 -0
  70. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +242 -0
  71. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +96 -0
  72. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +1200 -0
  73. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +272 -0
  74. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +198 -0
  75. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +655 -0
  76. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +1200 -0
  77. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +145 -0
  78. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +88 -0
  79. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +985 -0
  80. data/bridge/sdk-core/core-api/Cargo.toml +32 -0
  81. data/bridge/sdk-core/core-api/LICENSE.txt +23 -0
  82. data/bridge/sdk-core/core-api/src/errors.rs +95 -0
  83. data/bridge/sdk-core/core-api/src/lib.rs +109 -0
  84. data/bridge/sdk-core/core-api/src/telemetry.rs +147 -0
  85. data/bridge/sdk-core/core-api/src/worker.rs +148 -0
  86. data/bridge/sdk-core/etc/deps.svg +162 -0
  87. data/bridge/sdk-core/etc/dynamic-config.yaml +2 -0
  88. data/bridge/sdk-core/etc/otel-collector-config.yaml +36 -0
  89. data/bridge/sdk-core/etc/prometheus.yaml +6 -0
  90. data/bridge/sdk-core/etc/regen-depgraph.sh +5 -0
  91. data/bridge/sdk-core/fsm/Cargo.toml +18 -0
  92. data/bridge/sdk-core/fsm/LICENSE.txt +23 -0
  93. data/bridge/sdk-core/fsm/README.md +3 -0
  94. data/bridge/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +27 -0
  95. data/bridge/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +23 -0
  96. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +647 -0
  97. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +8 -0
  98. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.rs +18 -0
  99. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +12 -0
  100. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dynamic_dest_pass.rs +41 -0
  101. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.rs +14 -0
  102. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.stderr +11 -0
  103. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_arg_pass.rs +32 -0
  104. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_pass.rs +31 -0
  105. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/medium_complex_pass.rs +46 -0
  106. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.rs +29 -0
  107. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +12 -0
  108. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/simple_pass.rs +32 -0
  109. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.rs +18 -0
  110. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +5 -0
  111. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.rs +11 -0
  112. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +5 -0
  113. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.rs +11 -0
  114. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +5 -0
  115. data/bridge/sdk-core/fsm/rustfsm_trait/Cargo.toml +14 -0
  116. data/bridge/sdk-core/fsm/rustfsm_trait/LICENSE.txt +23 -0
  117. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +249 -0
  118. data/bridge/sdk-core/fsm/src/lib.rs +2 -0
  119. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  120. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  121. data/bridge/sdk-core/histories/fail_wf_task.bin +0 -0
  122. data/bridge/sdk-core/histories/timer_workflow_history.bin +0 -0
  123. data/bridge/sdk-core/integ-with-otel.sh +7 -0
  124. data/bridge/sdk-core/protos/api_upstream/README.md +9 -0
  125. data/bridge/sdk-core/protos/api_upstream/api-linter.yaml +40 -0
  126. data/bridge/sdk-core/protos/api_upstream/buf.yaml +9 -0
  127. data/bridge/sdk-core/protos/api_upstream/build/go.mod +7 -0
  128. data/bridge/sdk-core/protos/api_upstream/build/go.sum +5 -0
  129. data/bridge/sdk-core/protos/api_upstream/build/tools.go +29 -0
  130. data/bridge/sdk-core/protos/api_upstream/dependencies/gogoproto/gogo.proto +141 -0
  131. data/bridge/sdk-core/protos/api_upstream/go.mod +6 -0
  132. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +89 -0
  133. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +260 -0
  134. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +112 -0
  135. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +47 -0
  136. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +57 -0
  137. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +56 -0
  138. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +170 -0
  139. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +118 -0
  140. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/interaction_type.proto +39 -0
  141. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +51 -0
  142. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +50 -0
  143. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +41 -0
  144. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +60 -0
  145. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +59 -0
  146. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +40 -0
  147. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +122 -0
  148. data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +108 -0
  149. data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +114 -0
  150. data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +56 -0
  151. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +758 -0
  152. data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +87 -0
  153. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +97 -0
  154. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +121 -0
  155. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +80 -0
  156. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +61 -0
  157. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +55 -0
  158. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +379 -0
  159. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +108 -0
  160. data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +59 -0
  161. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +146 -0
  162. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +1168 -0
  163. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +415 -0
  164. data/bridge/sdk-core/protos/grpc/health/v1/health.proto +63 -0
  165. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
  166. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +79 -0
  167. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +77 -0
  168. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +15 -0
  169. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +30 -0
  170. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
  171. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +263 -0
  172. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +304 -0
  173. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +29 -0
  174. data/bridge/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
  175. data/bridge/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
  176. data/bridge/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
  177. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
  178. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
  179. data/bridge/sdk-core/rustfmt.toml +1 -0
  180. data/bridge/sdk-core/sdk/Cargo.toml +47 -0
  181. data/bridge/sdk-core/sdk/LICENSE.txt +23 -0
  182. data/bridge/sdk-core/sdk/src/activity_context.rs +230 -0
  183. data/bridge/sdk-core/sdk/src/app_data.rs +37 -0
  184. data/bridge/sdk-core/sdk/src/interceptors.rs +50 -0
  185. data/bridge/sdk-core/sdk/src/lib.rs +794 -0
  186. data/bridge/sdk-core/sdk/src/payload_converter.rs +11 -0
  187. data/bridge/sdk-core/sdk/src/workflow_context/options.rs +295 -0
  188. data/bridge/sdk-core/sdk/src/workflow_context.rs +694 -0
  189. data/bridge/sdk-core/sdk/src/workflow_future.rs +499 -0
  190. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +30 -0
  191. data/bridge/sdk-core/sdk-core-protos/LICENSE.txt +23 -0
  192. data/bridge/sdk-core/sdk-core-protos/build.rs +107 -0
  193. data/bridge/sdk-core/sdk-core-protos/src/constants.rs +7 -0
  194. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +544 -0
  195. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +230 -0
  196. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +1970 -0
  197. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
  198. data/bridge/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  199. data/bridge/sdk-core/test-utils/Cargo.toml +36 -0
  200. data/bridge/sdk-core/test-utils/src/canned_histories.rs +1579 -0
  201. data/bridge/sdk-core/test-utils/src/histfetch.rs +28 -0
  202. data/bridge/sdk-core/test-utils/src/lib.rs +650 -0
  203. data/bridge/sdk-core/tests/integ_tests/client_tests.rs +36 -0
  204. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +128 -0
  205. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +221 -0
  206. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +37 -0
  207. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +133 -0
  208. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +437 -0
  209. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
  210. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +878 -0
  211. data/bridge/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +61 -0
  212. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +59 -0
  213. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +58 -0
  214. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +50 -0
  215. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +60 -0
  216. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +54 -0
  217. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +788 -0
  218. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +53 -0
  219. data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +113 -0
  220. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +223 -0
  221. data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +93 -0
  222. data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +167 -0
  223. data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +99 -0
  224. data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +131 -0
  225. data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +75 -0
  226. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +597 -0
  227. data/bridge/sdk-core/tests/load_tests.rs +191 -0
  228. data/bridge/sdk-core/tests/main.rs +113 -0
  229. data/bridge/sdk-core/tests/runner.rs +93 -0
  230. data/bridge/src/connection.rs +186 -0
  231. data/bridge/src/lib.rs +239 -0
  232. data/bridge/src/runtime.rs +54 -0
  233. data/bridge/src/worker.rs +124 -0
  234. data/ext/Rakefile +9 -0
  235. data/lib/bridge.so +0 -0
  236. data/lib/gen/dependencies/gogoproto/gogo_pb.rb +14 -0
  237. data/lib/gen/temporal/api/batch/v1/message_pb.rb +50 -0
  238. data/lib/gen/temporal/api/command/v1/message_pb.rb +174 -0
  239. data/lib/gen/temporal/api/common/v1/message_pb.rb +69 -0
  240. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +33 -0
  241. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +39 -0
  242. data/lib/gen/temporal/api/enums/v1/common_pb.rb +42 -0
  243. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +68 -0
  244. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +77 -0
  245. data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +25 -0
  246. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +37 -0
  247. data/lib/gen/temporal/api/enums/v1/query_pb.rb +31 -0
  248. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +24 -0
  249. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +28 -0
  250. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +30 -0
  251. data/lib/gen/temporal/api/enums/v1/update_pb.rb +23 -0
  252. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +89 -0
  253. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +84 -0
  254. data/lib/gen/temporal/api/failure/v1/message_pb.rb +83 -0
  255. data/lib/gen/temporal/api/filter/v1/message_pb.rb +40 -0
  256. data/lib/gen/temporal/api/history/v1/message_pb.rb +490 -0
  257. data/lib/gen/temporal/api/interaction/v1/message_pb.rb +49 -0
  258. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +63 -0
  259. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +85 -0
  260. data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +20 -0
  261. data/lib/gen/temporal/api/query/v1/message_pb.rb +38 -0
  262. data/lib/gen/temporal/api/replication/v1/message_pb.rb +37 -0
  263. data/lib/gen/temporal/api/schedule/v1/message_pb.rb +149 -0
  264. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +73 -0
  265. data/lib/gen/temporal/api/version/v1/message_pb.rb +41 -0
  266. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +111 -0
  267. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +788 -0
  268. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +20 -0
  269. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +58 -0
  270. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +57 -0
  271. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +222 -0
  272. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +57 -0
  273. data/lib/gen/temporal/sdk/core/common/common_pb.rb +22 -0
  274. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +34 -0
  275. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +27 -0
  276. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +165 -0
  277. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +196 -0
  278. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +34 -0
  279. data/lib/temporalio/activity/context.rb +97 -0
  280. data/lib/temporalio/activity/info.rb +67 -0
  281. data/lib/temporalio/activity.rb +85 -0
  282. data/lib/temporalio/bridge/error.rb +8 -0
  283. data/lib/temporalio/bridge.rb +14 -0
  284. data/lib/temporalio/client/implementation.rb +340 -0
  285. data/lib/temporalio/client/workflow_handle.rb +243 -0
  286. data/lib/temporalio/client.rb +131 -0
  287. data/lib/temporalio/connection.rb +751 -0
  288. data/lib/temporalio/data_converter.rb +191 -0
  289. data/lib/temporalio/error/failure.rb +194 -0
  290. data/lib/temporalio/error/workflow_failure.rb +19 -0
  291. data/lib/temporalio/errors.rb +40 -0
  292. data/lib/temporalio/failure_converter/base.rb +26 -0
  293. data/lib/temporalio/failure_converter/basic.rb +319 -0
  294. data/lib/temporalio/failure_converter.rb +7 -0
  295. data/lib/temporalio/interceptor/chain.rb +28 -0
  296. data/lib/temporalio/interceptor/client.rb +123 -0
  297. data/lib/temporalio/payload_codec/base.rb +32 -0
  298. data/lib/temporalio/payload_converter/base.rb +24 -0
  299. data/lib/temporalio/payload_converter/bytes.rb +27 -0
  300. data/lib/temporalio/payload_converter/composite.rb +49 -0
  301. data/lib/temporalio/payload_converter/encoding_base.rb +35 -0
  302. data/lib/temporalio/payload_converter/json.rb +26 -0
  303. data/lib/temporalio/payload_converter/nil.rb +26 -0
  304. data/lib/temporalio/payload_converter.rb +14 -0
  305. data/lib/temporalio/retry_policy.rb +82 -0
  306. data/lib/temporalio/retry_state.rb +35 -0
  307. data/lib/temporalio/runtime.rb +25 -0
  308. data/lib/temporalio/timeout_type.rb +29 -0
  309. data/lib/temporalio/version.rb +3 -0
  310. data/lib/temporalio/worker/activity_runner.rb +92 -0
  311. data/lib/temporalio/worker/activity_worker.rb +138 -0
  312. data/lib/temporalio/worker/reactor.rb +46 -0
  313. data/lib/temporalio/worker/runner.rb +63 -0
  314. data/lib/temporalio/worker/sync_worker.rb +88 -0
  315. data/lib/temporalio/worker/thread_pool_executor.rb +51 -0
  316. data/lib/temporalio/worker.rb +198 -0
  317. data/lib/temporalio/workflow/execution_info.rb +54 -0
  318. data/lib/temporalio/workflow/execution_status.rb +36 -0
  319. data/lib/temporalio/workflow/id_reuse_policy.rb +36 -0
  320. data/lib/temporalio/workflow/query_reject_condition.rb +33 -0
  321. data/lib/temporalio.rb +12 -1
  322. data/lib/thermite_patch.rb +23 -0
  323. data/temporalio.gemspec +45 -0
  324. metadata +566 -9
  325. data/lib/temporal/version.rb +0 -3
  326. data/lib/temporal.rb +0 -4
  327. data/temporal.gemspec +0 -20
@@ -0,0 +1,597 @@
1
+ mod activities;
2
+ mod appdata_propagation;
3
+ mod cancel_external;
4
+ mod cancel_wf;
5
+ mod child_workflows;
6
+ mod continue_as_new;
7
+ mod determinism;
8
+ mod local_activities;
9
+ mod modify_wf_properties;
10
+ mod patches;
11
+ mod replay;
12
+ mod resets;
13
+ mod signals;
14
+ mod stickyness;
15
+ mod timers;
16
+ mod upsert_search_attrs;
17
+
18
+ use assert_matches::assert_matches;
19
+ use futures::{channel::mpsc::UnboundedReceiver, future, SinkExt, StreamExt};
20
+ use std::{
21
+ collections::HashMap,
22
+ sync::{
23
+ atomic::{AtomicUsize, Ordering},
24
+ Arc,
25
+ },
26
+ time::Duration,
27
+ };
28
+ use temporal_client::{WorkflowClientTrait, WorkflowOptions};
29
+ use temporal_sdk::{
30
+ interceptors::WorkerInterceptor, ActContext, ActivityOptions, WfContext, WorkflowResult,
31
+ };
32
+ use temporal_sdk_core::replay::HistoryForReplay;
33
+ use temporal_sdk_core_api::{errors::PollWfError, Worker};
34
+ use temporal_sdk_core_protos::{
35
+ coresdk::{
36
+ activity_result::ActivityExecutionResult,
37
+ workflow_activation::{workflow_activation_job, WorkflowActivation, WorkflowActivationJob},
38
+ workflow_commands::{ActivityCancellationType, FailWorkflowExecution, StartTimer},
39
+ workflow_completion::WorkflowActivationCompletion,
40
+ ActivityTaskCompletion, AsJsonPayloadExt, IntoCompletion,
41
+ },
42
+ temporal::api::{failure::v1::Failure, history::v1::history_event},
43
+ };
44
+ use temporal_sdk_core_test_utils::{
45
+ history_from_proto_binary, init_core_and_create_wf, init_core_replay_preloaded,
46
+ schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
47
+ };
48
+ use tokio::time::sleep;
49
+ use uuid::Uuid;
50
+
51
+ // TODO: We should get expected histories for these tests and confirm that the history at the end
52
+ // matches.
53
+
54
+ #[tokio::test]
55
+ async fn parallel_workflows_same_queue() {
56
+ let mut starter = CoreWfStarter::new("parallel_workflows_same_queue");
57
+ let core = starter.get_worker().await;
58
+ let num_workflows = 25usize;
59
+
60
+ let run_ids: Vec<_> = future::join_all(
61
+ (0..num_workflows)
62
+ .map(|i| starter.start_wf_with_id(format!("wf-id-{}", i), WorkflowOptions::default())),
63
+ )
64
+ .await;
65
+
66
+ let mut send_chans = HashMap::new();
67
+ async fn wf_task(
68
+ worker: Arc<dyn Worker>,
69
+ mut task_chan: UnboundedReceiver<WorkflowActivation>,
70
+ ) {
71
+ let task = task_chan.next().await.unwrap();
72
+ assert_matches!(
73
+ task.jobs.as_slice(),
74
+ [WorkflowActivationJob {
75
+ variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
76
+ }]
77
+ );
78
+ worker
79
+ .complete_timer(&task.run_id, 1, Duration::from_secs(1))
80
+ .await;
81
+ let task = task_chan.next().await.unwrap();
82
+ worker.complete_execution(&task.run_id).await;
83
+ }
84
+
85
+ let handles: Vec<_> = run_ids
86
+ .iter()
87
+ .map(|run_id| {
88
+ let (tx, rx) = futures::channel::mpsc::unbounded();
89
+ send_chans.insert(run_id.clone(), tx);
90
+ tokio::spawn(wf_task(core.clone(), rx))
91
+ })
92
+ .collect();
93
+
94
+ for _ in 0..num_workflows * 2 {
95
+ let task = core.poll_workflow_activation().await.unwrap();
96
+ send_chans
97
+ .get(&task.run_id)
98
+ .unwrap()
99
+ .send(task)
100
+ .await
101
+ .unwrap();
102
+ }
103
+
104
+ for handle in handles {
105
+ handle.await.unwrap()
106
+ }
107
+ core.shutdown().await;
108
+ }
109
+
110
+ static RUN_CT: AtomicUsize = AtomicUsize::new(0);
111
+ pub async fn cache_evictions_wf(command_sink: WfContext) -> WorkflowResult<()> {
112
+ RUN_CT.fetch_add(1, Ordering::SeqCst);
113
+ command_sink.timer(Duration::from_secs(1)).await;
114
+ Ok(().into())
115
+ }
116
+
117
+ #[tokio::test]
118
+ async fn workflow_lru_cache_evictions() {
119
+ let wf_type = "workflow_lru_cache_evictions";
120
+ let mut starter = CoreWfStarter::new(wf_type);
121
+ starter.max_cached_workflows(1);
122
+ let mut worker = starter.worker().await;
123
+ worker.register_wf(wf_type.to_string(), cache_evictions_wf);
124
+
125
+ let n_workflows = 3;
126
+ for _ in 0..n_workflows {
127
+ worker
128
+ .submit_wf(
129
+ format!("wce-{}", Uuid::new_v4()),
130
+ wf_type.to_string(),
131
+ vec![],
132
+ WorkflowOptions::default(),
133
+ )
134
+ .await
135
+ .unwrap();
136
+ }
137
+ struct CacheAsserter;
138
+ #[async_trait::async_trait(?Send)]
139
+ impl WorkerInterceptor for CacheAsserter {
140
+ async fn on_workflow_activation_completion(&self, _: &WorkflowActivationCompletion) {}
141
+ fn on_shutdown(&self, sdk_worker: &temporal_sdk::Worker) {
142
+ // 0 since the sdk worker force-evicts and drains everything on shutdown.
143
+ assert_eq!(sdk_worker.cached_workflows(), 0);
144
+ }
145
+ }
146
+ worker
147
+ .run_until_done_intercepted(Some(CacheAsserter))
148
+ .await
149
+ .unwrap();
150
+ // The wf must have started more than # workflows times, since all but one must experience
151
+ // an eviction
152
+ assert!(RUN_CT.load(Ordering::SeqCst) > n_workflows);
153
+ }
154
+
155
+ // Ideally this would be a unit test, but returning a pending future with mockall bloats the mock
156
+ // code a bunch and just isn't worth it. Do it when https://github.com/asomers/mockall/issues/189 is
157
+ // fixed.
158
+ #[tokio::test]
159
+ async fn shutdown_aborts_actively_blocked_poll() {
160
+ let mut starter = CoreWfStarter::new("shutdown_aborts_actively_blocked_poll");
161
+ let core = starter.get_worker().await;
162
+ // Begin the poll, and request shutdown from another thread after a small period of time.
163
+ let tcore = core.clone();
164
+ let handle = tokio::spawn(async move {
165
+ std::thread::sleep(Duration::from_millis(100));
166
+ tcore.shutdown().await;
167
+ });
168
+ assert_matches!(
169
+ core.poll_workflow_activation().await.unwrap_err(),
170
+ PollWfError::ShutDown
171
+ );
172
+ handle.await.unwrap();
173
+ // Ensure double-shutdown doesn't explode
174
+ core.shutdown().await;
175
+ assert_matches!(
176
+ core.poll_workflow_activation().await.unwrap_err(),
177
+ PollWfError::ShutDown
178
+ );
179
+ }
180
+
181
+ #[rstest::rstest]
182
+ #[tokio::test]
183
+ async fn fail_wf_task(#[values(true, false)] replay: bool) {
184
+ let core = if replay {
185
+ // We need to send the history twice, since we fail it the first time.
186
+ let mut hist_proto = history_from_proto_binary("histories/fail_wf_task.bin")
187
+ .await
188
+ .unwrap();
189
+ let hist = HistoryForReplay::new(hist_proto.clone(), "fake".to_string());
190
+ if let Some(history_event::Attributes::WorkflowExecutionStartedEventAttributes(
191
+ ref mut attrs,
192
+ )) = hist_proto.events[0].attributes
193
+ {
194
+ attrs.original_execution_run_id = "run2".to_string();
195
+ attrs.first_execution_run_id = "run2".to_string();
196
+ }
197
+ let hist2 = HistoryForReplay::new(hist_proto, "fake".to_string());
198
+ init_core_replay_preloaded("fail_wf_task", [hist, hist2])
199
+ } else {
200
+ let mut starter = init_core_and_create_wf("fail_wf_task").await;
201
+ starter.get_worker().await
202
+ };
203
+ // Start with a timer
204
+ let task = core.poll_workflow_activation().await.unwrap();
205
+ core.complete_timer(&task.run_id, 0, Duration::from_millis(200))
206
+ .await;
207
+
208
+ // Then break for whatever reason
209
+ let task = core.poll_workflow_activation().await.unwrap();
210
+ core.complete_workflow_activation(WorkflowActivationCompletion::fail(
211
+ task.run_id,
212
+ Failure::application_failure("I did an oopsie".to_string(), false),
213
+ ))
214
+ .await
215
+ .unwrap();
216
+
217
+ // The server will want to retry the task. This time we finish the workflow -- but we need
218
+ // to poll a couple of times as there will be more than one required workflow activation.
219
+ let task = core.poll_workflow_activation().await.unwrap();
220
+ // The first poll response will tell us to evict
221
+ assert_matches!(
222
+ task.jobs.as_slice(),
223
+ [WorkflowActivationJob {
224
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
225
+ }]
226
+ );
227
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
228
+ .await
229
+ .unwrap();
230
+
231
+ let task = core.poll_workflow_activation().await.unwrap();
232
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
233
+ task.run_id,
234
+ vec![StartTimer {
235
+ seq: 0,
236
+ start_to_fire_timeout: Some(prost_dur!(from_millis(200))),
237
+ }
238
+ .into()],
239
+ ))
240
+ .await
241
+ .unwrap();
242
+ let task = core.poll_workflow_activation().await.unwrap();
243
+ core.complete_execution(&task.run_id).await;
244
+ }
245
+
246
+ #[tokio::test]
247
+ async fn fail_workflow_execution() {
248
+ let core = init_core_and_create_wf("fail_workflow_execution")
249
+ .await
250
+ .get_worker()
251
+ .await;
252
+ let task = core.poll_workflow_activation().await.unwrap();
253
+ core.complete_timer(&task.run_id, 0, Duration::from_secs(1))
254
+ .await;
255
+ let task = core.poll_workflow_activation().await.unwrap();
256
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
257
+ task.run_id,
258
+ vec![FailWorkflowExecution {
259
+ failure: Some(Failure::application_failure("I'm ded".to_string(), false)),
260
+ }
261
+ .into()],
262
+ ))
263
+ .await
264
+ .unwrap();
265
+ }
266
+
267
+ #[tokio::test]
268
+ async fn signal_workflow() {
269
+ let mut starter = init_core_and_create_wf("signal_workflow").await;
270
+ let core = starter.get_worker().await;
271
+ let client = starter.get_client().await;
272
+ let workflow_id = starter.get_task_queue().to_string();
273
+
274
+ let signal_id_1 = "signal1";
275
+ let signal_id_2 = "signal2";
276
+ let res = core.poll_workflow_activation().await.unwrap();
277
+ // Task is completed with no commands
278
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
279
+ res.run_id.clone(),
280
+ vec![],
281
+ ))
282
+ .await
283
+ .unwrap();
284
+
285
+ // Send the signals to the server
286
+ client
287
+ .signal_workflow_execution(
288
+ workflow_id.to_string(),
289
+ res.run_id.to_string(),
290
+ signal_id_1.to_string(),
291
+ None,
292
+ None,
293
+ )
294
+ .await
295
+ .unwrap();
296
+ client
297
+ .signal_workflow_execution(
298
+ workflow_id.to_string(),
299
+ res.run_id.to_string(),
300
+ signal_id_2.to_string(),
301
+ None,
302
+ None,
303
+ )
304
+ .await
305
+ .unwrap();
306
+
307
+ let mut res = core.poll_workflow_activation().await.unwrap();
308
+ // Sometimes both signals are complete at once, sometimes only one, depending on server
309
+ // Converting test to wf function type would make this shorter
310
+ if res.jobs.len() == 2 {
311
+ assert_matches!(
312
+ res.jobs.as_slice(),
313
+ [
314
+ WorkflowActivationJob {
315
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
316
+ },
317
+ WorkflowActivationJob {
318
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
319
+ }
320
+ ]
321
+ );
322
+ } else if res.jobs.len() == 1 {
323
+ assert_matches!(
324
+ res.jobs.as_slice(),
325
+ [WorkflowActivationJob {
326
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
327
+ },]
328
+ );
329
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
330
+ res.run_id,
331
+ vec![],
332
+ ))
333
+ .await
334
+ .unwrap();
335
+ res = core.poll_workflow_activation().await.unwrap();
336
+ assert_matches!(
337
+ res.jobs.as_slice(),
338
+ [WorkflowActivationJob {
339
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
340
+ },]
341
+ );
342
+ }
343
+ core.complete_execution(&res.run_id).await;
344
+ }
345
+
346
+ #[tokio::test]
347
+ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
348
+ let mut starter =
349
+ init_core_and_create_wf("signal_workflow_signal_not_handled_on_workflow_completion").await;
350
+ let core = starter.get_worker().await;
351
+ let workflow_id = starter.get_task_queue().to_string();
352
+ let signal_id_1 = "signal1";
353
+ for i in 1..=2 {
354
+ let res = core.poll_workflow_activation().await.unwrap();
355
+ // Task is completed with a timer
356
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
357
+ res.run_id,
358
+ vec![StartTimer {
359
+ seq: 0,
360
+ start_to_fire_timeout: Some(prost_dur!(from_millis(10))),
361
+ }
362
+ .into()],
363
+ ))
364
+ .await
365
+ .unwrap();
366
+
367
+ let res = core.poll_workflow_activation().await.unwrap();
368
+
369
+ if i == 1 {
370
+ // First attempt we should only see the timer being fired
371
+ assert_matches!(
372
+ res.jobs.as_slice(),
373
+ [WorkflowActivationJob {
374
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
375
+ }]
376
+ );
377
+
378
+ let run_id = res.run_id.clone();
379
+
380
+ // Send the signal to the server
381
+ starter
382
+ .get_client()
383
+ .await
384
+ .signal_workflow_execution(
385
+ workflow_id.clone(),
386
+ res.run_id.to_string(),
387
+ signal_id_1.to_string(),
388
+ None,
389
+ None,
390
+ )
391
+ .await
392
+ .unwrap();
393
+
394
+ // Send completion - not having seen a poll response with a signal in it yet (unhandled
395
+ // command error will be logged as a warning and an eviction will be issued)
396
+ core.complete_execution(&run_id).await;
397
+
398
+ // We should be told to evict
399
+ let res = core.poll_workflow_activation().await.unwrap();
400
+ assert_matches!(
401
+ res.jobs.as_slice(),
402
+ [WorkflowActivationJob {
403
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
404
+ }]
405
+ );
406
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(res.run_id))
407
+ .await
408
+ .unwrap();
409
+ // Loop to the top to handle wf from the beginning
410
+ continue;
411
+ }
412
+
413
+ // On the second attempt, we will see the signal we failed to handle as well as the timer
414
+ assert_matches!(
415
+ res.jobs.as_slice(),
416
+ [
417
+ WorkflowActivationJob {
418
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
419
+ },
420
+ WorkflowActivationJob {
421
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
422
+ }
423
+ ]
424
+ );
425
+ core.complete_execution(&res.run_id).await;
426
+ }
427
+ }
428
+
429
+ #[tokio::test]
430
+ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
431
+ let activity_id = "act-1";
432
+ let signal_at_start = "at-start";
433
+ let signal_at_complete = "at-complete";
434
+ let mut wf_starter = CoreWfStarter::new("wft_timeout_doesnt_create_unsolvable_autocomplete");
435
+ wf_starter
436
+ // Test needs eviction on and a short timeout
437
+ .max_cached_workflows(0)
438
+ .max_wft(1)
439
+ .wft_timeout(Duration::from_secs(1));
440
+ let core = wf_starter.get_worker().await;
441
+ let client = wf_starter.get_client().await;
442
+ let task_q = wf_starter.get_task_queue();
443
+ let wf_id = &wf_starter.get_wf_id().to_owned();
444
+
445
+ // Set up some helpers for polling and completing
446
+ let poll_sched_act = || async {
447
+ let wf_task = core.poll_workflow_activation().await.unwrap();
448
+ core.complete_workflow_activation(
449
+ schedule_activity_cmd(
450
+ 0,
451
+ task_q,
452
+ activity_id,
453
+ ActivityCancellationType::TryCancel,
454
+ Duration::from_secs(60),
455
+ Duration::from_secs(60),
456
+ )
457
+ .into_completion(wf_task.run_id.clone()),
458
+ )
459
+ .await
460
+ .unwrap();
461
+ wf_task
462
+ };
463
+ wf_starter.start_wf().await;
464
+
465
+ // Poll and schedule the activity
466
+ let wf_task = poll_sched_act().await;
467
+ // Before polling for a task again, we start and complete the activity and send the
468
+ // corresponding signals.
469
+ let ac_task = core.poll_activity_task().await.unwrap();
470
+ let rid = wf_task.run_id.clone();
471
+ // Send the signals to the server & resolve activity -- sometimes this happens too fast
472
+ sleep(Duration::from_millis(200)).await;
473
+ client
474
+ .signal_workflow_execution(
475
+ wf_id.to_string(),
476
+ rid,
477
+ signal_at_start.to_string(),
478
+ None,
479
+ None,
480
+ )
481
+ .await
482
+ .unwrap();
483
+ // Complete activity successfully.
484
+ core.complete_activity_task(ActivityTaskCompletion {
485
+ task_token: ac_task.task_token,
486
+ result: Some(ActivityExecutionResult::ok(Default::default())),
487
+ })
488
+ .await
489
+ .unwrap();
490
+ let rid = wf_task.run_id.clone();
491
+ client
492
+ .signal_workflow_execution(
493
+ wf_id.to_string(),
494
+ rid,
495
+ signal_at_complete.to_string(),
496
+ None,
497
+ None,
498
+ )
499
+ .await
500
+ .unwrap();
501
+ // Now poll again, it will be an eviction b/c non-sticky mode.
502
+ let wf_task = core.poll_workflow_activation().await.unwrap();
503
+ assert_matches!(
504
+ wf_task.jobs.as_slice(),
505
+ [WorkflowActivationJob {
506
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
507
+ }]
508
+ );
509
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
510
+ .await
511
+ .unwrap();
512
+ // Start from the beginning
513
+ poll_sched_act().await;
514
+ let wf_task = core.poll_workflow_activation().await.unwrap();
515
+ // Time out this time
516
+ sleep(Duration::from_secs(2)).await;
517
+ // Poll again, which should not have any work to do and spin, until the complete goes through.
518
+ // Which will be rejected with not found, producing an eviction.
519
+ let (wf_task, _) = tokio::join!(
520
+ async { core.poll_workflow_activation().await.unwrap() },
521
+ async {
522
+ sleep(Duration::from_millis(500)).await;
523
+ // Reply to the first one, finally
524
+ core.complete_execution(&wf_task.run_id).await;
525
+ }
526
+ );
527
+ assert_matches!(
528
+ wf_task.jobs.as_slice(),
529
+ [WorkflowActivationJob {
530
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
531
+ }]
532
+ );
533
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
534
+ .await
535
+ .unwrap();
536
+ // Do it all over again, without timing out this time
537
+ poll_sched_act().await;
538
+ let wf_task = core.poll_workflow_activation().await.unwrap();
539
+ // Server can sometimes arbitrarily re-order the activity complete to be after the second signal
540
+ // Seeing 3 jobs is enough info.
541
+ assert_eq!(wf_task.jobs.len(), 3);
542
+ core.complete_execution(&wf_task.run_id).await;
543
+ }
544
+
545
+ /// We had a bug related to polling being faster than completion causing issues with cache
546
+ /// overflow. This test intentionally makes completes slower than polls to evaluate that.
547
+ ///
548
+ /// It's expected that this test may generate some task timeouts.
549
+ #[tokio::test]
550
+ async fn slow_completes_with_small_cache() {
551
+ let wf_name = "slow_completes_with_small_cache";
552
+ let mut starter = CoreWfStarter::new(wf_name);
553
+ starter.max_wft(5).max_cached_workflows(5);
554
+ let mut worker = starter.worker().await;
555
+ worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
556
+ for _ in 0..3 {
557
+ ctx.activity(ActivityOptions {
558
+ activity_type: "echo_activity".to_string(),
559
+ start_to_close_timeout: Some(Duration::from_secs(5)),
560
+ input: "hi!".as_json_payload().expect("serializes fine"),
561
+ ..Default::default()
562
+ })
563
+ .await;
564
+ ctx.timer(Duration::from_secs(1)).await;
565
+ }
566
+ Ok(().into())
567
+ });
568
+ worker.register_activity(
569
+ "echo_activity",
570
+ |_ctx: ActContext, echo_me: String| async move { Ok(echo_me) },
571
+ );
572
+ for i in 0..20 {
573
+ worker
574
+ .submit_wf(
575
+ format!("{}_{}", wf_name, i),
576
+ wf_name.to_owned(),
577
+ vec![],
578
+ WorkflowOptions::default(),
579
+ )
580
+ .await
581
+ .unwrap();
582
+ }
583
+
584
+ struct SlowCompleter {}
585
+ #[async_trait::async_trait(?Send)]
586
+ impl WorkerInterceptor for SlowCompleter {
587
+ async fn on_workflow_activation_completion(&self, _: &WorkflowActivationCompletion) {
588
+ // They don't need to be much slower
589
+ tokio::time::sleep(Duration::from_millis(100)).await;
590
+ }
591
+ fn on_shutdown(&self, _: &temporal_sdk::Worker) {}
592
+ }
593
+ worker
594
+ .run_until_done_intercepted(Some(SlowCompleter {}))
595
+ .await
596
+ .unwrap();
597
+ }