temporalio 0.0.0 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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,28 @@
1
+ //! Use this binary to fetch histories as proto-encoded binary. The first argument must be a
2
+ //! workflow ID. A run id may optionally be provided as the second arg. The history is written to
3
+ //! `{workflow_id}_history.bin`.
4
+ //!
5
+ //! We can use `clap` if this needs more arguments / other stuff later on.
6
+
7
+ use prost::Message;
8
+ use temporal_client::WorkflowClientTrait;
9
+ use temporal_sdk_core_test_utils::get_integ_server_options;
10
+
11
+ #[tokio::main]
12
+ async fn main() -> Result<(), anyhow::Error> {
13
+ let gw_opts = get_integ_server_options();
14
+ let client = gw_opts.connect("default", None, None).await?;
15
+ let wf_id = std::env::args()
16
+ .nth(1)
17
+ .expect("must provide workflow id as only argument");
18
+ let run_id = std::env::args().nth(2);
19
+ let hist = client
20
+ .get_workflow_execution_history(wf_id.clone(), run_id, vec![])
21
+ .await?
22
+ .history
23
+ .expect("history field must be populated");
24
+ // Serialize history to file
25
+ let byteified = hist.encode_to_vec();
26
+ tokio::fs::write(format!("{}_history.bin", wf_id), &byteified).await?;
27
+ Ok(())
28
+ }
@@ -0,0 +1,650 @@
1
+ //! This crate contains testing functionality that can be useful when building SDKs against Core,
2
+ //! or even when testing workflows written in SDKs that use Core.
3
+
4
+ #[macro_use]
5
+ extern crate tracing;
6
+
7
+ pub mod canned_histories;
8
+
9
+ use crate::stream::{Stream, TryStreamExt};
10
+ use futures::{future, stream, stream::FuturesUnordered, StreamExt};
11
+ use parking_lot::Mutex;
12
+ use prost::Message;
13
+ use rand::{distributions::Standard, Rng};
14
+ use std::{
15
+ convert::TryFrom, env, future::Future, net::SocketAddr, path::PathBuf, sync::Arc,
16
+ time::Duration,
17
+ };
18
+ use temporal_client::{
19
+ Client, RetryClient, WorkflowClientTrait, WorkflowExecutionInfo, WorkflowOptions,
20
+ };
21
+ use temporal_sdk::{
22
+ interceptors::{FailOnNondeterminismInterceptor, WorkerInterceptor},
23
+ IntoActivityFunc, Worker, WorkflowFunction,
24
+ };
25
+ use temporal_sdk_core::{
26
+ ephemeral_server::{EphemeralExe, EphemeralExeVersion},
27
+ init_replay_worker, init_worker,
28
+ replay::HistoryForReplay,
29
+ ClientOptions, ClientOptionsBuilder, CoreRuntime, WorkerConfig, WorkerConfigBuilder,
30
+ };
31
+ use temporal_sdk_core_api::{
32
+ telemetry::{
33
+ Logger, MetricsExporter, OtelCollectorOptions, TelemetryOptions, TelemetryOptionsBuilder,
34
+ TraceExportConfig, TraceExporter,
35
+ },
36
+ Worker as CoreWorker,
37
+ };
38
+ use temporal_sdk_core_protos::{
39
+ coresdk::{
40
+ workflow_commands::{
41
+ workflow_command, ActivityCancellationType, CompleteWorkflowExecution,
42
+ ScheduleActivity, ScheduleLocalActivity, StartTimer,
43
+ },
44
+ workflow_completion::WorkflowActivationCompletion,
45
+ },
46
+ temporal::api::{common::v1::Payload, history::v1::History},
47
+ };
48
+ use tokio::sync::OnceCell;
49
+ use url::Url;
50
+
51
+ pub const NAMESPACE: &str = "default";
52
+ pub const TEST_Q: &str = "q";
53
+ /// The env var used to specify where the integ tests should point
54
+ pub const INTEG_SERVER_TARGET_ENV_VAR: &str = "TEMPORAL_SERVICE_ADDRESS";
55
+ /// This env var is set (to any value) if temporalite is in use
56
+ pub const INTEG_TEMPORALITE_USED_ENV_VAR: &str = "INTEG_TEMPORALITE_ON";
57
+ /// This env var is set (to any value) if the test server is in use
58
+ pub const INTEG_TEST_SERVER_USED_ENV_VAR: &str = "INTEG_TEST_SERVER_ON";
59
+
60
+ /// If set, turn export traces and metrics to the OTel collector at the given URL
61
+ const OTEL_URL_ENV_VAR: &str = "TEMPORAL_INTEG_OTEL_URL";
62
+ /// If set, enable direct scraping of prom metrics on the specified port
63
+ const PROM_ENABLE_ENV_VAR: &str = "TEMPORAL_INTEG_PROM_PORT";
64
+ /// Create a worker instance which will use the provided test name to base the task queue and wf id
65
+ /// upon. Returns the instance and the task queue name (which is also the workflow id).
66
+ pub async fn init_core_and_create_wf(test_name: &str) -> CoreWfStarter {
67
+ let mut starter = CoreWfStarter::new(test_name);
68
+ let _ = starter.get_worker().await;
69
+ starter.start_wf().await;
70
+ starter
71
+ }
72
+
73
+ /// Create a worker replay instance preloaded with provided histories. Returns the worker impl.
74
+ pub fn init_core_replay_preloaded<I>(test_name: &str, histories: I) -> Arc<dyn CoreWorker>
75
+ where
76
+ I: IntoIterator<Item = HistoryForReplay> + 'static,
77
+ <I as IntoIterator>::IntoIter: Send,
78
+ {
79
+ init_core_replay_stream(test_name, stream::iter(histories))
80
+ }
81
+ pub fn init_core_replay_stream<I>(test_name: &str, histories: I) -> Arc<dyn CoreWorker>
82
+ where
83
+ I: Stream<Item = HistoryForReplay> + Send + 'static,
84
+ {
85
+ let worker_cfg = WorkerConfigBuilder::default()
86
+ .namespace(NAMESPACE)
87
+ .task_queue(test_name)
88
+ .worker_build_id("test_bin_id")
89
+ .build()
90
+ .expect("Configuration options construct properly");
91
+ let worker =
92
+ init_replay_worker(worker_cfg, histories).expect("Replay worker must init properly");
93
+ Arc::new(worker)
94
+ }
95
+ pub fn replay_sdk_worker<I>(histories: I) -> Worker
96
+ where
97
+ I: IntoIterator<Item = HistoryForReplay> + 'static,
98
+ <I as IntoIterator>::IntoIter: Send,
99
+ {
100
+ replay_sdk_worker_stream(stream::iter(histories))
101
+ }
102
+ pub fn replay_sdk_worker_stream<I>(histories: I) -> Worker
103
+ where
104
+ I: Stream<Item = HistoryForReplay> + Send + 'static,
105
+ {
106
+ let core = init_core_replay_stream("replay_worker_test", histories);
107
+ let mut worker = Worker::new_from_core(core, "replay_q".to_string());
108
+ worker.set_worker_interceptor(Box::new(FailOnNondeterminismInterceptor {}));
109
+ worker
110
+ }
111
+
112
+ /// Load history from a file containing the protobuf serialization of it
113
+ pub async fn history_from_proto_binary(path_from_root: &str) -> Result<History, anyhow::Error> {
114
+ let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
115
+ path.push("..");
116
+ path.push(path_from_root);
117
+ let bytes = tokio::fs::read(path).await?;
118
+ Ok(History::decode(&*bytes)?)
119
+ }
120
+
121
+ static INTEG_TESTS_RT: once_cell::sync::OnceCell<CoreRuntime> = once_cell::sync::OnceCell::new();
122
+ pub fn init_integ_telem() {
123
+ INTEG_TESTS_RT.get_or_init(|| {
124
+ let telemetry_options = get_integ_telem_options();
125
+ let rt =
126
+ CoreRuntime::new_assume_tokio(telemetry_options).expect("Core runtime inits cleanly");
127
+ let _ = tracing::subscriber::set_global_default(rt.trace_subscriber());
128
+ rt
129
+ });
130
+ }
131
+
132
+ /// Implements a builder pattern to help integ tests initialize core and create workflows
133
+ pub struct CoreWfStarter {
134
+ /// Used for both the task queue and workflow id
135
+ task_queue_name: String,
136
+ pub worker_config: WorkerConfig,
137
+ wft_timeout: Option<Duration>,
138
+ initted_worker: OnceCell<InitializedWorker>,
139
+ }
140
+ struct InitializedWorker {
141
+ worker: Arc<dyn CoreWorker>,
142
+ client: Arc<RetryClient<Client>>,
143
+ }
144
+
145
+ impl CoreWfStarter {
146
+ pub fn new(test_name: &str) -> Self {
147
+ let rand_bytes: Vec<u8> = rand::thread_rng().sample_iter(&Standard).take(6).collect();
148
+ let task_q_salt = base64::encode(rand_bytes);
149
+ let task_queue = format!("{}_{}", test_name, task_q_salt);
150
+ Self::new_tq_name(&task_queue)
151
+ }
152
+
153
+ pub fn new_tq_name(task_queue: &str) -> Self {
154
+ init_integ_telem();
155
+ Self {
156
+ task_queue_name: task_queue.to_owned(),
157
+ worker_config: WorkerConfigBuilder::default()
158
+ .namespace(NAMESPACE)
159
+ .task_queue(task_queue)
160
+ .worker_build_id("test_build_id")
161
+ .max_cached_workflows(1000_usize)
162
+ .build()
163
+ .unwrap(),
164
+ wft_timeout: None,
165
+ initted_worker: OnceCell::new(),
166
+ }
167
+ }
168
+
169
+ pub async fn worker(&mut self) -> TestWorker {
170
+ let mut w = TestWorker::new(
171
+ self.get_worker().await,
172
+ self.worker_config.task_queue.clone(),
173
+ );
174
+ w.client = Some(self.get_client().await);
175
+
176
+ w
177
+ }
178
+
179
+ pub async fn shutdown(&mut self) {
180
+ self.get_worker().await.shutdown().await;
181
+ }
182
+
183
+ pub async fn get_worker(&mut self) -> Arc<dyn CoreWorker> {
184
+ self.get_or_init().await.worker.clone()
185
+ }
186
+
187
+ pub async fn get_client(&mut self) -> Arc<RetryClient<Client>> {
188
+ self.get_or_init().await.client.clone()
189
+ }
190
+
191
+ /// Start the workflow defined by the builder and return run id
192
+ pub async fn start_wf(&self) -> String {
193
+ self.start_wf_with_id(self.task_queue_name.clone(), WorkflowOptions::default())
194
+ .await
195
+ }
196
+
197
+ pub async fn start_wf_with_id(&self, workflow_id: String, mut opts: WorkflowOptions) -> String {
198
+ opts.task_timeout = opts.task_timeout.or(self.wft_timeout);
199
+ self.initted_worker
200
+ .get()
201
+ .expect(
202
+ "Worker must be initted before starting a workflow.\
203
+ Tests must call `get_worker` first.",
204
+ )
205
+ .client
206
+ .start_workflow(
207
+ vec![],
208
+ self.worker_config.task_queue.clone(),
209
+ workflow_id,
210
+ self.task_queue_name.clone(),
211
+ None,
212
+ opts,
213
+ )
214
+ .await
215
+ .unwrap()
216
+ .run_id
217
+ }
218
+
219
+ /// Fetch the history for the indicated workflow and replay it using the provided worker.
220
+ /// Can be used after completing workflows normally to ensure replay works as well.
221
+ pub async fn fetch_history_and_replay(
222
+ &mut self,
223
+ wf_id: impl Into<String>,
224
+ run_id: impl Into<String>,
225
+ worker: &mut Worker,
226
+ ) -> Result<(), anyhow::Error> {
227
+ let wf_id = wf_id.into();
228
+ // Fetch history and replay it
229
+ let history = self
230
+ .get_client()
231
+ .await
232
+ .get_workflow_execution_history(wf_id.clone(), Some(run_id.into()), vec![])
233
+ .await?
234
+ .history
235
+ .expect("history field must be populated");
236
+ let with_id = HistoryForReplay::new(history, wf_id);
237
+ let replay_worker = init_core_replay_preloaded(worker.task_queue(), [with_id]);
238
+ worker.with_new_core_worker(replay_worker);
239
+ worker.set_worker_interceptor(Box::new(FailOnNondeterminismInterceptor {}));
240
+ worker.run().await.unwrap();
241
+ Ok(())
242
+ }
243
+
244
+ pub fn get_task_queue(&self) -> &str {
245
+ &self.worker_config.task_queue
246
+ }
247
+
248
+ pub fn get_wf_id(&self) -> &str {
249
+ &self.task_queue_name
250
+ }
251
+
252
+ pub fn max_cached_workflows(&mut self, num: usize) -> &mut Self {
253
+ self.worker_config.max_cached_workflows = num;
254
+ self
255
+ }
256
+
257
+ pub fn max_wft(&mut self, max: usize) -> &mut Self {
258
+ self.worker_config.max_outstanding_workflow_tasks = max;
259
+ self
260
+ }
261
+
262
+ pub fn max_at(&mut self, max: usize) -> &mut Self {
263
+ self.worker_config.max_outstanding_activities = max;
264
+ self
265
+ }
266
+
267
+ pub fn max_local_at(&mut self, max: usize) -> &mut Self {
268
+ self.worker_config.max_outstanding_local_activities = max;
269
+ self
270
+ }
271
+
272
+ pub fn max_at_polls(&mut self, max: usize) -> &mut Self {
273
+ self.worker_config.max_concurrent_at_polls = max;
274
+ self
275
+ }
276
+
277
+ pub fn wft_timeout(&mut self, timeout: Duration) -> &mut Self {
278
+ self.wft_timeout = Some(timeout);
279
+ self
280
+ }
281
+
282
+ async fn get_or_init(&mut self) -> &InitializedWorker {
283
+ self.initted_worker
284
+ .get_or_init(|| async {
285
+ let client = Arc::new(
286
+ get_integ_server_options()
287
+ .connect(self.worker_config.namespace.clone(), None, None)
288
+ .await
289
+ .expect("Must connect"),
290
+ );
291
+ let worker = init_worker(
292
+ INTEG_TESTS_RT.get().unwrap(),
293
+ self.worker_config.clone(),
294
+ client.clone(),
295
+ )
296
+ .expect("Worker inits cleanly");
297
+ InitializedWorker {
298
+ worker: Arc::new(worker),
299
+ client,
300
+ }
301
+ })
302
+ .await
303
+ }
304
+ }
305
+
306
+ /// Provides conveniences for running integ tests with the SDK (against real server or mocks)
307
+ pub struct TestWorker {
308
+ inner: Worker,
309
+ pub core_worker: Arc<dyn CoreWorker>,
310
+ client: Option<Arc<RetryClient<Client>>>,
311
+ pub started_workflows: Mutex<Vec<WorkflowExecutionInfo>>,
312
+ /// If set true (default), and a client is available, we will fetch workflow results to
313
+ /// determine when they have all completed.
314
+ pub fetch_results: bool,
315
+ iceptor: Option<TestWorkerCompletionIceptor>,
316
+ }
317
+ impl TestWorker {
318
+ /// Create a new test worker
319
+ pub fn new(core_worker: Arc<dyn CoreWorker>, task_queue: impl Into<String>) -> Self {
320
+ let inner = Worker::new_from_core(core_worker.clone(), task_queue);
321
+ let iceptor = TestWorkerCompletionIceptor::new(
322
+ TestWorkerShutdownCond::NoAutoShutdown,
323
+ Arc::new(inner.shutdown_handle()),
324
+ );
325
+ Self {
326
+ inner,
327
+ core_worker,
328
+ client: None,
329
+ started_workflows: Mutex::new(vec![]),
330
+ fetch_results: true,
331
+ iceptor: Some(iceptor),
332
+ }
333
+ }
334
+
335
+ pub fn inner_mut(&mut self) -> &mut Worker {
336
+ &mut self.inner
337
+ }
338
+
339
+ // TODO: Maybe trait-ify?
340
+ pub fn register_wf<F: Into<WorkflowFunction>>(
341
+ &mut self,
342
+ workflow_type: impl Into<String>,
343
+ wf_function: F,
344
+ ) {
345
+ self.inner.register_wf(workflow_type, wf_function)
346
+ }
347
+
348
+ pub fn register_activity<A, R, O>(
349
+ &mut self,
350
+ activity_type: impl Into<String>,
351
+ act_function: impl IntoActivityFunc<A, R, O>,
352
+ ) {
353
+ self.inner.register_activity(activity_type, act_function)
354
+ }
355
+
356
+ /// Create a workflow, asking the server to start it with the provided workflow ID and using the
357
+ /// provided workflow function.
358
+ ///
359
+ /// Increments the expected Workflow run count.
360
+ ///
361
+ /// Returns the run id of the started workflow
362
+ pub async fn submit_wf(
363
+ &self,
364
+ workflow_id: impl Into<String>,
365
+ workflow_type: impl Into<String>,
366
+ input: Vec<Payload>,
367
+ options: WorkflowOptions,
368
+ ) -> Result<String, anyhow::Error> {
369
+ if let Some(c) = self.client.as_ref() {
370
+ let wfid = workflow_id.into();
371
+ let res = c
372
+ .start_workflow(
373
+ input,
374
+ self.inner.task_queue().to_string(),
375
+ wfid.clone(),
376
+ workflow_type.into(),
377
+ None,
378
+ options,
379
+ )
380
+ .await?;
381
+ self.started_workflows.lock().push(WorkflowExecutionInfo {
382
+ namespace: c.namespace().to_string(),
383
+ workflow_id: wfid,
384
+ run_id: Some(res.run_id.clone()),
385
+ });
386
+ Ok(res.run_id)
387
+ } else {
388
+ Ok("fake_run_id".to_string())
389
+ }
390
+ }
391
+
392
+ /// Runs until all expected workflows have completed
393
+ pub async fn run_until_done(&mut self) -> Result<(), anyhow::Error> {
394
+ self.run_until_done_intercepted(Option::<TestWorkerCompletionIceptor>::None)
395
+ .await
396
+ }
397
+
398
+ /// See [Self::run_until_done], but allows configuration of some low-level interception.
399
+ pub async fn run_until_done_intercepted(
400
+ &mut self,
401
+ interceptor: Option<impl WorkerInterceptor + 'static>,
402
+ ) -> Result<(), anyhow::Error> {
403
+ let mut iceptor = self.iceptor.take().unwrap();
404
+ // Automatically use results-based complete detection if we have a client
405
+ if self.fetch_results {
406
+ if let Some(c) = self.client.clone() {
407
+ iceptor.condition = TestWorkerShutdownCond::GetResults(
408
+ std::mem::take(&mut self.started_workflows.lock()),
409
+ c,
410
+ );
411
+ }
412
+ }
413
+ iceptor.next = interceptor.map(|i| Box::new(i) as Box<dyn WorkerInterceptor>);
414
+ let get_results_waiter = iceptor.wait_all_wfs();
415
+ self.inner.set_worker_interceptor(Box::new(iceptor));
416
+ tokio::try_join!(self.inner.run(), get_results_waiter)?;
417
+ Ok(())
418
+ }
419
+ }
420
+
421
+ pub type BoxDynActivationHook = Box<dyn Fn(&WorkflowActivationCompletion)>;
422
+
423
+ pub enum TestWorkerShutdownCond {
424
+ GetResults(Vec<WorkflowExecutionInfo>, Arc<RetryClient<Client>>),
425
+ NoAutoShutdown,
426
+ }
427
+ /// Implements calling the shutdown handle when the expected number of test workflows has completed
428
+ pub struct TestWorkerCompletionIceptor {
429
+ condition: TestWorkerShutdownCond,
430
+ shutdown_handle: Arc<dyn Fn()>,
431
+ every_activation: Option<BoxDynActivationHook>,
432
+ next: Option<Box<dyn WorkerInterceptor>>,
433
+ }
434
+ impl TestWorkerCompletionIceptor {
435
+ pub fn new(condition: TestWorkerShutdownCond, shutdown_handle: Arc<dyn Fn()>) -> Self {
436
+ Self {
437
+ condition,
438
+ shutdown_handle,
439
+ every_activation: None,
440
+ next: None,
441
+ }
442
+ }
443
+
444
+ fn wait_all_wfs(&mut self) -> impl Future<Output = Result<(), anyhow::Error>> + 'static {
445
+ if let TestWorkerShutdownCond::GetResults(ref mut wfs, ref client) = self.condition {
446
+ let wfs = std::mem::take(wfs);
447
+ let shutdown_h = self.shutdown_handle.clone();
448
+ let client = (**client).clone();
449
+ let stream = stream::iter(
450
+ wfs.into_iter()
451
+ .map(move |info| info.bind_untyped(client.clone())),
452
+ )
453
+ .map(Ok);
454
+ future::Either::Left(async move {
455
+ stream
456
+ .try_for_each_concurrent(None, |wh| async move {
457
+ wh.get_workflow_result(Default::default()).await?;
458
+ Ok::<_, anyhow::Error>(())
459
+ })
460
+ .await?;
461
+ shutdown_h();
462
+ Ok(())
463
+ })
464
+ } else {
465
+ future::Either::Right(future::ready(Ok(())))
466
+ }
467
+ }
468
+ }
469
+ #[async_trait::async_trait(?Send)]
470
+ impl WorkerInterceptor for TestWorkerCompletionIceptor {
471
+ async fn on_workflow_activation_completion(&self, completion: &WorkflowActivationCompletion) {
472
+ if let Some(func) = self.every_activation.as_ref() {
473
+ func(completion);
474
+ }
475
+ if completion.has_execution_ending() {
476
+ info!("Workflow {} says it's finishing", &completion.run_id);
477
+ }
478
+ if let Some(n) = self.next.as_ref() {
479
+ n.on_workflow_activation_completion(completion).await;
480
+ }
481
+ }
482
+
483
+ fn on_shutdown(&self, sdk_worker: &Worker) {
484
+ if let Some(n) = self.next.as_ref() {
485
+ n.on_shutdown(sdk_worker);
486
+ }
487
+ }
488
+ }
489
+
490
+ /// Returns the client options used to connect to the server used for integration tests.
491
+ pub fn get_integ_server_options() -> ClientOptions {
492
+ let temporal_server_address = match env::var(INTEG_SERVER_TARGET_ENV_VAR) {
493
+ Ok(addr) => addr,
494
+ Err(_) => "http://localhost:7233".to_owned(),
495
+ };
496
+ let url = Url::try_from(&*temporal_server_address).unwrap();
497
+ ClientOptionsBuilder::default()
498
+ .identity("integ_tester".to_string())
499
+ .target_url(url)
500
+ .client_name("temporal-core".to_string())
501
+ .client_version("0.1.0".to_string())
502
+ .build()
503
+ .unwrap()
504
+ }
505
+
506
+ pub fn get_integ_telem_options() -> TelemetryOptions {
507
+ let mut ob = TelemetryOptionsBuilder::default();
508
+ let filter_string =
509
+ env::var("RUST_LOG").unwrap_or_else(|_| "temporal_sdk_core=INFO".to_string());
510
+ if let Some(url) = env::var(OTEL_URL_ENV_VAR)
511
+ .ok()
512
+ .map(|x| x.parse::<Url>().unwrap())
513
+ {
514
+ let opts = OtelCollectorOptions {
515
+ url,
516
+ headers: Default::default(),
517
+ metric_periodicity: None,
518
+ };
519
+ ob.tracing(TraceExportConfig {
520
+ filter: filter_string.clone(),
521
+ exporter: TraceExporter::Otel(opts.clone()),
522
+ });
523
+ ob.metrics(MetricsExporter::Otel(opts));
524
+ }
525
+ if let Some(addr) = env::var(PROM_ENABLE_ENV_VAR)
526
+ .ok()
527
+ .map(|x| SocketAddr::new([127, 0, 0, 1].into(), x.parse().unwrap()))
528
+ {
529
+ ob.metrics(MetricsExporter::Prometheus(addr));
530
+ }
531
+ ob.logging(Logger::Console {
532
+ filter: filter_string,
533
+ })
534
+ .build()
535
+ .unwrap()
536
+ }
537
+
538
+ pub fn default_cached_download() -> EphemeralExe {
539
+ EphemeralExe::CachedDownload {
540
+ version: EphemeralExeVersion::Default {
541
+ sdk_name: "sdk-rust".to_string(),
542
+ sdk_version: "0.1.0".to_string(),
543
+ },
544
+ dest_dir: None,
545
+ }
546
+ }
547
+
548
+ pub fn schedule_activity_cmd(
549
+ seq: u32,
550
+ task_q: &str,
551
+ activity_id: &str,
552
+ cancellation_type: ActivityCancellationType,
553
+ activity_timeout: Duration,
554
+ heartbeat_timeout: Duration,
555
+ ) -> workflow_command::Variant {
556
+ ScheduleActivity {
557
+ seq,
558
+ activity_id: activity_id.to_string(),
559
+ activity_type: "test_activity".to_string(),
560
+ task_queue: task_q.to_owned(),
561
+ schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
562
+ start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
563
+ schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
564
+ heartbeat_timeout: Some(heartbeat_timeout.try_into().expect("duration fits")),
565
+ cancellation_type: cancellation_type as i32,
566
+ ..Default::default()
567
+ }
568
+ .into()
569
+ }
570
+
571
+ pub fn schedule_local_activity_cmd(
572
+ seq: u32,
573
+ activity_id: &str,
574
+ cancellation_type: ActivityCancellationType,
575
+ activity_timeout: Duration,
576
+ ) -> workflow_command::Variant {
577
+ ScheduleLocalActivity {
578
+ seq,
579
+ activity_id: activity_id.to_string(),
580
+ activity_type: "test_activity".to_string(),
581
+ schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
582
+ start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
583
+ schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
584
+ cancellation_type: cancellation_type as i32,
585
+ ..Default::default()
586
+ }
587
+ .into()
588
+ }
589
+
590
+ pub fn start_timer_cmd(seq: u32, duration: Duration) -> workflow_command::Variant {
591
+ StartTimer {
592
+ seq,
593
+ start_to_fire_timeout: Some(duration.try_into().expect("duration fits")),
594
+ }
595
+ .into()
596
+ }
597
+
598
+ /// Given a desired number of concurrent executions and a provided function that produces a future,
599
+ /// run that many instances of the future concurrently.
600
+ ///
601
+ /// Annoyingly, because of a sorta-bug in the way async blocks work, the async block produced by
602
+ /// the closure must be `async move` if it uses the provided iteration number. On the plus side,
603
+ /// since you're usually just accessing core in the closure, if core is a reference everything just
604
+ /// works. See <https://github.com/rust-lang/rust/issues/81653>
605
+ pub async fn fanout_tasks<FutureMaker, Fut>(num: usize, fm: FutureMaker)
606
+ where
607
+ FutureMaker: Fn(usize) -> Fut,
608
+ Fut: Future,
609
+ {
610
+ let mut tasks = FuturesUnordered::new();
611
+ for i in 0..num {
612
+ tasks.push(fm(i));
613
+ }
614
+
615
+ while tasks.next().await.is_some() {}
616
+ }
617
+
618
+ #[async_trait::async_trait]
619
+ pub trait WorkerTestHelpers {
620
+ async fn complete_execution(&self, run_id: &str);
621
+ async fn complete_timer(&self, run_id: &str, seq: u32, duration: Duration);
622
+ }
623
+
624
+ #[async_trait::async_trait]
625
+ impl<T> WorkerTestHelpers for T
626
+ where
627
+ T: CoreWorker + ?Sized,
628
+ {
629
+ async fn complete_execution(&self, run_id: &str) {
630
+ self.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
631
+ run_id.to_string(),
632
+ vec![CompleteWorkflowExecution { result: None }.into()],
633
+ ))
634
+ .await
635
+ .unwrap();
636
+ }
637
+
638
+ async fn complete_timer(&self, run_id: &str, seq: u32, duration: Duration) {
639
+ self.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
640
+ run_id.to_string(),
641
+ vec![StartTimer {
642
+ seq,
643
+ start_to_fire_timeout: Some(duration.try_into().expect("duration fits")),
644
+ }
645
+ .into()],
646
+ ))
647
+ .await
648
+ .unwrap();
649
+ }
650
+ }