temporalio 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +301 -0
  3. data/bridge/Cargo.lock +2888 -0
  4. data/bridge/Cargo.toml +27 -0
  5. data/bridge/sdk-core/ARCHITECTURE.md +76 -0
  6. data/bridge/sdk-core/Cargo.lock +2606 -0
  7. data/bridge/sdk-core/Cargo.toml +2 -0
  8. data/bridge/sdk-core/LICENSE.txt +23 -0
  9. data/bridge/sdk-core/README.md +104 -0
  10. data/bridge/sdk-core/arch_docs/diagrams/README.md +10 -0
  11. data/bridge/sdk-core/arch_docs/diagrams/sticky_queues.puml +40 -0
  12. data/bridge/sdk-core/arch_docs/diagrams/workflow_internals.svg +1 -0
  13. data/bridge/sdk-core/arch_docs/sticky_queues.md +51 -0
  14. data/bridge/sdk-core/client/Cargo.toml +40 -0
  15. data/bridge/sdk-core/client/LICENSE.txt +23 -0
  16. data/bridge/sdk-core/client/src/lib.rs +1286 -0
  17. data/bridge/sdk-core/client/src/metrics.rs +165 -0
  18. data/bridge/sdk-core/client/src/raw.rs +932 -0
  19. data/bridge/sdk-core/client/src/retry.rs +751 -0
  20. data/bridge/sdk-core/client/src/workflow_handle/mod.rs +185 -0
  21. data/bridge/sdk-core/core/Cargo.toml +116 -0
  22. data/bridge/sdk-core/core/LICENSE.txt +23 -0
  23. data/bridge/sdk-core/core/benches/workflow_replay.rs +76 -0
  24. data/bridge/sdk-core/core/src/abstractions.rs +166 -0
  25. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +1014 -0
  26. data/bridge/sdk-core/core/src/core_tests/child_workflows.rs +221 -0
  27. data/bridge/sdk-core/core/src/core_tests/determinism.rs +107 -0
  28. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +925 -0
  29. data/bridge/sdk-core/core/src/core_tests/mod.rs +100 -0
  30. data/bridge/sdk-core/core/src/core_tests/queries.rs +894 -0
  31. data/bridge/sdk-core/core/src/core_tests/replay_flag.rs +65 -0
  32. data/bridge/sdk-core/core/src/core_tests/workers.rs +259 -0
  33. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +124 -0
  34. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +2090 -0
  35. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +515 -0
  36. data/bridge/sdk-core/core/src/lib.rs +282 -0
  37. data/bridge/sdk-core/core/src/pollers/mod.rs +54 -0
  38. data/bridge/sdk-core/core/src/pollers/poll_buffer.rs +297 -0
  39. data/bridge/sdk-core/core/src/protosext/mod.rs +428 -0
  40. data/bridge/sdk-core/core/src/replay/mod.rs +215 -0
  41. data/bridge/sdk-core/core/src/retry_logic.rs +202 -0
  42. data/bridge/sdk-core/core/src/telemetry/log_export.rs +190 -0
  43. data/bridge/sdk-core/core/src/telemetry/metrics.rs +428 -0
  44. data/bridge/sdk-core/core/src/telemetry/mod.rs +407 -0
  45. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +78 -0
  46. data/bridge/sdk-core/core/src/test_help/mod.rs +889 -0
  47. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +580 -0
  48. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +1048 -0
  49. data/bridge/sdk-core/core/src/worker/activities.rs +481 -0
  50. data/bridge/sdk-core/core/src/worker/client/mocks.rs +87 -0
  51. data/bridge/sdk-core/core/src/worker/client.rs +373 -0
  52. data/bridge/sdk-core/core/src/worker/mod.rs +570 -0
  53. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +37 -0
  54. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +101 -0
  55. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +532 -0
  56. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +907 -0
  57. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +294 -0
  58. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +167 -0
  59. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +858 -0
  60. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +136 -0
  61. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +157 -0
  62. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +129 -0
  63. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +1450 -0
  64. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +316 -0
  65. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +178 -0
  66. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +708 -0
  67. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +439 -0
  68. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +435 -0
  69. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +175 -0
  70. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +242 -0
  71. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +96 -0
  72. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +1200 -0
  73. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +272 -0
  74. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +198 -0
  75. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +655 -0
  76. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +1200 -0
  77. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +145 -0
  78. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +88 -0
  79. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +985 -0
  80. data/bridge/sdk-core/core-api/Cargo.toml +32 -0
  81. data/bridge/sdk-core/core-api/LICENSE.txt +23 -0
  82. data/bridge/sdk-core/core-api/src/errors.rs +95 -0
  83. data/bridge/sdk-core/core-api/src/lib.rs +109 -0
  84. data/bridge/sdk-core/core-api/src/telemetry.rs +147 -0
  85. data/bridge/sdk-core/core-api/src/worker.rs +148 -0
  86. data/bridge/sdk-core/etc/deps.svg +162 -0
  87. data/bridge/sdk-core/etc/dynamic-config.yaml +2 -0
  88. data/bridge/sdk-core/etc/otel-collector-config.yaml +36 -0
  89. data/bridge/sdk-core/etc/prometheus.yaml +6 -0
  90. data/bridge/sdk-core/etc/regen-depgraph.sh +5 -0
  91. data/bridge/sdk-core/fsm/Cargo.toml +18 -0
  92. data/bridge/sdk-core/fsm/LICENSE.txt +23 -0
  93. data/bridge/sdk-core/fsm/README.md +3 -0
  94. data/bridge/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +27 -0
  95. data/bridge/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +23 -0
  96. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +647 -0
  97. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +8 -0
  98. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.rs +18 -0
  99. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +12 -0
  100. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dynamic_dest_pass.rs +41 -0
  101. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.rs +14 -0
  102. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.stderr +11 -0
  103. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_arg_pass.rs +32 -0
  104. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_pass.rs +31 -0
  105. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/medium_complex_pass.rs +46 -0
  106. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.rs +29 -0
  107. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +12 -0
  108. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/simple_pass.rs +32 -0
  109. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.rs +18 -0
  110. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +5 -0
  111. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.rs +11 -0
  112. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +5 -0
  113. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.rs +11 -0
  114. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +5 -0
  115. data/bridge/sdk-core/fsm/rustfsm_trait/Cargo.toml +14 -0
  116. data/bridge/sdk-core/fsm/rustfsm_trait/LICENSE.txt +23 -0
  117. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +249 -0
  118. data/bridge/sdk-core/fsm/src/lib.rs +2 -0
  119. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  120. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  121. data/bridge/sdk-core/histories/fail_wf_task.bin +0 -0
  122. data/bridge/sdk-core/histories/timer_workflow_history.bin +0 -0
  123. data/bridge/sdk-core/integ-with-otel.sh +7 -0
  124. data/bridge/sdk-core/protos/api_upstream/README.md +9 -0
  125. data/bridge/sdk-core/protos/api_upstream/api-linter.yaml +40 -0
  126. data/bridge/sdk-core/protos/api_upstream/buf.yaml +9 -0
  127. data/bridge/sdk-core/protos/api_upstream/build/go.mod +7 -0
  128. data/bridge/sdk-core/protos/api_upstream/build/go.sum +5 -0
  129. data/bridge/sdk-core/protos/api_upstream/build/tools.go +29 -0
  130. data/bridge/sdk-core/protos/api_upstream/dependencies/gogoproto/gogo.proto +141 -0
  131. data/bridge/sdk-core/protos/api_upstream/go.mod +6 -0
  132. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +89 -0
  133. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +260 -0
  134. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +112 -0
  135. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +47 -0
  136. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +57 -0
  137. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +56 -0
  138. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +170 -0
  139. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +118 -0
  140. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/interaction_type.proto +39 -0
  141. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +51 -0
  142. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +50 -0
  143. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +41 -0
  144. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +60 -0
  145. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +59 -0
  146. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +40 -0
  147. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +122 -0
  148. data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +108 -0
  149. data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +114 -0
  150. data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +56 -0
  151. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +758 -0
  152. data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +87 -0
  153. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +97 -0
  154. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +121 -0
  155. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +80 -0
  156. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +61 -0
  157. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +55 -0
  158. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +379 -0
  159. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +108 -0
  160. data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +59 -0
  161. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +146 -0
  162. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +1168 -0
  163. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +415 -0
  164. data/bridge/sdk-core/protos/grpc/health/v1/health.proto +63 -0
  165. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
  166. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +79 -0
  167. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +77 -0
  168. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +15 -0
  169. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +30 -0
  170. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
  171. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +263 -0
  172. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +304 -0
  173. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +29 -0
  174. data/bridge/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
  175. data/bridge/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
  176. data/bridge/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
  177. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
  178. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
  179. data/bridge/sdk-core/rustfmt.toml +1 -0
  180. data/bridge/sdk-core/sdk/Cargo.toml +47 -0
  181. data/bridge/sdk-core/sdk/LICENSE.txt +23 -0
  182. data/bridge/sdk-core/sdk/src/activity_context.rs +230 -0
  183. data/bridge/sdk-core/sdk/src/app_data.rs +37 -0
  184. data/bridge/sdk-core/sdk/src/interceptors.rs +50 -0
  185. data/bridge/sdk-core/sdk/src/lib.rs +794 -0
  186. data/bridge/sdk-core/sdk/src/payload_converter.rs +11 -0
  187. data/bridge/sdk-core/sdk/src/workflow_context/options.rs +295 -0
  188. data/bridge/sdk-core/sdk/src/workflow_context.rs +694 -0
  189. data/bridge/sdk-core/sdk/src/workflow_future.rs +499 -0
  190. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +30 -0
  191. data/bridge/sdk-core/sdk-core-protos/LICENSE.txt +23 -0
  192. data/bridge/sdk-core/sdk-core-protos/build.rs +107 -0
  193. data/bridge/sdk-core/sdk-core-protos/src/constants.rs +7 -0
  194. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +544 -0
  195. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +230 -0
  196. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +1970 -0
  197. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
  198. data/bridge/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  199. data/bridge/sdk-core/test-utils/Cargo.toml +36 -0
  200. data/bridge/sdk-core/test-utils/src/canned_histories.rs +1579 -0
  201. data/bridge/sdk-core/test-utils/src/histfetch.rs +28 -0
  202. data/bridge/sdk-core/test-utils/src/lib.rs +650 -0
  203. data/bridge/sdk-core/tests/integ_tests/client_tests.rs +36 -0
  204. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +128 -0
  205. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +221 -0
  206. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +37 -0
  207. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +133 -0
  208. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +437 -0
  209. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
  210. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +878 -0
  211. data/bridge/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +61 -0
  212. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +59 -0
  213. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +58 -0
  214. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +50 -0
  215. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +60 -0
  216. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +54 -0
  217. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +788 -0
  218. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +53 -0
  219. data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +113 -0
  220. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +223 -0
  221. data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +93 -0
  222. data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +167 -0
  223. data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +99 -0
  224. data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +131 -0
  225. data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +75 -0
  226. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +597 -0
  227. data/bridge/sdk-core/tests/load_tests.rs +191 -0
  228. data/bridge/sdk-core/tests/main.rs +113 -0
  229. data/bridge/sdk-core/tests/runner.rs +93 -0
  230. data/bridge/src/connection.rs +186 -0
  231. data/bridge/src/lib.rs +239 -0
  232. data/bridge/src/runtime.rs +54 -0
  233. data/bridge/src/worker.rs +124 -0
  234. data/ext/Rakefile +9 -0
  235. data/lib/bridge.so +0 -0
  236. data/lib/gen/dependencies/gogoproto/gogo_pb.rb +14 -0
  237. data/lib/gen/temporal/api/batch/v1/message_pb.rb +50 -0
  238. data/lib/gen/temporal/api/command/v1/message_pb.rb +174 -0
  239. data/lib/gen/temporal/api/common/v1/message_pb.rb +69 -0
  240. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +33 -0
  241. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +39 -0
  242. data/lib/gen/temporal/api/enums/v1/common_pb.rb +42 -0
  243. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +68 -0
  244. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +77 -0
  245. data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +25 -0
  246. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +37 -0
  247. data/lib/gen/temporal/api/enums/v1/query_pb.rb +31 -0
  248. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +24 -0
  249. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +28 -0
  250. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +30 -0
  251. data/lib/gen/temporal/api/enums/v1/update_pb.rb +23 -0
  252. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +89 -0
  253. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +84 -0
  254. data/lib/gen/temporal/api/failure/v1/message_pb.rb +83 -0
  255. data/lib/gen/temporal/api/filter/v1/message_pb.rb +40 -0
  256. data/lib/gen/temporal/api/history/v1/message_pb.rb +490 -0
  257. data/lib/gen/temporal/api/interaction/v1/message_pb.rb +49 -0
  258. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +63 -0
  259. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +85 -0
  260. data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +20 -0
  261. data/lib/gen/temporal/api/query/v1/message_pb.rb +38 -0
  262. data/lib/gen/temporal/api/replication/v1/message_pb.rb +37 -0
  263. data/lib/gen/temporal/api/schedule/v1/message_pb.rb +149 -0
  264. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +73 -0
  265. data/lib/gen/temporal/api/version/v1/message_pb.rb +41 -0
  266. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +111 -0
  267. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +788 -0
  268. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +20 -0
  269. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +58 -0
  270. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +57 -0
  271. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +222 -0
  272. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +57 -0
  273. data/lib/gen/temporal/sdk/core/common/common_pb.rb +22 -0
  274. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +34 -0
  275. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +27 -0
  276. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +165 -0
  277. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +196 -0
  278. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +34 -0
  279. data/lib/temporalio/activity/context.rb +97 -0
  280. data/lib/temporalio/activity/info.rb +67 -0
  281. data/lib/temporalio/activity.rb +85 -0
  282. data/lib/temporalio/bridge/error.rb +8 -0
  283. data/lib/temporalio/bridge.rb +14 -0
  284. data/lib/temporalio/client/implementation.rb +340 -0
  285. data/lib/temporalio/client/workflow_handle.rb +243 -0
  286. data/lib/temporalio/client.rb +131 -0
  287. data/lib/temporalio/connection.rb +751 -0
  288. data/lib/temporalio/data_converter.rb +191 -0
  289. data/lib/temporalio/error/failure.rb +194 -0
  290. data/lib/temporalio/error/workflow_failure.rb +19 -0
  291. data/lib/temporalio/errors.rb +40 -0
  292. data/lib/temporalio/failure_converter/base.rb +26 -0
  293. data/lib/temporalio/failure_converter/basic.rb +319 -0
  294. data/lib/temporalio/failure_converter.rb +7 -0
  295. data/lib/temporalio/interceptor/chain.rb +28 -0
  296. data/lib/temporalio/interceptor/client.rb +123 -0
  297. data/lib/temporalio/payload_codec/base.rb +32 -0
  298. data/lib/temporalio/payload_converter/base.rb +24 -0
  299. data/lib/temporalio/payload_converter/bytes.rb +27 -0
  300. data/lib/temporalio/payload_converter/composite.rb +49 -0
  301. data/lib/temporalio/payload_converter/encoding_base.rb +35 -0
  302. data/lib/temporalio/payload_converter/json.rb +26 -0
  303. data/lib/temporalio/payload_converter/nil.rb +26 -0
  304. data/lib/temporalio/payload_converter.rb +14 -0
  305. data/lib/temporalio/retry_policy.rb +82 -0
  306. data/lib/temporalio/retry_state.rb +35 -0
  307. data/lib/temporalio/runtime.rb +25 -0
  308. data/lib/temporalio/timeout_type.rb +29 -0
  309. data/lib/temporalio/version.rb +3 -0
  310. data/lib/temporalio/worker/activity_runner.rb +92 -0
  311. data/lib/temporalio/worker/activity_worker.rb +138 -0
  312. data/lib/temporalio/worker/reactor.rb +46 -0
  313. data/lib/temporalio/worker/runner.rb +63 -0
  314. data/lib/temporalio/worker/sync_worker.rb +88 -0
  315. data/lib/temporalio/worker/thread_pool_executor.rb +51 -0
  316. data/lib/temporalio/worker.rb +198 -0
  317. data/lib/temporalio/workflow/execution_info.rb +54 -0
  318. data/lib/temporalio/workflow/execution_status.rb +36 -0
  319. data/lib/temporalio/workflow/id_reuse_policy.rb +36 -0
  320. data/lib/temporalio/workflow/query_reject_condition.rb +33 -0
  321. data/lib/temporalio.rb +12 -1
  322. data/lib/thermite_patch.rb +23 -0
  323. data/temporalio.gemspec +45 -0
  324. metadata +566 -9
  325. data/lib/temporal/version.rb +0 -3
  326. data/lib/temporal.rb +0 -4
  327. data/temporal.gemspec +0 -20
@@ -0,0 +1,570 @@
1
+ mod activities;
2
+ pub(crate) mod client;
3
+ mod workflow;
4
+
5
+ pub use temporal_sdk_core_api::worker::{WorkerConfig, WorkerConfigBuilder};
6
+
7
+ pub(crate) use activities::{
8
+ ExecutingLAId, LocalActRequest, LocalActivityExecutionResult, LocalActivityResolution,
9
+ NewLocalAct,
10
+ };
11
+ #[cfg(test)]
12
+ pub(crate) use workflow::ManagedWFFunc;
13
+ pub(crate) use workflow::{wft_poller::new_wft_poller, LEGACY_QUERY_ID};
14
+
15
+ use crate::{
16
+ errors::CompleteWfError,
17
+ pollers::{
18
+ new_activity_task_buffer, new_workflow_task_buffer, BoxedActPoller, Poller,
19
+ WorkflowTaskPoller,
20
+ },
21
+ protosext::{validate_activity_completion, ValidPollWFTQResponse},
22
+ telemetry::metrics::{
23
+ activity_poller, local_activity_worker_type, workflow_poller, workflow_sticky_poller,
24
+ MetricsContext,
25
+ },
26
+ worker::{
27
+ activities::{DispatchOrTimeoutLA, LACompleteAction, LocalActivityManager},
28
+ client::WorkerClient,
29
+ workflow::{LocalResolution, WorkflowBasics, Workflows},
30
+ },
31
+ ActivityHeartbeat, CompleteActivityError, PollActivityError, PollWfError, WorkerTrait,
32
+ };
33
+ use activities::{LocalInFlightActInfo, WorkerActivityTasks};
34
+ use futures::Stream;
35
+ use std::{convert::TryInto, sync::Arc};
36
+ use temporal_sdk_core_protos::{
37
+ coresdk::{
38
+ activity_result::activity_execution_result,
39
+ activity_task::ActivityTask,
40
+ workflow_activation::{remove_from_cache::EvictionReason, WorkflowActivation},
41
+ workflow_completion::WorkflowActivationCompletion,
42
+ ActivityTaskCompletion,
43
+ },
44
+ temporal::api::{
45
+ enums::v1::TaskQueueKind,
46
+ taskqueue::v1::{StickyExecutionAttributes, TaskQueue},
47
+ workflowservice::v1::PollActivityTaskQueueResponse,
48
+ },
49
+ TaskToken,
50
+ };
51
+ use tokio_util::sync::CancellationToken;
52
+
53
+ /// A worker polls on a certain task queue
54
+ pub struct Worker {
55
+ config: WorkerConfig,
56
+ wf_client: Arc<dyn WorkerClient>,
57
+
58
+ /// Manages all workflows and WFT processing
59
+ workflows: Workflows,
60
+ /// Manages activity tasks for this worker/task queue
61
+ at_task_mgr: Option<WorkerActivityTasks>,
62
+ /// Manages local activities
63
+ local_act_mgr: Arc<LocalActivityManager>,
64
+ /// Has shutdown been called?
65
+ shutdown_token: CancellationToken,
66
+ /// Will be called at the end of each activation completion
67
+ #[allow(clippy::type_complexity)] // Sorry clippy, there's no simple way to re-use here.
68
+ post_activate_hook: Option<Box<dyn Fn(&Self, &str, usize) + Send + Sync>>,
69
+ }
70
+
71
+ #[async_trait::async_trait]
72
+ impl WorkerTrait for Worker {
73
+ async fn poll_workflow_activation(&self) -> Result<WorkflowActivation, PollWfError> {
74
+ self.next_workflow_activation().await
75
+ }
76
+
77
+ #[instrument(skip(self))]
78
+ async fn poll_activity_task(&self) -> Result<ActivityTask, PollActivityError> {
79
+ loop {
80
+ match self.activity_poll().await.transpose() {
81
+ Some(r) => break r,
82
+ None => {
83
+ tokio::task::yield_now().await;
84
+ continue;
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ async fn complete_workflow_activation(
91
+ &self,
92
+ completion: WorkflowActivationCompletion,
93
+ ) -> Result<(), CompleteWfError> {
94
+ self.complete_workflow_activation(completion).await
95
+ }
96
+
97
+ async fn complete_activity_task(
98
+ &self,
99
+ completion: ActivityTaskCompletion,
100
+ ) -> Result<(), CompleteActivityError> {
101
+ let task_token = TaskToken(completion.task_token);
102
+ let status = if let Some(s) = completion.result.and_then(|r| r.status) {
103
+ s
104
+ } else {
105
+ return Err(CompleteActivityError::MalformedActivityCompletion {
106
+ reason: "Activity completion had empty result/status field".to_owned(),
107
+ completion: None,
108
+ });
109
+ };
110
+
111
+ self.complete_activity(task_token, status).await
112
+ }
113
+
114
+ fn record_activity_heartbeat(&self, details: ActivityHeartbeat) {
115
+ self.record_heartbeat(details);
116
+ }
117
+
118
+ fn request_workflow_eviction(&self, run_id: &str) {
119
+ self.request_wf_eviction(
120
+ run_id,
121
+ "Eviction explicitly requested by lang",
122
+ EvictionReason::LangRequested,
123
+ );
124
+ }
125
+
126
+ fn get_config(&self) -> &WorkerConfig {
127
+ &self.config
128
+ }
129
+
130
+ /// Begins the shutdown process, tells pollers they should stop. Is idempotent.
131
+ fn initiate_shutdown(&self) {
132
+ self.shutdown_token.cancel();
133
+ // First, we want to stop polling of both activity and workflow tasks
134
+ if let Some(atm) = self.at_task_mgr.as_ref() {
135
+ atm.notify_shutdown();
136
+ }
137
+ info!(
138
+ task_queue=%self.config.task_queue,
139
+ namespace=%self.config.namespace,
140
+ "Initiated shutdown",
141
+ );
142
+ }
143
+
144
+ async fn shutdown(&self) {
145
+ self.shutdown().await
146
+ }
147
+
148
+ async fn finalize_shutdown(self) {
149
+ self.shutdown().await;
150
+ self.finalize_shutdown().await
151
+ }
152
+ }
153
+
154
+ impl Worker {
155
+ pub(crate) fn new(
156
+ config: WorkerConfig,
157
+ sticky_queue_name: Option<String>,
158
+ client: Arc<dyn WorkerClient>,
159
+ metrics: MetricsContext,
160
+ ) -> Self {
161
+ info!(task_queue=%config.task_queue,
162
+ namespace=%config.namespace,
163
+ "Initializing worker");
164
+ metrics.worker_registered();
165
+
166
+ let shutdown_token = CancellationToken::new();
167
+ let max_nonsticky_polls = if sticky_queue_name.is_some() {
168
+ config.max_nonsticky_polls()
169
+ } else {
170
+ config.max_concurrent_wft_polls
171
+ };
172
+ let max_sticky_polls = config.max_sticky_polls();
173
+ let wft_metrics = metrics.with_new_attrs([workflow_poller()]);
174
+ let mut wf_task_poll_buffer = new_workflow_task_buffer(
175
+ client.clone(),
176
+ config.task_queue.clone(),
177
+ false,
178
+ max_nonsticky_polls,
179
+ max_nonsticky_polls * 2,
180
+ shutdown_token.child_token(),
181
+ );
182
+ wf_task_poll_buffer.set_num_pollers_handler(move |np| wft_metrics.record_num_pollers(np));
183
+ let sticky_queue_poller = sticky_queue_name.as_ref().map(|sqn| {
184
+ let sticky_metrics = metrics.with_new_attrs([workflow_sticky_poller()]);
185
+ let mut sp = new_workflow_task_buffer(
186
+ client.clone(),
187
+ sqn.clone(),
188
+ true,
189
+ max_sticky_polls,
190
+ max_sticky_polls * 2,
191
+ shutdown_token.child_token(),
192
+ );
193
+ sp.set_num_pollers_handler(move |np| sticky_metrics.record_num_pollers(np));
194
+ sp
195
+ });
196
+ let act_poll_buffer = if config.no_remote_activities {
197
+ None
198
+ } else {
199
+ let mut ap = new_activity_task_buffer(
200
+ client.clone(),
201
+ config.task_queue.clone(),
202
+ config.max_concurrent_at_polls,
203
+ config.max_concurrent_at_polls * 2,
204
+ config.max_task_queue_activities_per_second,
205
+ shutdown_token.child_token(),
206
+ );
207
+ let act_metrics = metrics.with_new_attrs([activity_poller()]);
208
+ ap.set_num_pollers_handler(move |np| act_metrics.record_num_pollers(np));
209
+ Some(Box::from(ap)
210
+ as Box<
211
+ dyn Poller<PollActivityTaskQueueResponse> + Send + Sync,
212
+ >)
213
+ };
214
+ let wf_task_poll_buffer = Box::new(WorkflowTaskPoller::new(
215
+ wf_task_poll_buffer,
216
+ sticky_queue_poller,
217
+ ));
218
+ let wft_stream = new_wft_poller(wf_task_poll_buffer, metrics.clone());
219
+ Self::new_with_pollers(
220
+ config,
221
+ sticky_queue_name,
222
+ client,
223
+ wft_stream,
224
+ act_poll_buffer,
225
+ metrics,
226
+ shutdown_token,
227
+ )
228
+ }
229
+
230
+ #[cfg(test)]
231
+ pub(crate) fn new_test(config: WorkerConfig, client: impl WorkerClient + 'static) -> Self {
232
+ Self::new(config, None, Arc::new(client), MetricsContext::no_op())
233
+ }
234
+
235
+ pub(crate) fn new_with_pollers(
236
+ config: WorkerConfig,
237
+ sticky_queue_name: Option<String>,
238
+ client: Arc<dyn WorkerClient>,
239
+ wft_stream: impl Stream<Item = Result<ValidPollWFTQResponse, tonic::Status>> + Send + 'static,
240
+ act_poller: Option<BoxedActPoller>,
241
+ metrics: MetricsContext,
242
+ shutdown_token: CancellationToken,
243
+ ) -> Self {
244
+ let local_act_mgr = Arc::new(LocalActivityManager::new(
245
+ config.max_outstanding_local_activities,
246
+ config.namespace.clone(),
247
+ metrics.with_new_attrs([local_activity_worker_type()]),
248
+ ));
249
+ let lam_clone = local_act_mgr.clone();
250
+ let local_act_req_sink = move |requests| lam_clone.enqueue(requests);
251
+ let at_task_mgr = act_poller.map(|ap| {
252
+ WorkerActivityTasks::new(
253
+ config.max_outstanding_activities,
254
+ config.max_worker_activities_per_second,
255
+ ap,
256
+ client.clone(),
257
+ metrics.clone(),
258
+ config.max_heartbeat_throttle_interval,
259
+ config.default_heartbeat_throttle_interval,
260
+ )
261
+ });
262
+ Self {
263
+ wf_client: client.clone(),
264
+ workflows: Workflows::new(
265
+ WorkflowBasics {
266
+ max_cached_workflows: config.max_cached_workflows,
267
+ max_outstanding_wfts: config.max_outstanding_workflow_tasks,
268
+ shutdown_token: shutdown_token.child_token(),
269
+ metrics,
270
+ namespace: config.namespace.clone(),
271
+ task_queue: config.task_queue.clone(),
272
+ ignore_evicts_on_shutdown: config.ignore_evicts_on_shutdown,
273
+ },
274
+ sticky_queue_name.map(|sq| StickyExecutionAttributes {
275
+ worker_task_queue: Some(TaskQueue {
276
+ name: sq,
277
+ kind: TaskQueueKind::Sticky as i32,
278
+ }),
279
+ schedule_to_start_timeout: Some(
280
+ config
281
+ .sticky_queue_schedule_to_start_timeout
282
+ .try_into()
283
+ .expect("timeout fits into proto"),
284
+ ),
285
+ }),
286
+ client,
287
+ wft_stream,
288
+ local_act_req_sink,
289
+ at_task_mgr
290
+ .as_ref()
291
+ .map(|mgr| mgr.get_handle_for_workflows()),
292
+ ),
293
+ at_task_mgr,
294
+ local_act_mgr,
295
+ config,
296
+ shutdown_token,
297
+ post_activate_hook: None,
298
+ }
299
+ }
300
+
301
+ /// Will shutdown the worker. Does not resolve until all outstanding workflow tasks have been
302
+ /// completed
303
+ async fn shutdown(&self) {
304
+ self.initiate_shutdown();
305
+ // Next we need to wait for all local activities to finish so no more workflow task
306
+ // heartbeats will be generated
307
+ self.local_act_mgr.shutdown_and_wait_all_finished().await;
308
+ // Wait for workflows to finish
309
+ self.workflows
310
+ .shutdown()
311
+ .await
312
+ .expect("Workflow processing terminates cleanly");
313
+ // Wait for activities to finish
314
+ if let Some(acts) = self.at_task_mgr.as_ref() {
315
+ acts.wait_all_finished().await;
316
+ }
317
+ }
318
+
319
+ /// Finish shutting down by consuming the background pollers and freeing all resources
320
+ async fn finalize_shutdown(self) {
321
+ if let Some(b) = self.at_task_mgr {
322
+ b.shutdown().await;
323
+ }
324
+ }
325
+
326
+ pub(crate) fn shutdown_token(&self) -> CancellationToken {
327
+ self.shutdown_token.clone()
328
+ }
329
+
330
+ /// Returns number of currently cached workflows
331
+ pub async fn cached_workflows(&self) -> usize {
332
+ self.workflows
333
+ .get_state_info()
334
+ .await
335
+ .map(|r| r.cached_workflows)
336
+ .unwrap_or_default()
337
+ }
338
+
339
+ /// Returns number of currently outstanding workflow tasks
340
+ #[cfg(test)]
341
+ pub(crate) async fn outstanding_workflow_tasks(&self) -> usize {
342
+ self.workflows
343
+ .get_state_info()
344
+ .await
345
+ .map(|r| r.outstanding_wft)
346
+ .unwrap_or_default()
347
+ }
348
+
349
+ #[cfg(test)]
350
+ pub(crate) async fn available_wft_permits(&self) -> usize {
351
+ self.workflows
352
+ .get_state_info()
353
+ .await
354
+ .expect("You can only check for available permits before shutdown")
355
+ .available_wft_permits
356
+ }
357
+
358
+ /// Get new activity tasks (may be local or nonlocal). Local activities are returned first
359
+ /// before polling the server if there are any.
360
+ ///
361
+ /// Returns `Ok(None)` in the event of a poll timeout or if the polling loop should otherwise
362
+ /// be restarted
363
+ async fn activity_poll(&self) -> Result<Option<ActivityTask>, PollActivityError> {
364
+ let act_mgr_poll = async {
365
+ if let Some(ref act_mgr) = self.at_task_mgr {
366
+ act_mgr.poll().await
367
+ } else {
368
+ info!("Activity polling is disabled for this worker");
369
+ self.shutdown_token.cancelled().await;
370
+ Err(PollActivityError::ShutDown)
371
+ }
372
+ };
373
+
374
+ tokio::select! {
375
+ biased;
376
+
377
+ r = self.local_act_mgr.next_pending() => {
378
+ match r {
379
+ Some(DispatchOrTimeoutLA::Dispatch(r)) => Ok(Some(r)),
380
+ Some(DispatchOrTimeoutLA::Timeout { run_id, resolution, task }) => {
381
+ self.notify_local_result(
382
+ &run_id, LocalResolution::LocalActivity(resolution));
383
+ Ok(task)
384
+ },
385
+ None => {
386
+ if self.shutdown_token.is_cancelled() {
387
+ return Err(PollActivityError::ShutDown);
388
+ }
389
+ Ok(None)
390
+ }
391
+ }
392
+ },
393
+ r = act_mgr_poll => r,
394
+ }
395
+ }
396
+
397
+ /// Attempt to record an activity heartbeat
398
+ pub(crate) fn record_heartbeat(&self, details: ActivityHeartbeat) {
399
+ if let Some(at_mgr) = self.at_task_mgr.as_ref() {
400
+ let tt = details.task_token.clone();
401
+ if let Err(e) = at_mgr.record_heartbeat(details) {
402
+ warn!(task_token = ?tt, details = ?e, "Activity heartbeat failed.");
403
+ }
404
+ }
405
+ }
406
+
407
+ #[instrument(skip(self, task_token, status),
408
+ fields(task_token=%&task_token, status=%&status,
409
+ task_queue=%self.config.task_queue, workflow_id, run_id))]
410
+ pub(crate) async fn complete_activity(
411
+ &self,
412
+ task_token: TaskToken,
413
+ status: activity_execution_result::Status,
414
+ ) -> Result<(), CompleteActivityError> {
415
+ validate_activity_completion(&status)?;
416
+ if task_token.is_local_activity_task() {
417
+ let as_la_res: LocalActivityExecutionResult = status.try_into()?;
418
+ match self.local_act_mgr.complete(&task_token, &as_la_res) {
419
+ LACompleteAction::Report(info) => self.complete_local_act(as_la_res, info, None),
420
+ LACompleteAction::LangDoesTimerBackoff(backoff, info) => {
421
+ // This la needs to write a failure marker, and then we will tell lang how
422
+ // long of a timer to schedule to back off for. We do this because there are
423
+ // no other situations where core generates "internal" commands so it is much
424
+ // simpler for lang to reply with the timer / next LA command than to do it
425
+ // internally. Plus, this backoff hack we'd like to eliminate eventually.
426
+ self.complete_local_act(as_la_res, info, Some(backoff));
427
+ }
428
+ LACompleteAction::WillBeRetried => {
429
+ // Nothing to do here
430
+ }
431
+ LACompleteAction::Untracked => {
432
+ warn!("Tried to complete untracked local activity {}", task_token);
433
+ }
434
+ }
435
+ return Ok(());
436
+ }
437
+
438
+ if let Some(atm) = &self.at_task_mgr {
439
+ atm.complete(task_token, status, &*self.wf_client).await;
440
+ } else {
441
+ error!(
442
+ "Tried to complete activity {} on a worker that does not have an activity manager",
443
+ task_token
444
+ );
445
+ }
446
+ Ok(())
447
+ }
448
+
449
+ #[instrument(skip(self), fields(run_id, workflow_id, task_queue=%self.config.task_queue))]
450
+ pub(crate) async fn next_workflow_activation(&self) -> Result<WorkflowActivation, PollWfError> {
451
+ self.workflows.next_workflow_activation().await
452
+ }
453
+
454
+ #[instrument(skip(self, completion),
455
+ fields(completion=%&completion, run_id=%completion.run_id, workflow_id,
456
+ task_queue=%self.config.task_queue))]
457
+ pub(crate) async fn complete_workflow_activation(
458
+ &self,
459
+ completion: WorkflowActivationCompletion,
460
+ ) -> Result<(), CompleteWfError> {
461
+ let run_id = completion.run_id.clone();
462
+ let most_recent_event = self.workflows.activation_completed(completion).await?;
463
+ if let Some(h) = &self.post_activate_hook {
464
+ h(self, &run_id, most_recent_event);
465
+ }
466
+ Ok(())
467
+ }
468
+
469
+ /// Request a workflow eviction
470
+ pub(crate) fn request_wf_eviction(
471
+ &self,
472
+ run_id: &str,
473
+ message: impl Into<String>,
474
+ reason: EvictionReason,
475
+ ) {
476
+ self.workflows.request_eviction(run_id, message, reason);
477
+ }
478
+
479
+ /// Sets a function to be called at the end of each activation completion
480
+ pub(crate) fn set_post_activate_hook(
481
+ &mut self,
482
+ callback: impl Fn(&Self, &str, usize) + Send + Sync + 'static,
483
+ ) {
484
+ self.post_activate_hook = Some(Box::new(callback))
485
+ }
486
+
487
+ fn complete_local_act(
488
+ &self,
489
+ la_res: LocalActivityExecutionResult,
490
+ info: LocalInFlightActInfo,
491
+ backoff: Option<prost_types::Duration>,
492
+ ) {
493
+ self.notify_local_result(
494
+ &info.la_info.workflow_exec_info.run_id,
495
+ LocalResolution::LocalActivity(LocalActivityResolution {
496
+ seq: info.la_info.schedule_cmd.seq,
497
+ result: la_res,
498
+ runtime: info.dispatch_time.elapsed(),
499
+ attempt: info.attempt,
500
+ backoff,
501
+ original_schedule_time: info.la_info.schedule_cmd.original_schedule_time,
502
+ }),
503
+ )
504
+ }
505
+
506
+ fn notify_local_result(&self, run_id: &str, res: LocalResolution) {
507
+ self.workflows.notify_of_local_result(run_id, res);
508
+ }
509
+ }
510
+
511
+ #[cfg(test)]
512
+ mod tests {
513
+ use super::*;
514
+ use crate::{test_help::test_worker_cfg, worker::client::mocks::mock_workflow_client};
515
+ use temporal_sdk_core_protos::temporal::api::workflowservice::v1::PollActivityTaskQueueResponse;
516
+
517
+ #[tokio::test]
518
+ async fn activity_timeouts_dont_eat_permits() {
519
+ let mut mock_client = mock_workflow_client();
520
+ mock_client
521
+ .expect_poll_activity_task()
522
+ .returning(|_, _| Ok(PollActivityTaskQueueResponse::default()));
523
+
524
+ let cfg = test_worker_cfg()
525
+ .max_outstanding_activities(5_usize)
526
+ .build()
527
+ .unwrap();
528
+ let worker = Worker::new_test(cfg, mock_client);
529
+ assert_eq!(worker.activity_poll().await.unwrap(), None);
530
+ assert_eq!(worker.at_task_mgr.unwrap().remaining_activity_capacity(), 5);
531
+ }
532
+
533
+ #[tokio::test]
534
+ async fn activity_errs_dont_eat_permits() {
535
+ let mut mock_client = mock_workflow_client();
536
+ mock_client
537
+ .expect_poll_activity_task()
538
+ .returning(|_, _| Err(tonic::Status::internal("ahhh")));
539
+
540
+ let cfg = test_worker_cfg()
541
+ .max_outstanding_activities(5_usize)
542
+ .build()
543
+ .unwrap();
544
+ let worker = Worker::new_test(cfg, mock_client);
545
+ assert!(worker.activity_poll().await.is_err());
546
+ assert_eq!(worker.at_task_mgr.unwrap().remaining_activity_capacity(), 5);
547
+ }
548
+
549
+ #[test]
550
+ fn max_polls_calculated_properly() {
551
+ let mut wcb = WorkerConfigBuilder::default();
552
+ let cfg = wcb
553
+ .namespace("default")
554
+ .task_queue("whatever")
555
+ .worker_build_id("test_bin_id")
556
+ .max_concurrent_wft_polls(5_usize)
557
+ .build()
558
+ .unwrap();
559
+ assert_eq!(cfg.max_nonsticky_polls(), 1);
560
+ assert_eq!(cfg.max_sticky_polls(), 4);
561
+ }
562
+
563
+ #[test]
564
+ fn max_polls_zero_is_err() {
565
+ assert!(test_worker_cfg()
566
+ .max_concurrent_wft_polls(0_usize)
567
+ .build()
568
+ .is_err());
569
+ }
570
+ }
@@ -0,0 +1,37 @@
1
+ use crate::{
2
+ telemetry::VecDisplayer,
3
+ worker::workflow::{WFCommand, WorkflowFetcher},
4
+ };
5
+ use std::sync::mpsc::{self, Receiver, Sender};
6
+
7
+ /// The [DrivenWorkflow] trait expects to be called to make progress, but the [CoreSDKService]
8
+ /// expects to be polled by the lang sdk. This struct acts as the bridge between the two, buffering
9
+ /// output from calls to [DrivenWorkflow] and offering them to [CoreSDKService]
10
+ #[derive(Debug)]
11
+ pub(crate) struct WorkflowBridge {
12
+ incoming_commands: Receiver<Vec<WFCommand>>,
13
+ }
14
+
15
+ impl WorkflowBridge {
16
+ /// Create a new bridge, returning it and the sink used to send commands to it.
17
+ pub(crate) fn new() -> (Self, Sender<Vec<WFCommand>>) {
18
+ let (tx, rx) = mpsc::channel();
19
+ (
20
+ Self {
21
+ incoming_commands: rx,
22
+ },
23
+ tx,
24
+ )
25
+ }
26
+ }
27
+
28
+ #[async_trait::async_trait]
29
+ impl WorkflowFetcher for WorkflowBridge {
30
+ async fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand> {
31
+ let in_cmds = self.incoming_commands.try_recv();
32
+
33
+ let in_cmds = in_cmds.unwrap_or_else(|_| vec![WFCommand::NoCommandsFromLang]);
34
+ debug!(in_cmds = %in_cmds.display(), "wf bridge iteration fetch");
35
+ in_cmds
36
+ }
37
+ }