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,587 @@
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 patches;
10
+ mod replay;
11
+ mod resets;
12
+ mod signals;
13
+ mod stickyness;
14
+ mod timers;
15
+ mod upsert_search_attrs;
16
+
17
+ use assert_matches::assert_matches;
18
+ use futures::{channel::mpsc::UnboundedReceiver, future, SinkExt, StreamExt};
19
+ use std::{
20
+ collections::HashMap,
21
+ sync::{
22
+ atomic::{AtomicUsize, Ordering},
23
+ Arc,
24
+ },
25
+ time::Duration,
26
+ };
27
+ use temporal_client::{WorkflowClientTrait, WorkflowOptions};
28
+ use temporal_sdk::{
29
+ interceptors::WorkerInterceptor, ActContext, ActivityOptions, WfContext, WorkflowResult,
30
+ };
31
+ use temporal_sdk_core_api::{errors::PollWfError, Worker};
32
+ use temporal_sdk_core_protos::{
33
+ coresdk::{
34
+ activity_result::ActivityExecutionResult,
35
+ workflow_activation::{workflow_activation_job, WorkflowActivation, WorkflowActivationJob},
36
+ workflow_commands::{ActivityCancellationType, FailWorkflowExecution, StartTimer},
37
+ workflow_completion::WorkflowActivationCompletion,
38
+ ActivityTaskCompletion, AsJsonPayloadExt, IntoCompletion,
39
+ },
40
+ temporal::api::failure::v1::Failure,
41
+ };
42
+ use temporal_sdk_core_test_utils::{
43
+ history_from_proto_binary, init_core_and_create_wf, init_core_replay_preloaded,
44
+ schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
45
+ };
46
+ use tokio::time::sleep;
47
+ use uuid::Uuid;
48
+
49
+ // TODO: We should get expected histories for these tests and confirm that the history at the end
50
+ // matches.
51
+
52
+ #[tokio::test]
53
+ async fn parallel_workflows_same_queue() {
54
+ let mut starter = CoreWfStarter::new("parallel_workflows_same_queue");
55
+ let core = starter.get_worker().await;
56
+ let num_workflows = 25usize;
57
+
58
+ let run_ids: Vec<_> = future::join_all(
59
+ (0..num_workflows)
60
+ .map(|i| starter.start_wf_with_id(format!("wf-id-{}", i), WorkflowOptions::default())),
61
+ )
62
+ .await;
63
+
64
+ let mut send_chans = HashMap::new();
65
+ async fn wf_task(
66
+ worker: Arc<dyn Worker>,
67
+ mut task_chan: UnboundedReceiver<WorkflowActivation>,
68
+ ) {
69
+ let task = task_chan.next().await.unwrap();
70
+ assert_matches!(
71
+ task.jobs.as_slice(),
72
+ [WorkflowActivationJob {
73
+ variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
74
+ }]
75
+ );
76
+ worker
77
+ .complete_timer(&task.run_id, 1, Duration::from_secs(1))
78
+ .await;
79
+ let task = task_chan.next().await.unwrap();
80
+ worker.complete_execution(&task.run_id).await;
81
+ }
82
+
83
+ let handles: Vec<_> = run_ids
84
+ .iter()
85
+ .map(|run_id| {
86
+ let (tx, rx) = futures::channel::mpsc::unbounded();
87
+ send_chans.insert(run_id.clone(), tx);
88
+ tokio::spawn(wf_task(core.clone(), rx))
89
+ })
90
+ .collect();
91
+
92
+ for _ in 0..num_workflows * 2 {
93
+ let task = core.poll_workflow_activation().await.unwrap();
94
+ send_chans
95
+ .get(&task.run_id)
96
+ .unwrap()
97
+ .send(task)
98
+ .await
99
+ .unwrap();
100
+ }
101
+
102
+ for handle in handles {
103
+ handle.await.unwrap()
104
+ }
105
+ }
106
+
107
+ static RUN_CT: AtomicUsize = AtomicUsize::new(0);
108
+ pub async fn cache_evictions_wf(command_sink: WfContext) -> WorkflowResult<()> {
109
+ RUN_CT.fetch_add(1, Ordering::SeqCst);
110
+ command_sink.timer(Duration::from_secs(1)).await;
111
+ Ok(().into())
112
+ }
113
+
114
+ #[tokio::test]
115
+ async fn workflow_lru_cache_evictions() {
116
+ let wf_type = "workflow_lru_cache_evictions";
117
+ let mut starter = CoreWfStarter::new(wf_type);
118
+ starter.max_cached_workflows(1);
119
+ let mut worker = starter.worker().await;
120
+ worker.register_wf(wf_type.to_string(), cache_evictions_wf);
121
+
122
+ let n_workflows = 3;
123
+ for _ in 0..n_workflows {
124
+ worker
125
+ .submit_wf(
126
+ format!("wce-{}", Uuid::new_v4()),
127
+ wf_type.to_string(),
128
+ vec![],
129
+ WorkflowOptions::default(),
130
+ )
131
+ .await
132
+ .unwrap();
133
+ }
134
+ struct CacheAsserter;
135
+ #[async_trait::async_trait(?Send)]
136
+ impl WorkerInterceptor for CacheAsserter {
137
+ async fn on_workflow_activation_completion(&self, _: &WorkflowActivationCompletion) {}
138
+ fn on_shutdown(&self, sdk_worker: &temporal_sdk::Worker) {
139
+ // 0 since the sdk worker force-evicts and drains everything on shutdown.
140
+ assert_eq!(sdk_worker.cached_workflows(), 0);
141
+ }
142
+ }
143
+ worker
144
+ .run_until_done_intercepted(Some(CacheAsserter))
145
+ .await
146
+ .unwrap();
147
+ // The wf must have started more than # workflows times, since all but one must experience
148
+ // an eviction
149
+ assert!(RUN_CT.load(Ordering::SeqCst) > n_workflows);
150
+ }
151
+
152
+ // Ideally this would be a unit test, but returning a pending future with mockall bloats the mock
153
+ // code a bunch and just isn't worth it. Do it when https://github.com/asomers/mockall/issues/189 is
154
+ // fixed.
155
+ #[tokio::test]
156
+ async fn shutdown_aborts_actively_blocked_poll() {
157
+ let mut starter = CoreWfStarter::new("shutdown_aborts_actively_blocked_poll");
158
+ let core = starter.get_worker().await;
159
+ // Begin the poll, and request shutdown from another thread after a small period of time.
160
+ let tcore = core.clone();
161
+ let handle = tokio::spawn(async move {
162
+ std::thread::sleep(Duration::from_millis(100));
163
+ tcore.shutdown().await;
164
+ });
165
+ assert_matches!(
166
+ core.poll_workflow_activation().await.unwrap_err(),
167
+ PollWfError::ShutDown
168
+ );
169
+ handle.await.unwrap();
170
+ // Ensure double-shutdown doesn't explode
171
+ core.shutdown().await;
172
+ assert_matches!(
173
+ core.poll_workflow_activation().await.unwrap_err(),
174
+ PollWfError::ShutDown
175
+ );
176
+ }
177
+
178
+ #[rstest::rstest]
179
+ #[tokio::test]
180
+ async fn fail_wf_task(#[values(true, false)] replay: bool) {
181
+ let core = if replay {
182
+ let (core, _) = init_core_replay_preloaded(
183
+ "fail_wf_task",
184
+ &history_from_proto_binary("histories/fail_wf_task.bin")
185
+ .await
186
+ .unwrap(),
187
+ );
188
+ core
189
+ } else {
190
+ let mut starter = init_core_and_create_wf("fail_wf_task").await;
191
+ starter.get_worker().await
192
+ };
193
+ // Start with a timer
194
+ let task = core.poll_workflow_activation().await.unwrap();
195
+ core.complete_timer(&task.run_id, 0, Duration::from_millis(200))
196
+ .await;
197
+
198
+ // Then break for whatever reason
199
+ let task = core.poll_workflow_activation().await.unwrap();
200
+ core.complete_workflow_activation(WorkflowActivationCompletion::fail(
201
+ task.run_id,
202
+ Failure::application_failure("I did an oopsie".to_string(), false),
203
+ ))
204
+ .await
205
+ .unwrap();
206
+
207
+ // The server will want to retry the task. This time we finish the workflow -- but we need
208
+ // to poll a couple of times as there will be more than one required workflow activation.
209
+ let task = core.poll_workflow_activation().await.unwrap();
210
+ // The first poll response will tell us to evict
211
+ assert_matches!(
212
+ task.jobs.as_slice(),
213
+ [WorkflowActivationJob {
214
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
215
+ }]
216
+ );
217
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
218
+ .await
219
+ .unwrap();
220
+
221
+ let task = core.poll_workflow_activation().await.unwrap();
222
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
223
+ task.run_id,
224
+ vec![StartTimer {
225
+ seq: 0,
226
+ start_to_fire_timeout: Some(prost_dur!(from_millis(200))),
227
+ }
228
+ .into()],
229
+ ))
230
+ .await
231
+ .unwrap();
232
+ let task = core.poll_workflow_activation().await.unwrap();
233
+ core.complete_execution(&task.run_id).await;
234
+ }
235
+
236
+ #[tokio::test]
237
+ async fn fail_workflow_execution() {
238
+ let core = init_core_and_create_wf("fail_workflow_execution")
239
+ .await
240
+ .get_worker()
241
+ .await;
242
+ let task = core.poll_workflow_activation().await.unwrap();
243
+ core.complete_timer(&task.run_id, 0, Duration::from_secs(1))
244
+ .await;
245
+ let task = core.poll_workflow_activation().await.unwrap();
246
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
247
+ task.run_id,
248
+ vec![FailWorkflowExecution {
249
+ failure: Some(Failure::application_failure("I'm ded".to_string(), false)),
250
+ }
251
+ .into()],
252
+ ))
253
+ .await
254
+ .unwrap();
255
+ }
256
+
257
+ #[tokio::test]
258
+ async fn signal_workflow() {
259
+ let mut starter = init_core_and_create_wf("signal_workflow").await;
260
+ let core = starter.get_worker().await;
261
+ let client = starter.get_client().await;
262
+ let workflow_id = starter.get_task_queue().to_string();
263
+
264
+ let signal_id_1 = "signal1";
265
+ let signal_id_2 = "signal2";
266
+ let res = core.poll_workflow_activation().await.unwrap();
267
+ // Task is completed with no commands
268
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
269
+ res.run_id.clone(),
270
+ vec![],
271
+ ))
272
+ .await
273
+ .unwrap();
274
+
275
+ // Send the signals to the server
276
+ client
277
+ .signal_workflow_execution(
278
+ workflow_id.to_string(),
279
+ res.run_id.to_string(),
280
+ signal_id_1.to_string(),
281
+ None,
282
+ None,
283
+ )
284
+ .await
285
+ .unwrap();
286
+ client
287
+ .signal_workflow_execution(
288
+ workflow_id.to_string(),
289
+ res.run_id.to_string(),
290
+ signal_id_2.to_string(),
291
+ None,
292
+ None,
293
+ )
294
+ .await
295
+ .unwrap();
296
+
297
+ let mut res = core.poll_workflow_activation().await.unwrap();
298
+ // Sometimes both signals are complete at once, sometimes only one, depending on server
299
+ // Converting test to wf function type would make this shorter
300
+ if res.jobs.len() == 2 {
301
+ assert_matches!(
302
+ res.jobs.as_slice(),
303
+ [
304
+ WorkflowActivationJob {
305
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
306
+ },
307
+ WorkflowActivationJob {
308
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
309
+ }
310
+ ]
311
+ );
312
+ } else if res.jobs.len() == 1 {
313
+ assert_matches!(
314
+ res.jobs.as_slice(),
315
+ [WorkflowActivationJob {
316
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
317
+ },]
318
+ );
319
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
320
+ res.run_id,
321
+ vec![],
322
+ ))
323
+ .await
324
+ .unwrap();
325
+ res = core.poll_workflow_activation().await.unwrap();
326
+ assert_matches!(
327
+ res.jobs.as_slice(),
328
+ [WorkflowActivationJob {
329
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
330
+ },]
331
+ );
332
+ }
333
+ core.complete_execution(&res.run_id).await;
334
+ }
335
+
336
+ #[tokio::test]
337
+ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
338
+ let mut starter =
339
+ init_core_and_create_wf("signal_workflow_signal_not_handled_on_workflow_completion").await;
340
+ let core = starter.get_worker().await;
341
+ let workflow_id = starter.get_task_queue().to_string();
342
+ let signal_id_1 = "signal1";
343
+ for i in 1..=2 {
344
+ let res = core.poll_workflow_activation().await.unwrap();
345
+ // Task is completed with a timer
346
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
347
+ res.run_id,
348
+ vec![StartTimer {
349
+ seq: 0,
350
+ start_to_fire_timeout: Some(prost_dur!(from_millis(10))),
351
+ }
352
+ .into()],
353
+ ))
354
+ .await
355
+ .unwrap();
356
+
357
+ let res = core.poll_workflow_activation().await.unwrap();
358
+
359
+ if i == 1 {
360
+ // First attempt we should only see the timer being fired
361
+ assert_matches!(
362
+ res.jobs.as_slice(),
363
+ [WorkflowActivationJob {
364
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
365
+ }]
366
+ );
367
+
368
+ let run_id = res.run_id.clone();
369
+
370
+ // Send the signal to the server
371
+ starter
372
+ .get_client()
373
+ .await
374
+ .signal_workflow_execution(
375
+ workflow_id.clone(),
376
+ res.run_id.to_string(),
377
+ signal_id_1.to_string(),
378
+ None,
379
+ None,
380
+ )
381
+ .await
382
+ .unwrap();
383
+
384
+ // Send completion - not having seen a poll response with a signal in it yet (unhandled
385
+ // command error will be logged as a warning and an eviction will be issued)
386
+ core.complete_execution(&run_id).await;
387
+
388
+ // We should be told to evict
389
+ let res = core.poll_workflow_activation().await.unwrap();
390
+ assert_matches!(
391
+ res.jobs.as_slice(),
392
+ [WorkflowActivationJob {
393
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
394
+ }]
395
+ );
396
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(res.run_id))
397
+ .await
398
+ .unwrap();
399
+ // Loop to the top to handle wf from the beginning
400
+ continue;
401
+ }
402
+
403
+ // On the second attempt, we will see the signal we failed to handle as well as the timer
404
+ assert_matches!(
405
+ res.jobs.as_slice(),
406
+ [
407
+ WorkflowActivationJob {
408
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
409
+ },
410
+ WorkflowActivationJob {
411
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
412
+ }
413
+ ]
414
+ );
415
+ core.complete_execution(&res.run_id).await;
416
+ }
417
+ }
418
+
419
+ #[tokio::test]
420
+ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
421
+ let activity_id = "act-1";
422
+ let signal_at_start = "at-start";
423
+ let signal_at_complete = "at-complete";
424
+ let mut wf_starter = CoreWfStarter::new("wft_timeout_doesnt_create_unsolvable_autocomplete");
425
+ wf_starter
426
+ // Test needs eviction on and a short timeout
427
+ .max_cached_workflows(0)
428
+ .max_wft(1)
429
+ .wft_timeout(Duration::from_secs(1));
430
+ let core = wf_starter.get_worker().await;
431
+ let client = wf_starter.get_client().await;
432
+ let task_q = wf_starter.get_task_queue();
433
+ let wf_id = &wf_starter.get_wf_id().to_owned();
434
+
435
+ // Set up some helpers for polling and completing
436
+ let poll_sched_act = || async {
437
+ let wf_task = core.poll_workflow_activation().await.unwrap();
438
+ core.complete_workflow_activation(
439
+ schedule_activity_cmd(
440
+ 0,
441
+ task_q,
442
+ activity_id,
443
+ ActivityCancellationType::TryCancel,
444
+ Duration::from_secs(60),
445
+ Duration::from_secs(60),
446
+ )
447
+ .into_completion(wf_task.run_id.clone()),
448
+ )
449
+ .await
450
+ .unwrap();
451
+ wf_task
452
+ };
453
+ wf_starter.start_wf().await;
454
+
455
+ // Poll and schedule the activity
456
+ let wf_task = poll_sched_act().await;
457
+ // Before polling for a task again, we start and complete the activity and send the
458
+ // corresponding signals.
459
+ let ac_task = core.poll_activity_task().await.unwrap();
460
+ let rid = wf_task.run_id.clone();
461
+ // Send the signals to the server & resolve activity -- sometimes this happens too fast
462
+ sleep(Duration::from_millis(200)).await;
463
+ client
464
+ .signal_workflow_execution(
465
+ wf_id.to_string(),
466
+ rid,
467
+ signal_at_start.to_string(),
468
+ None,
469
+ None,
470
+ )
471
+ .await
472
+ .unwrap();
473
+ // Complete activity successfully.
474
+ core.complete_activity_task(ActivityTaskCompletion {
475
+ task_token: ac_task.task_token,
476
+ result: Some(ActivityExecutionResult::ok(Default::default())),
477
+ })
478
+ .await
479
+ .unwrap();
480
+ let rid = wf_task.run_id.clone();
481
+ client
482
+ .signal_workflow_execution(
483
+ wf_id.to_string(),
484
+ rid,
485
+ signal_at_complete.to_string(),
486
+ None,
487
+ None,
488
+ )
489
+ .await
490
+ .unwrap();
491
+ // Now poll again, it will be an eviction b/c non-sticky mode.
492
+ let wf_task = core.poll_workflow_activation().await.unwrap();
493
+ assert_matches!(
494
+ wf_task.jobs.as_slice(),
495
+ [WorkflowActivationJob {
496
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
497
+ }]
498
+ );
499
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
500
+ .await
501
+ .unwrap();
502
+ // Start from the beginning
503
+ poll_sched_act().await;
504
+ let wf_task = core.poll_workflow_activation().await.unwrap();
505
+ // Time out this time
506
+ sleep(Duration::from_secs(2)).await;
507
+ // Poll again, which should not have any work to do and spin, until the complete goes through.
508
+ // Which will be rejected with not found, producing an eviction.
509
+ let (wf_task, _) = tokio::join!(
510
+ async { core.poll_workflow_activation().await.unwrap() },
511
+ async {
512
+ sleep(Duration::from_millis(500)).await;
513
+ // Reply to the first one, finally
514
+ core.complete_execution(&wf_task.run_id).await;
515
+ }
516
+ );
517
+ assert_matches!(
518
+ wf_task.jobs.as_slice(),
519
+ [WorkflowActivationJob {
520
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
521
+ }]
522
+ );
523
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
524
+ .await
525
+ .unwrap();
526
+ // Do it all over again, without timing out this time
527
+ poll_sched_act().await;
528
+ let wf_task = core.poll_workflow_activation().await.unwrap();
529
+ // Server can sometimes arbitrarily re-order the activity complete to be after the second signal
530
+ // Seeing 3 jobs is enough info.
531
+ assert_eq!(wf_task.jobs.len(), 3);
532
+ core.complete_execution(&wf_task.run_id).await;
533
+ }
534
+
535
+ /// We had a bug related to polling being faster than completion causing issues with cache
536
+ /// overflow. This test intentionally makes completes slower than polls to evaluate that.
537
+ ///
538
+ /// It's expected that this test may generate some task timeouts.
539
+ #[tokio::test]
540
+ async fn slow_completes_with_small_cache() {
541
+ let wf_name = "slow_completes_with_small_cache";
542
+ let mut starter = CoreWfStarter::new(wf_name);
543
+ starter.max_wft(5).max_cached_workflows(5);
544
+ let mut worker = starter.worker().await;
545
+ worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
546
+ for _ in 0..3 {
547
+ ctx.activity(ActivityOptions {
548
+ activity_type: "echo_activity".to_string(),
549
+ start_to_close_timeout: Some(Duration::from_secs(5)),
550
+ input: "hi!".as_json_payload().expect("serializes fine"),
551
+ ..Default::default()
552
+ })
553
+ .await;
554
+ ctx.timer(Duration::from_secs(1)).await;
555
+ }
556
+ Ok(().into())
557
+ });
558
+ worker.register_activity(
559
+ "echo_activity",
560
+ |_ctx: ActContext, echo_me: String| async move { Ok(echo_me) },
561
+ );
562
+ for i in 0..20 {
563
+ worker
564
+ .submit_wf(
565
+ format!("{}_{}", wf_name, i),
566
+ wf_name.to_owned(),
567
+ vec![],
568
+ WorkflowOptions::default(),
569
+ )
570
+ .await
571
+ .unwrap();
572
+ }
573
+
574
+ struct SlowCompleter {}
575
+ #[async_trait::async_trait(?Send)]
576
+ impl WorkerInterceptor for SlowCompleter {
577
+ async fn on_workflow_activation_completion(&self, _: &WorkflowActivationCompletion) {
578
+ // They don't need to be much slower
579
+ tokio::time::sleep(Duration::from_millis(100)).await;
580
+ }
581
+ fn on_shutdown(&self, _: &temporal_sdk::Worker) {}
582
+ }
583
+ worker
584
+ .run_until_done_intercepted(Some(SlowCompleter {}))
585
+ .await
586
+ .unwrap();
587
+ }