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,110 @@
1
+ use crate::worker::workflow::{WFCommand, WorkflowStartedInfo};
2
+ use temporal_sdk_core_protos::{
3
+ coresdk::workflow_activation::{
4
+ start_workflow_from_attribs, workflow_activation_job, CancelWorkflow, SignalWorkflow,
5
+ WorkflowActivationJob,
6
+ },
7
+ temporal::api::history::v1::WorkflowExecutionStartedEventAttributes,
8
+ utilities::TryIntoOrNone,
9
+ };
10
+
11
+ /// Abstracts away the concept of an actual workflow implementation, handling sending it new
12
+ /// jobs and fetching output from it.
13
+ pub struct DrivenWorkflow {
14
+ started_attrs: Option<WorkflowStartedInfo>,
15
+ fetcher: Box<dyn WorkflowFetcher>,
16
+ /// Outgoing activation jobs that need to be sent to the lang sdk
17
+ outgoing_wf_activation_jobs: Vec<workflow_activation_job::Variant>,
18
+ }
19
+
20
+ impl<WF> From<Box<WF>> for DrivenWorkflow
21
+ where
22
+ WF: WorkflowFetcher + 'static,
23
+ {
24
+ fn from(wf: Box<WF>) -> Self {
25
+ Self {
26
+ started_attrs: None,
27
+ fetcher: wf,
28
+ outgoing_wf_activation_jobs: Default::default(),
29
+ }
30
+ }
31
+ }
32
+
33
+ impl DrivenWorkflow {
34
+ /// Start the workflow
35
+ pub fn start(
36
+ &mut self,
37
+ workflow_id: String,
38
+ randomness_seed: u64,
39
+ attribs: WorkflowExecutionStartedEventAttributes,
40
+ ) {
41
+ debug!(run_id = %attribs.original_execution_run_id, "Driven WF start");
42
+ let started_info = WorkflowStartedInfo {
43
+ workflow_task_timeout: attribs.workflow_task_timeout.clone().try_into_or_none(),
44
+ workflow_execution_timeout: attribs
45
+ .workflow_execution_timeout
46
+ .clone()
47
+ .try_into_or_none(),
48
+ memo: attribs.memo.clone(),
49
+ search_attrs: attribs.search_attributes.clone(),
50
+ retry_policy: attribs.retry_policy.clone(),
51
+ };
52
+ self.send_job(start_workflow_from_attribs(attribs, workflow_id, randomness_seed).into());
53
+ self.started_attrs = Some(started_info);
54
+ }
55
+
56
+ /// Return the attributes from the workflow execution started event if this workflow has started
57
+ pub fn get_started_info(&self) -> Option<&WorkflowStartedInfo> {
58
+ self.started_attrs.as_ref()
59
+ }
60
+
61
+ /// Enqueue a new job to be sent to the driven workflow
62
+ pub fn send_job(&mut self, job: workflow_activation_job::Variant) {
63
+ self.outgoing_wf_activation_jobs.push(job);
64
+ }
65
+
66
+ /// Observe pending jobs
67
+ pub fn peek_pending_jobs(&self) -> &[workflow_activation_job::Variant] {
68
+ self.outgoing_wf_activation_jobs.as_slice()
69
+ }
70
+
71
+ /// Drain all pending jobs, so that they may be sent to the driven workflow
72
+ pub fn drain_jobs(&mut self) -> Vec<WorkflowActivationJob> {
73
+ self.outgoing_wf_activation_jobs
74
+ .drain(..)
75
+ .map(Into::into)
76
+ .collect()
77
+ }
78
+
79
+ /// Signal the workflow
80
+ pub fn signal(&mut self, signal: SignalWorkflow) {
81
+ self.send_job(workflow_activation_job::Variant::SignalWorkflow(signal));
82
+ }
83
+
84
+ /// Cancel the workflow
85
+ pub fn cancel(&mut self, attribs: CancelWorkflow) {
86
+ self.send_job(workflow_activation_job::Variant::CancelWorkflow(attribs));
87
+ }
88
+ }
89
+
90
+ #[async_trait::async_trait]
91
+ impl WorkflowFetcher for DrivenWorkflow {
92
+ async fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand> {
93
+ self.fetcher.fetch_workflow_iteration_output().await
94
+ }
95
+ }
96
+
97
+ /// Implementors of this trait represent a way to fetch output from executing/iterating some
98
+ /// workflow code (or a mocked workflow).
99
+ #[async_trait::async_trait]
100
+ pub trait WorkflowFetcher: Send {
101
+ /// Obtain any output from the workflow's recent execution(s). Because the lang sdk is
102
+ /// responsible for calling workflow code as a result of receiving tasks from
103
+ /// [crate::Core::poll_task], we cannot directly iterate it here. Thus implementations of this
104
+ /// trait are expected to either buffer output or otherwise produce it on demand when this
105
+ /// function is called.
106
+ ///
107
+ /// In the case of the real [WorkflowBridge] implementation, commands are simply pulled from
108
+ /// a buffer that the language side sinks into when it calls [crate::Core::complete_task]
109
+ async fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand>;
110
+ }
@@ -0,0 +1,458 @@
1
+ use crate::{
2
+ replay::{HistoryInfo, TestHistoryBuilder},
3
+ worker::client::WorkerClient,
4
+ };
5
+ use futures::{future::BoxFuture, stream, stream::BoxStream, FutureExt, Stream, StreamExt};
6
+ use std::{
7
+ collections::VecDeque,
8
+ fmt::Debug,
9
+ future::Future,
10
+ pin::Pin,
11
+ sync::Arc,
12
+ task::{Context, Poll},
13
+ };
14
+ use temporal_sdk_core_protos::temporal::api::{
15
+ enums::v1::EventType,
16
+ history::v1::{History, HistoryEvent},
17
+ workflowservice::v1::GetWorkflowExecutionHistoryResponse,
18
+ };
19
+ use tracing::Instrument;
20
+
21
+ /// A slimmed down version of a poll workflow task response which includes just the info needed
22
+ /// by [WorkflowManager]. History events are expected to be consumed from it and applied to the
23
+ /// state machines.
24
+ pub struct HistoryUpdate {
25
+ events: BoxStream<'static, Result<HistoryEvent, tonic::Status>>,
26
+ /// It is useful to be able to look ahead up to one workflow task beyond the currently
27
+ /// requested one. The initial (possibly only) motivation for this being to be able to
28
+ /// pre-emptively notify lang about patch markers so that calls to `changed` do not need to
29
+ /// be async.
30
+ buffered: VecDeque<HistoryEvent>,
31
+ pub previous_started_event_id: i64,
32
+ }
33
+ impl Debug for HistoryUpdate {
34
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35
+ write!(
36
+ f,
37
+ "HistoryUpdate(previous_started_event_id: {})",
38
+ self.previous_started_event_id
39
+ )
40
+ }
41
+ }
42
+
43
+ pub struct HistoryPaginator {
44
+ // Potentially this could actually be a ref w/ lifetime here
45
+ client: Arc<dyn WorkerClient>,
46
+ event_queue: VecDeque<HistoryEvent>,
47
+ wf_id: String,
48
+ run_id: String,
49
+ next_page_token: NextPageToken,
50
+ open_history_request:
51
+ Option<BoxFuture<'static, Result<GetWorkflowExecutionHistoryResponse, tonic::Status>>>,
52
+ /// These are events that should be returned once pagination has finished. This only happens
53
+ /// during cache misses, where we got a partial task but need to fetch history from the start.
54
+ /// We use this to apply any
55
+ final_events: Vec<HistoryEvent>,
56
+ }
57
+
58
+ #[derive(Clone, Debug)]
59
+ pub enum NextPageToken {
60
+ /// There is no page token, we need to fetch history from the beginning
61
+ FetchFromStart,
62
+ /// There is a page token
63
+ Next(Vec<u8>),
64
+ /// There is no page token, we are done fetching history
65
+ Done,
66
+ }
67
+
68
+ // If we're converting from a page token from the server, if it's empty, then we're done.
69
+ impl From<Vec<u8>> for NextPageToken {
70
+ fn from(page_token: Vec<u8>) -> Self {
71
+ if page_token.is_empty() {
72
+ NextPageToken::Done
73
+ } else {
74
+ NextPageToken::Next(page_token)
75
+ }
76
+ }
77
+ }
78
+
79
+ impl HistoryPaginator {
80
+ pub(crate) fn new(
81
+ initial_history: History,
82
+ wf_id: String,
83
+ run_id: String,
84
+ next_page_token: impl Into<NextPageToken>,
85
+ client: Arc<dyn WorkerClient>,
86
+ ) -> Self {
87
+ let next_page_token = next_page_token.into();
88
+ let (event_queue, final_events) =
89
+ if matches!(next_page_token, NextPageToken::FetchFromStart) {
90
+ (VecDeque::new(), initial_history.events)
91
+ } else {
92
+ (initial_history.events.into(), vec![])
93
+ };
94
+ Self {
95
+ client,
96
+ event_queue,
97
+ wf_id,
98
+ run_id,
99
+ next_page_token,
100
+ open_history_request: None,
101
+ final_events,
102
+ }
103
+ }
104
+
105
+ fn extend_queue_with_new_page(&mut self, resp: GetWorkflowExecutionHistoryResponse) {
106
+ self.next_page_token = resp.next_page_token.into();
107
+ self.event_queue
108
+ .extend(resp.history.map(|h| h.events).unwrap_or_default());
109
+ if matches!(&self.next_page_token, NextPageToken::Done) {
110
+ // If finished, we need to extend the queue with the final events, skipping any
111
+ // which are already present.
112
+ if let Some(last_event_id) = self.event_queue.back().map(|e| e.event_id) {
113
+ let final_events = std::mem::take(&mut self.final_events);
114
+ self.event_queue.extend(
115
+ final_events
116
+ .into_iter()
117
+ .skip_while(|e2| e2.event_id <= last_event_id),
118
+ );
119
+ }
120
+ };
121
+ }
122
+ }
123
+
124
+ impl Stream for HistoryPaginator {
125
+ type Item = Result<HistoryEvent, tonic::Status>;
126
+
127
+ fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
128
+ if let Some(e) = self.event_queue.pop_front() {
129
+ return Poll::Ready(Some(Ok(e)));
130
+ }
131
+ let history_req = if let Some(req) = self.open_history_request.as_mut() {
132
+ req
133
+ } else {
134
+ let npt = match std::mem::replace(&mut self.next_page_token, NextPageToken::Done) {
135
+ // If there's no open request and the last page token we got was empty, we're done.
136
+ NextPageToken::Done => return Poll::Ready(None),
137
+ NextPageToken::FetchFromStart => vec![],
138
+ NextPageToken::Next(v) => v,
139
+ };
140
+ debug!(run_id=%self.run_id, "Fetching new history page");
141
+ let gw = self.client.clone();
142
+ let wid = self.wf_id.clone();
143
+ let rid = self.run_id.clone();
144
+ let resp_fut = async move {
145
+ gw.get_workflow_execution_history(wid, Some(rid), npt)
146
+ .instrument(span!(tracing::Level::TRACE, "fetch_history_in_paginator"))
147
+ .await
148
+ };
149
+ self.open_history_request.insert(resp_fut.boxed())
150
+ };
151
+
152
+ return match Future::poll(history_req.as_mut(), cx) {
153
+ Poll::Ready(resp) => {
154
+ self.open_history_request = None;
155
+ match resp {
156
+ Err(neterr) => Poll::Ready(Some(Err(neterr))),
157
+ Ok(resp) => {
158
+ self.extend_queue_with_new_page(resp);
159
+ Poll::Ready(self.event_queue.pop_front().map(Ok))
160
+ }
161
+ }
162
+ }
163
+ Poll::Pending => Poll::Pending,
164
+ };
165
+ }
166
+ }
167
+
168
+ impl HistoryUpdate {
169
+ pub fn new(history_iterator: HistoryPaginator, previous_wft_started_id: i64) -> Self {
170
+ Self {
171
+ events: history_iterator.fuse().boxed(),
172
+ buffered: VecDeque::new(),
173
+ previous_started_event_id: previous_wft_started_id,
174
+ }
175
+ }
176
+
177
+ /// Create an instance of an update directly from events - should only be used for replaying.
178
+ pub fn new_from_events<I: IntoIterator<Item = HistoryEvent>>(
179
+ events: I,
180
+ previous_wft_started_id: i64,
181
+ ) -> Self
182
+ where
183
+ <I as IntoIterator>::IntoIter: Send + 'static,
184
+ {
185
+ Self {
186
+ events: stream::iter(events.into_iter().map(Ok)).boxed(),
187
+ buffered: VecDeque::new(),
188
+ previous_started_event_id: previous_wft_started_id,
189
+ }
190
+ }
191
+
192
+ /// Given a workflow task started id, return all events starting at that number (inclusive) to
193
+ /// the next WFT started event (inclusive). If there is no subsequent WFT started event,
194
+ /// remaining history is returned.
195
+ ///
196
+ /// Events are *consumed* by this process, to keep things efficient in workflow machines, and
197
+ /// the function may call out to server to fetch more pages if they are known to exist and
198
+ /// needed to complete the WFT sequence.
199
+ ///
200
+ /// Always buffers the WFT sequence *after* the returned one as well, if it is available.
201
+ ///
202
+ /// Can return a tonic error in the event that fetching additional history was needed and failed
203
+ pub async fn take_next_wft_sequence(
204
+ &mut self,
205
+ from_wft_started_id: i64,
206
+ ) -> Result<Vec<HistoryEvent>, tonic::Status> {
207
+ let (next_wft_events, maybe_bonus_event) = self
208
+ .take_next_wft_sequence_impl(from_wft_started_id)
209
+ .await?;
210
+ if let Some(be) = maybe_bonus_event {
211
+ self.buffered.push_back(be);
212
+ }
213
+
214
+ if let Some(last_event_id) = next_wft_events.last().map(|he| he.event_id) {
215
+ // Always attempt to fetch the *next* WFT sequence as well, to buffer it for lookahead
216
+ let (buffer_these_events, maybe_bonus_event) =
217
+ self.take_next_wft_sequence_impl(last_event_id).await?;
218
+ self.buffered.extend(buffer_these_events);
219
+ if let Some(be) = maybe_bonus_event {
220
+ self.buffered.push_back(be);
221
+ }
222
+ }
223
+
224
+ Ok(next_wft_events)
225
+ }
226
+
227
+ /// Lets the caller peek ahead at the next WFT sequence that will be returned by
228
+ /// [take_next_wft_sequence]. Will always return an empty iterator if that has not been called
229
+ /// first. May also return an empty iterator or incomplete sequence if we are at the end of
230
+ /// history.
231
+ pub fn peek_next_wft_sequence(&self) -> impl Iterator<Item = &HistoryEvent> {
232
+ self.buffered.iter()
233
+ }
234
+
235
+ async fn take_next_wft_sequence_impl(
236
+ &mut self,
237
+ from_event_id: i64,
238
+ ) -> Result<(Vec<HistoryEvent>, Option<HistoryEvent>), tonic::Status> {
239
+ let mut events_to_next_wft_started: Vec<HistoryEvent> = vec![];
240
+
241
+ // This flag tracks if, while determining events to be returned, we have seen the next
242
+ // logically significant WFT started event which follows the one that was passed in as a
243
+ // parameter. If a WFT fails or times out, it is not significant. So we will stop returning
244
+ // events (exclusive) as soon as we see an event following a WFT started that is *not*
245
+ // failed or timed out.
246
+ let mut saw_next_wft = false;
247
+ let mut should_pop = |e: &HistoryEvent| {
248
+ if e.event_id <= from_event_id {
249
+ return true;
250
+ } else if e.event_type == EventType::WorkflowTaskStarted as i32 {
251
+ saw_next_wft = true;
252
+ return true;
253
+ }
254
+
255
+ if saw_next_wft {
256
+ // Must ignore failures and timeouts
257
+ if e.event_type == EventType::WorkflowTaskFailed as i32
258
+ || e.event_type == EventType::WorkflowTaskTimedOut as i32
259
+ {
260
+ saw_next_wft = false;
261
+ return true;
262
+ }
263
+ return false;
264
+ }
265
+
266
+ true
267
+ };
268
+
269
+ // Fetch events from the buffer first, then from the network
270
+ let mut event_q = stream::iter(self.buffered.drain(..).map(Ok)).chain(&mut self.events);
271
+
272
+ let mut extra_e = None;
273
+ let mut last_seen_id = None;
274
+ while let Some(e) = event_q.next().await {
275
+ let e = e?;
276
+
277
+ // This little block prevents us from infinitely fetching work from the server in the
278
+ // event that, for whatever reason, it keeps returning stuff we've already seen.
279
+ if let Some(last_id) = last_seen_id {
280
+ if e.event_id <= last_id {
281
+ error!("Server returned history event IDs that went backwards!");
282
+ break;
283
+ }
284
+ }
285
+ last_seen_id = Some(e.event_id);
286
+
287
+ // It's possible to have gotten a new history update without eviction (ex: unhandled
288
+ // command on completion), where we may need to skip events we already handled.
289
+ if e.event_id > from_event_id {
290
+ if !should_pop(&e) {
291
+ extra_e = Some(e);
292
+ break;
293
+ }
294
+ events_to_next_wft_started.push(e);
295
+ }
296
+ }
297
+
298
+ Ok((events_to_next_wft_started, extra_e))
299
+ }
300
+ }
301
+
302
+ impl From<HistoryInfo> for HistoryUpdate {
303
+ fn from(v: HistoryInfo) -> Self {
304
+ Self::new_from_events(v.events().to_vec(), v.previous_started_event_id())
305
+ }
306
+ }
307
+
308
+ pub trait TestHBExt {
309
+ fn as_history_update(&self) -> HistoryUpdate;
310
+ }
311
+
312
+ impl TestHBExt for TestHistoryBuilder {
313
+ fn as_history_update(&self) -> HistoryUpdate {
314
+ self.get_full_history_info().unwrap().into()
315
+ }
316
+ }
317
+
318
+ #[cfg(test)]
319
+ pub mod tests {
320
+ use super::*;
321
+ use crate::{test_help::canned_histories, worker::client::mocks::mock_workflow_client};
322
+
323
+ #[tokio::test]
324
+ async fn consumes_standard_wft_sequence() {
325
+ let timer_hist = canned_histories::single_timer("t");
326
+ let mut update = timer_hist.as_history_update();
327
+ let seq_1 = update.take_next_wft_sequence(0).await.unwrap();
328
+ assert_eq!(seq_1.len(), 3);
329
+ assert_eq!(seq_1.last().unwrap().event_id, 3);
330
+ let seq_2 = update.take_next_wft_sequence(3).await.unwrap();
331
+ assert_eq!(seq_2.len(), 5);
332
+ assert_eq!(seq_2.last().unwrap().event_id, 8);
333
+ }
334
+
335
+ #[tokio::test]
336
+ async fn skips_wft_failed() {
337
+ let failed_hist = canned_histories::workflow_fails_with_reset_after_timer("t", "runid");
338
+ let mut update = failed_hist.as_history_update();
339
+ let seq_1 = update.take_next_wft_sequence(0).await.unwrap();
340
+ assert_eq!(seq_1.len(), 3);
341
+ assert_eq!(seq_1.last().unwrap().event_id, 3);
342
+ let seq_2 = update.take_next_wft_sequence(3).await.unwrap();
343
+ assert_eq!(seq_2.len(), 8);
344
+ assert_eq!(seq_2.last().unwrap().event_id, 11);
345
+ }
346
+
347
+ #[tokio::test]
348
+ async fn skips_wft_timeout() {
349
+ let failed_hist = canned_histories::wft_timeout_repro();
350
+ let mut update = failed_hist.as_history_update();
351
+ let seq_1 = update.take_next_wft_sequence(0).await.unwrap();
352
+ assert_eq!(seq_1.len(), 3);
353
+ assert_eq!(seq_1.last().unwrap().event_id, 3);
354
+ let seq_2 = update.take_next_wft_sequence(3).await.unwrap();
355
+ assert_eq!(seq_2.len(), 11);
356
+ assert_eq!(seq_2.last().unwrap().event_id, 14);
357
+ }
358
+
359
+ #[tokio::test]
360
+ async fn skips_events_before_desired_wft() {
361
+ let timer_hist = canned_histories::single_timer("t");
362
+ let mut update = timer_hist.as_history_update();
363
+ // We haven't processed the first 3 events, but we should still only get the second sequence
364
+ let seq_2 = update.take_next_wft_sequence(3).await.unwrap();
365
+ assert_eq!(seq_2.len(), 5);
366
+ assert_eq!(seq_2.last().unwrap().event_id, 8);
367
+ }
368
+
369
+ #[tokio::test]
370
+ async fn paginator_fetches_new_pages() {
371
+ // Note that this test triggers the "event ids that went backwards" error, acceptably.
372
+ // Can be fixed by having mock not return earlier events.
373
+ let wft_count = 500;
374
+ let long_hist = canned_histories::long_sequential_timers(wft_count);
375
+ let initial_hist = long_hist.get_history_info(10).unwrap();
376
+ let prev_started = initial_hist.previous_started_event_id();
377
+ let mut mock_client = mock_workflow_client();
378
+
379
+ let mut npt = 2;
380
+ mock_client
381
+ .expect_get_workflow_execution_history()
382
+ .returning(move |_, _, passed_npt| {
383
+ assert_eq!(passed_npt, vec![npt]);
384
+ let history = long_hist.get_history_info(10 * npt as usize).unwrap();
385
+ npt += 1;
386
+ Ok(GetWorkflowExecutionHistoryResponse {
387
+ history: Some(history.into()),
388
+ raw_history: vec![],
389
+ next_page_token: vec![npt],
390
+ archived: false,
391
+ })
392
+ });
393
+
394
+ let mut update = HistoryUpdate::new(
395
+ HistoryPaginator::new(
396
+ initial_hist.into(),
397
+ "wfid".to_string(),
398
+ "runid".to_string(),
399
+ vec![2], // Start at page "2"
400
+ Arc::new(mock_client),
401
+ ),
402
+ prev_started,
403
+ );
404
+
405
+ let seq = update.take_next_wft_sequence(0).await.unwrap();
406
+ assert_eq!(seq.len(), 3);
407
+
408
+ let mut last_event_id = 3;
409
+ let mut last_started_id = 3;
410
+ for _ in 1..wft_count {
411
+ let seq = update
412
+ .take_next_wft_sequence(last_started_id)
413
+ .await
414
+ .unwrap();
415
+ for e in &seq {
416
+ last_event_id += 1;
417
+ assert_eq!(e.event_id, last_event_id);
418
+ }
419
+ assert_eq!(seq.len(), 5);
420
+ last_started_id += 5;
421
+ }
422
+ }
423
+
424
+ #[tokio::test]
425
+ async fn handles_cache_misses() {
426
+ let timer_hist = canned_histories::single_timer("t");
427
+ let partial_task = timer_hist.get_one_wft(2).unwrap();
428
+ let mut history_from_get: GetWorkflowExecutionHistoryResponse =
429
+ timer_hist.get_history_info(2).unwrap().into();
430
+ // Chop off the last event, which is WFT started, which server doesn't return in get
431
+ // history
432
+ history_from_get.history.as_mut().map(|h| h.events.pop());
433
+ let mut mock_client = mock_workflow_client();
434
+ mock_client
435
+ .expect_get_workflow_execution_history()
436
+ .returning(move |_, _, _| Ok(history_from_get.clone()));
437
+
438
+ let mut update = HistoryUpdate::new(
439
+ HistoryPaginator::new(
440
+ partial_task.into(),
441
+ "wfid".to_string(),
442
+ "runid".to_string(),
443
+ // A cache miss means we'll try to fetch from start
444
+ NextPageToken::FetchFromStart,
445
+ Arc::new(mock_client),
446
+ ),
447
+ 1,
448
+ );
449
+ // We expect if we try to take the first task sequence that the first event is the first
450
+ // event in the sequence.
451
+ let seq = update.take_next_wft_sequence(0).await.unwrap();
452
+ assert_eq!(seq[0].event_id, 1);
453
+ let seq = update.take_next_wft_sequence(3).await.unwrap();
454
+ // Verify anything extra (which should only ever be WFT started) was re-appended to the
455
+ // end of the event iteration after fetching the old history.
456
+ assert_eq!(seq.last().unwrap().event_id, 8);
457
+ }
458
+ }