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,566 @@
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(level = "debug", 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
+ #[instrument(level = "debug", skip(self, completion), fields(completion=%&completion))]
98
+ async fn complete_activity_task(
99
+ &self,
100
+ completion: ActivityTaskCompletion,
101
+ ) -> Result<(), CompleteActivityError> {
102
+ let task_token = TaskToken(completion.task_token);
103
+ let status = if let Some(s) = completion.result.and_then(|r| r.status) {
104
+ s
105
+ } else {
106
+ return Err(CompleteActivityError::MalformedActivityCompletion {
107
+ reason: "Activity completion had empty result/status field".to_owned(),
108
+ completion: None,
109
+ });
110
+ };
111
+
112
+ self.complete_activity(task_token, status).await
113
+ }
114
+
115
+ fn record_activity_heartbeat(&self, details: ActivityHeartbeat) {
116
+ self.record_heartbeat(details);
117
+ }
118
+
119
+ fn request_workflow_eviction(&self, run_id: &str) {
120
+ self.request_wf_eviction(
121
+ run_id,
122
+ "Eviction explicitly requested by lang",
123
+ EvictionReason::LangRequested,
124
+ );
125
+ }
126
+
127
+ fn get_config(&self) -> &WorkerConfig {
128
+ &self.config
129
+ }
130
+
131
+ /// Begins the shutdown process, tells pollers they should stop. Is idempotent.
132
+ fn initiate_shutdown(&self) {
133
+ self.shutdown_token.cancel();
134
+ // First, we want to stop polling of both activity and workflow tasks
135
+ if let Some(atm) = self.at_task_mgr.as_ref() {
136
+ atm.notify_shutdown();
137
+ }
138
+ info!("Initiated shutdown");
139
+ }
140
+
141
+ async fn shutdown(&self) {
142
+ self.shutdown().await
143
+ }
144
+
145
+ async fn finalize_shutdown(self) {
146
+ self.shutdown().await;
147
+ self.finalize_shutdown().await
148
+ }
149
+ }
150
+
151
+ impl Worker {
152
+ pub(crate) fn new(
153
+ config: WorkerConfig,
154
+ sticky_queue_name: Option<String>,
155
+ client: Arc<dyn WorkerClient>,
156
+ metrics: MetricsContext,
157
+ ) -> Self {
158
+ info!(task_queue = %config.task_queue, "Initializing worker");
159
+ metrics.worker_registered();
160
+
161
+ let shutdown_token = CancellationToken::new();
162
+ let max_nonsticky_polls = if sticky_queue_name.is_some() {
163
+ config.max_nonsticky_polls()
164
+ } else {
165
+ config.max_concurrent_wft_polls
166
+ };
167
+ let max_sticky_polls = config.max_sticky_polls();
168
+ let wft_metrics = metrics.with_new_attrs([workflow_poller()]);
169
+ let mut wf_task_poll_buffer = new_workflow_task_buffer(
170
+ client.clone(),
171
+ config.task_queue.clone(),
172
+ false,
173
+ max_nonsticky_polls,
174
+ max_nonsticky_polls * 2,
175
+ shutdown_token.child_token(),
176
+ );
177
+ wf_task_poll_buffer.set_num_pollers_handler(move |np| wft_metrics.record_num_pollers(np));
178
+ let sticky_queue_poller = sticky_queue_name.as_ref().map(|sqn| {
179
+ let sticky_metrics = metrics.with_new_attrs([workflow_sticky_poller()]);
180
+ let mut sp = new_workflow_task_buffer(
181
+ client.clone(),
182
+ sqn.clone(),
183
+ true,
184
+ max_sticky_polls,
185
+ max_sticky_polls * 2,
186
+ shutdown_token.child_token(),
187
+ );
188
+ sp.set_num_pollers_handler(move |np| sticky_metrics.record_num_pollers(np));
189
+ sp
190
+ });
191
+ let act_poll_buffer = if config.no_remote_activities {
192
+ None
193
+ } else {
194
+ let mut ap = new_activity_task_buffer(
195
+ client.clone(),
196
+ config.task_queue.clone(),
197
+ config.max_concurrent_at_polls,
198
+ config.max_concurrent_at_polls * 2,
199
+ config.max_task_queue_activities_per_second,
200
+ shutdown_token.child_token(),
201
+ );
202
+ let act_metrics = metrics.with_new_attrs([activity_poller()]);
203
+ ap.set_num_pollers_handler(move |np| act_metrics.record_num_pollers(np));
204
+ Some(Box::from(ap)
205
+ as Box<
206
+ dyn Poller<PollActivityTaskQueueResponse> + Send + Sync,
207
+ >)
208
+ };
209
+ let wf_task_poll_buffer = Box::new(WorkflowTaskPoller::new(
210
+ wf_task_poll_buffer,
211
+ sticky_queue_poller,
212
+ ));
213
+ let wft_stream = new_wft_poller(wf_task_poll_buffer, metrics.clone());
214
+ Self::new_with_pollers(
215
+ config,
216
+ sticky_queue_name,
217
+ client,
218
+ wft_stream,
219
+ act_poll_buffer,
220
+ metrics,
221
+ shutdown_token,
222
+ )
223
+ }
224
+
225
+ #[cfg(test)]
226
+ pub(crate) fn new_test(config: WorkerConfig, client: impl WorkerClient + 'static) -> Self {
227
+ Self::new(config, None, Arc::new(client), Default::default())
228
+ }
229
+
230
+ pub(crate) fn new_with_pollers(
231
+ config: WorkerConfig,
232
+ sticky_queue_name: Option<String>,
233
+ client: Arc<dyn WorkerClient>,
234
+ wft_stream: impl Stream<Item = Result<ValidPollWFTQResponse, tonic::Status>> + Send + 'static,
235
+ act_poller: Option<BoxedActPoller>,
236
+ metrics: MetricsContext,
237
+ shutdown_token: CancellationToken,
238
+ ) -> Self {
239
+ let local_act_mgr = Arc::new(LocalActivityManager::new(
240
+ config.max_outstanding_local_activities,
241
+ config.namespace.clone(),
242
+ metrics.with_new_attrs([local_activity_worker_type()]),
243
+ ));
244
+ let lam_clone = local_act_mgr.clone();
245
+ let local_act_req_sink = move |requests| lam_clone.enqueue(requests);
246
+ let at_task_mgr = act_poller.map(|ap| {
247
+ WorkerActivityTasks::new(
248
+ config.max_outstanding_activities,
249
+ config.max_worker_activities_per_second,
250
+ ap,
251
+ client.clone(),
252
+ metrics.clone(),
253
+ config.max_heartbeat_throttle_interval,
254
+ config.default_heartbeat_throttle_interval,
255
+ )
256
+ });
257
+ Self {
258
+ wf_client: client.clone(),
259
+ workflows: Workflows::new(
260
+ WorkflowBasics {
261
+ max_cached_workflows: config.max_cached_workflows,
262
+ max_outstanding_wfts: config.max_outstanding_workflow_tasks,
263
+ shutdown_token: shutdown_token.child_token(),
264
+ metrics,
265
+ namespace: config.namespace.clone(),
266
+ task_queue: config.task_queue.clone(),
267
+ },
268
+ sticky_queue_name.map(|sq| StickyExecutionAttributes {
269
+ worker_task_queue: Some(TaskQueue {
270
+ name: sq,
271
+ kind: TaskQueueKind::Sticky as i32,
272
+ }),
273
+ schedule_to_start_timeout: Some(
274
+ config
275
+ .sticky_queue_schedule_to_start_timeout
276
+ .try_into()
277
+ .expect("timeout fits into proto"),
278
+ ),
279
+ }),
280
+ client,
281
+ wft_stream,
282
+ local_act_req_sink,
283
+ at_task_mgr
284
+ .as_ref()
285
+ .map(|mgr| mgr.get_handle_for_workflows()),
286
+ ),
287
+ at_task_mgr,
288
+ local_act_mgr,
289
+ config,
290
+ shutdown_token,
291
+ post_activate_hook: None,
292
+ }
293
+ }
294
+
295
+ /// Will shutdown the worker. Does not resolve until all outstanding workflow tasks have been
296
+ /// completed
297
+ async fn shutdown(&self) {
298
+ self.initiate_shutdown();
299
+ // Next we need to wait for all local activities to finish so no more workflow task
300
+ // heartbeats will be generated
301
+ self.local_act_mgr.shutdown_and_wait_all_finished().await;
302
+ // Wait for workflows to finish
303
+ self.workflows
304
+ .shutdown()
305
+ .await
306
+ .expect("Workflow processing terminates cleanly");
307
+ // Wait for activities to finish
308
+ if let Some(acts) = self.at_task_mgr.as_ref() {
309
+ acts.wait_all_finished().await;
310
+ }
311
+ }
312
+
313
+ /// Finish shutting down by consuming the background pollers and freeing all resources
314
+ async fn finalize_shutdown(self) {
315
+ if let Some(b) = self.at_task_mgr {
316
+ b.shutdown().await;
317
+ }
318
+ }
319
+
320
+ /// Returns number of currently cached workflows
321
+ pub async fn cached_workflows(&self) -> usize {
322
+ self.workflows
323
+ .get_state_info()
324
+ .await
325
+ .map(|r| r.cached_workflows)
326
+ .unwrap_or_default()
327
+ }
328
+
329
+ /// Returns number of currently outstanding workflow tasks
330
+ #[cfg(test)]
331
+ pub(crate) async fn outstanding_workflow_tasks(&self) -> usize {
332
+ self.workflows
333
+ .get_state_info()
334
+ .await
335
+ .map(|r| r.outstanding_wft)
336
+ .unwrap_or_default()
337
+ }
338
+
339
+ #[cfg(test)]
340
+ pub(crate) async fn available_wft_permits(&self) -> usize {
341
+ self.workflows
342
+ .get_state_info()
343
+ .await
344
+ .expect("You can only check for available permits before shutdown")
345
+ .available_wft_permits
346
+ }
347
+
348
+ /// Get new activity tasks (may be local or nonlocal). Local activities are returned first
349
+ /// before polling the server if there are any.
350
+ ///
351
+ /// Returns `Ok(None)` in the event of a poll timeout or if the polling loop should otherwise
352
+ /// be restarted
353
+ async fn activity_poll(&self) -> Result<Option<ActivityTask>, PollActivityError> {
354
+ let act_mgr_poll = async {
355
+ if let Some(ref act_mgr) = self.at_task_mgr {
356
+ act_mgr.poll().await
357
+ } else {
358
+ info!("Activity polling is disabled for this worker");
359
+ self.shutdown_token.cancelled().await;
360
+ Err(PollActivityError::ShutDown)
361
+ }
362
+ };
363
+
364
+ tokio::select! {
365
+ biased;
366
+
367
+ r = self.local_act_mgr.next_pending() => {
368
+ match r {
369
+ Some(DispatchOrTimeoutLA::Dispatch(r)) => Ok(Some(r)),
370
+ Some(DispatchOrTimeoutLA::Timeout { run_id, resolution, task }) => {
371
+ self.notify_local_result(
372
+ &run_id, LocalResolution::LocalActivity(resolution));
373
+ Ok(task)
374
+ },
375
+ None => {
376
+ if self.shutdown_token.is_cancelled() {
377
+ return Err(PollActivityError::ShutDown);
378
+ }
379
+ Ok(None)
380
+ }
381
+ }
382
+ },
383
+ r = act_mgr_poll => r,
384
+ }
385
+ }
386
+
387
+ /// Attempt to record an activity heartbeat
388
+ pub(crate) fn record_heartbeat(&self, details: ActivityHeartbeat) {
389
+ if let Some(at_mgr) = self.at_task_mgr.as_ref() {
390
+ let tt = details.task_token.clone();
391
+ if let Err(e) = at_mgr.record_heartbeat(details) {
392
+ warn!(task_token = ?tt, details = ?e, "Activity heartbeat failed.");
393
+ }
394
+ }
395
+ }
396
+
397
+ pub(crate) async fn complete_activity(
398
+ &self,
399
+ task_token: TaskToken,
400
+ status: activity_execution_result::Status,
401
+ ) -> Result<(), CompleteActivityError> {
402
+ validate_activity_completion(&status)?;
403
+ if task_token.is_local_activity_task() {
404
+ let as_la_res: LocalActivityExecutionResult = status.try_into()?;
405
+ match self.local_act_mgr.complete(&task_token, &as_la_res) {
406
+ LACompleteAction::Report(info) => self.complete_local_act(as_la_res, info, None),
407
+ LACompleteAction::LangDoesTimerBackoff(backoff, info) => {
408
+ // This la needs to write a failure marker, and then we will tell lang how
409
+ // long of a timer to schedule to back off for. We do this because there are
410
+ // no other situations where core generates "internal" commands so it is much
411
+ // simpler for lang to reply with the timer / next LA command than to do it
412
+ // internally. Plus, this backoff hack we'd like to eliminate eventually.
413
+ self.complete_local_act(as_la_res, info, Some(backoff));
414
+ }
415
+ LACompleteAction::WillBeRetried => {
416
+ // Nothing to do here
417
+ }
418
+ LACompleteAction::Untracked => {
419
+ warn!("Tried to complete untracked local activity {}", task_token);
420
+ }
421
+ }
422
+ return Ok(());
423
+ }
424
+
425
+ if let Some(atm) = &self.at_task_mgr {
426
+ atm.complete(task_token, status, &*self.wf_client).await;
427
+ } else {
428
+ error!(
429
+ "Tried to complete activity {} on a worker that does not have an activity manager",
430
+ task_token
431
+ );
432
+ }
433
+ Ok(())
434
+ }
435
+
436
+ #[instrument(level = "debug", skip(self), fields(run_id))]
437
+ pub(crate) async fn next_workflow_activation(&self) -> Result<WorkflowActivation, PollWfError> {
438
+ self.workflows.next_workflow_activation().await
439
+ }
440
+
441
+ #[instrument(level = "debug", skip(self, completion),
442
+ fields(completion=%&completion, run_id=%completion.run_id))]
443
+ pub(crate) async fn complete_workflow_activation(
444
+ &self,
445
+ completion: WorkflowActivationCompletion,
446
+ ) -> Result<(), CompleteWfError> {
447
+ let run_id = completion.run_id.clone();
448
+ let most_recent_event = self.workflows.activation_completed(completion).await?;
449
+ if let Some(h) = &self.post_activate_hook {
450
+ h(self, &run_id, most_recent_event);
451
+ }
452
+ Ok(())
453
+ }
454
+
455
+ /// Request a workflow eviction
456
+ pub(crate) fn request_wf_eviction(
457
+ &self,
458
+ run_id: &str,
459
+ message: impl Into<String>,
460
+ reason: EvictionReason,
461
+ ) {
462
+ self.workflows.request_eviction(run_id, message, reason);
463
+ }
464
+
465
+ /// Sets a function to be called at the end of each activation completion
466
+ pub(crate) fn set_post_activate_hook(
467
+ &mut self,
468
+ callback: impl Fn(&Self, &str, usize) + Send + Sync + 'static,
469
+ ) {
470
+ self.post_activate_hook = Some(Box::new(callback))
471
+ }
472
+
473
+ /// Used for replay workers - causes the worker to shutdown when the given run reaches the
474
+ /// given event number
475
+ pub(crate) fn set_shutdown_on_run_reaches_event(&mut self, run_id: String, last_event: i64) {
476
+ self.set_post_activate_hook(move |worker, activated_run_id, last_processed_event| {
477
+ if activated_run_id == run_id && last_processed_event >= last_event as usize {
478
+ worker.initiate_shutdown();
479
+ }
480
+ });
481
+ }
482
+
483
+ fn complete_local_act(
484
+ &self,
485
+ la_res: LocalActivityExecutionResult,
486
+ info: LocalInFlightActInfo,
487
+ backoff: Option<prost_types::Duration>,
488
+ ) {
489
+ self.notify_local_result(
490
+ &info.la_info.workflow_exec_info.run_id,
491
+ LocalResolution::LocalActivity(LocalActivityResolution {
492
+ seq: info.la_info.schedule_cmd.seq,
493
+ result: la_res,
494
+ runtime: info.dispatch_time.elapsed(),
495
+ attempt: info.attempt,
496
+ backoff,
497
+ original_schedule_time: Some(info.la_info.schedule_time),
498
+ }),
499
+ )
500
+ }
501
+
502
+ fn notify_local_result(&self, run_id: &str, res: LocalResolution) {
503
+ self.workflows.notify_of_local_result(run_id, res);
504
+ }
505
+ }
506
+
507
+ #[cfg(test)]
508
+ mod tests {
509
+ use super::*;
510
+ use crate::{test_help::test_worker_cfg, worker::client::mocks::mock_workflow_client};
511
+ use temporal_sdk_core_protos::temporal::api::workflowservice::v1::PollActivityTaskQueueResponse;
512
+
513
+ #[tokio::test]
514
+ async fn activity_timeouts_dont_eat_permits() {
515
+ let mut mock_client = mock_workflow_client();
516
+ mock_client
517
+ .expect_poll_activity_task()
518
+ .returning(|_, _| Ok(PollActivityTaskQueueResponse::default()));
519
+
520
+ let cfg = test_worker_cfg()
521
+ .max_outstanding_activities(5_usize)
522
+ .build()
523
+ .unwrap();
524
+ let worker = Worker::new_test(cfg, mock_client);
525
+ assert_eq!(worker.activity_poll().await.unwrap(), None);
526
+ assert_eq!(worker.at_task_mgr.unwrap().remaining_activity_capacity(), 5);
527
+ }
528
+
529
+ #[tokio::test]
530
+ async fn activity_errs_dont_eat_permits() {
531
+ let mut mock_client = mock_workflow_client();
532
+ mock_client
533
+ .expect_poll_activity_task()
534
+ .returning(|_, _| Err(tonic::Status::internal("ahhh")));
535
+
536
+ let cfg = test_worker_cfg()
537
+ .max_outstanding_activities(5_usize)
538
+ .build()
539
+ .unwrap();
540
+ let worker = Worker::new_test(cfg, mock_client);
541
+ assert!(worker.activity_poll().await.is_err());
542
+ assert_eq!(worker.at_task_mgr.unwrap().remaining_activity_capacity(), 5);
543
+ }
544
+
545
+ #[test]
546
+ fn max_polls_calculated_properly() {
547
+ let mut wcb = WorkerConfigBuilder::default();
548
+ let cfg = wcb
549
+ .namespace("default")
550
+ .task_queue("whatever")
551
+ .worker_build_id("test_bin_id")
552
+ .max_concurrent_wft_polls(5_usize)
553
+ .build()
554
+ .unwrap();
555
+ assert_eq!(cfg.max_nonsticky_polls(), 1);
556
+ assert_eq!(cfg.max_sticky_polls(), 4);
557
+ }
558
+
559
+ #[test]
560
+ fn max_polls_zero_is_err() {
561
+ assert!(test_worker_cfg()
562
+ .max_concurrent_wft_polls(0_usize)
563
+ .build()
564
+ .is_err());
565
+ }
566
+ }
@@ -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
+ }