temporalio 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (469) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +4035 -0
  3. data/Cargo.toml +25 -0
  4. data/Gemfile +20 -0
  5. data/LICENSE +16 -15
  6. data/README.md +455 -195
  7. data/Rakefile +387 -0
  8. data/ext/Cargo.toml +25 -0
  9. data/lib/temporalio/activity/complete_async_error.rb +11 -0
  10. data/lib/temporalio/activity/context.rb +82 -77
  11. data/lib/temporalio/activity/definition.rb +77 -0
  12. data/lib/temporalio/activity/info.rb +42 -46
  13. data/lib/temporalio/activity.rb +49 -65
  14. data/lib/temporalio/api/batch/v1/message.rb +31 -0
  15. data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +93 -0
  16. data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +25 -0
  17. data/lib/temporalio/api/cloud/cloudservice.rb +3 -0
  18. data/lib/temporalio/api/cloud/identity/v1/message.rb +36 -0
  19. data/lib/temporalio/api/cloud/namespace/v1/message.rb +35 -0
  20. data/lib/temporalio/api/cloud/operation/v1/message.rb +27 -0
  21. data/lib/temporalio/api/cloud/region/v1/message.rb +23 -0
  22. data/lib/temporalio/api/command/v1/message.rb +46 -0
  23. data/lib/temporalio/api/common/v1/grpc_status.rb +23 -0
  24. data/lib/temporalio/api/common/v1/message.rb +41 -0
  25. data/lib/temporalio/api/enums/v1/batch_operation.rb +22 -0
  26. data/lib/temporalio/api/enums/v1/command_type.rb +21 -0
  27. data/lib/temporalio/api/enums/v1/common.rb +26 -0
  28. data/lib/temporalio/api/enums/v1/event_type.rb +21 -0
  29. data/lib/temporalio/api/enums/v1/failed_cause.rb +26 -0
  30. data/lib/temporalio/api/enums/v1/namespace.rb +23 -0
  31. data/lib/temporalio/api/enums/v1/query.rb +22 -0
  32. data/lib/temporalio/api/enums/v1/reset.rb +23 -0
  33. data/lib/temporalio/api/enums/v1/schedule.rb +21 -0
  34. data/lib/temporalio/api/enums/v1/task_queue.rb +25 -0
  35. data/lib/temporalio/api/enums/v1/update.rb +22 -0
  36. data/lib/temporalio/api/enums/v1/workflow.rb +30 -0
  37. data/lib/temporalio/api/errordetails/v1/message.rb +42 -0
  38. data/lib/temporalio/api/export/v1/message.rb +24 -0
  39. data/lib/temporalio/api/failure/v1/message.rb +35 -0
  40. data/lib/temporalio/api/filter/v1/message.rb +27 -0
  41. data/lib/temporalio/api/history/v1/message.rb +90 -0
  42. data/lib/temporalio/api/namespace/v1/message.rb +31 -0
  43. data/lib/temporalio/api/nexus/v1/message.rb +40 -0
  44. data/lib/temporalio/api/operatorservice/v1/request_response.rb +49 -0
  45. data/lib/temporalio/api/operatorservice/v1/service.rb +23 -0
  46. data/lib/temporalio/api/operatorservice.rb +3 -0
  47. data/lib/temporalio/api/protocol/v1/message.rb +23 -0
  48. data/lib/temporalio/api/query/v1/message.rb +27 -0
  49. data/lib/temporalio/api/replication/v1/message.rb +26 -0
  50. data/lib/temporalio/api/schedule/v1/message.rb +42 -0
  51. data/lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb +25 -0
  52. data/lib/temporalio/api/sdk/v1/task_complete_metadata.rb +21 -0
  53. data/lib/temporalio/api/sdk/v1/user_metadata.rb +23 -0
  54. data/lib/temporalio/api/sdk/v1/workflow_metadata.rb +23 -0
  55. data/lib/temporalio/api/taskqueue/v1/message.rb +45 -0
  56. data/lib/temporalio/api/update/v1/message.rb +33 -0
  57. data/lib/temporalio/api/version/v1/message.rb +26 -0
  58. data/lib/temporalio/api/workflow/v1/message.rb +43 -0
  59. data/lib/temporalio/api/workflowservice/v1/request_response.rb +189 -0
  60. data/lib/temporalio/api/workflowservice/v1/service.rb +23 -0
  61. data/lib/temporalio/api/workflowservice.rb +3 -0
  62. data/lib/temporalio/api.rb +13 -0
  63. data/lib/temporalio/cancellation.rb +150 -0
  64. data/lib/temporalio/client/activity_id_reference.rb +32 -0
  65. data/lib/temporalio/client/async_activity_handle.rb +110 -0
  66. data/lib/temporalio/client/connection/cloud_service.rb +648 -0
  67. data/lib/temporalio/client/connection/operator_service.rb +249 -0
  68. data/lib/temporalio/client/connection/service.rb +41 -0
  69. data/lib/temporalio/client/connection/workflow_service.rb +1218 -0
  70. data/lib/temporalio/client/connection.rb +270 -0
  71. data/lib/temporalio/client/interceptor.rb +316 -0
  72. data/lib/temporalio/client/workflow_execution.rb +103 -0
  73. data/lib/temporalio/client/workflow_execution_count.rb +36 -0
  74. data/lib/temporalio/client/workflow_execution_status.rb +18 -0
  75. data/lib/temporalio/client/workflow_handle.rb +380 -177
  76. data/lib/temporalio/client/workflow_query_reject_condition.rb +14 -0
  77. data/lib/temporalio/client/workflow_update_handle.rb +67 -0
  78. data/lib/temporalio/client/workflow_update_wait_stage.rb +17 -0
  79. data/lib/temporalio/client.rb +366 -93
  80. data/lib/temporalio/common_enums.rb +24 -0
  81. data/lib/temporalio/converters/data_converter.rb +102 -0
  82. data/lib/temporalio/converters/failure_converter.rb +200 -0
  83. data/lib/temporalio/converters/payload_codec.rb +26 -0
  84. data/lib/temporalio/converters/payload_converter/binary_null.rb +34 -0
  85. data/lib/temporalio/converters/payload_converter/binary_plain.rb +35 -0
  86. data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +42 -0
  87. data/lib/temporalio/converters/payload_converter/composite.rb +62 -0
  88. data/lib/temporalio/converters/payload_converter/encoding.rb +35 -0
  89. data/lib/temporalio/converters/payload_converter/json_plain.rb +44 -0
  90. data/lib/temporalio/converters/payload_converter/json_protobuf.rb +41 -0
  91. data/lib/temporalio/converters/payload_converter.rb +73 -0
  92. data/lib/temporalio/converters.rb +9 -0
  93. data/lib/temporalio/error/failure.rb +119 -94
  94. data/lib/temporalio/error.rb +147 -0
  95. data/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +34 -0
  96. data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +31 -0
  97. data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +33 -0
  98. data/lib/temporalio/internal/bridge/api/common/common.rb +26 -0
  99. data/lib/temporalio/internal/bridge/api/core_interface.rb +36 -0
  100. data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +27 -0
  101. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +52 -0
  102. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +54 -0
  103. data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +30 -0
  104. data/lib/temporalio/internal/bridge/api.rb +3 -0
  105. data/lib/temporalio/internal/bridge/client.rb +90 -0
  106. data/lib/temporalio/internal/bridge/runtime.rb +53 -0
  107. data/lib/temporalio/internal/bridge/testing.rb +46 -0
  108. data/lib/temporalio/internal/bridge/worker.rb +83 -0
  109. data/lib/temporalio/internal/bridge.rb +36 -0
  110. data/lib/temporalio/internal/client/implementation.rb +525 -0
  111. data/lib/temporalio/internal/proto_utils.rb +54 -0
  112. data/lib/temporalio/internal/worker/activity_worker.rb +345 -0
  113. data/lib/temporalio/internal/worker/multi_runner.rb +169 -0
  114. data/lib/temporalio/internal.rb +7 -0
  115. data/lib/temporalio/retry_policy.rb +39 -80
  116. data/lib/temporalio/runtime.rb +259 -13
  117. data/lib/temporalio/scoped_logger.rb +96 -0
  118. data/lib/temporalio/search_attributes.rb +300 -0
  119. data/lib/temporalio/testing/activity_environment.rb +132 -0
  120. data/lib/temporalio/testing/workflow_environment.rb +113 -88
  121. data/lib/temporalio/testing.rb +4 -169
  122. data/lib/temporalio/version.rb +3 -1
  123. data/lib/temporalio/worker/activity_executor/fiber.rb +49 -0
  124. data/lib/temporalio/worker/activity_executor/thread_pool.rb +254 -0
  125. data/lib/temporalio/worker/activity_executor.rb +55 -0
  126. data/lib/temporalio/worker/interceptor.rb +88 -0
  127. data/lib/temporalio/worker/tuner.rb +151 -0
  128. data/lib/temporalio/worker.rb +385 -163
  129. data/lib/temporalio/workflow_history.rb +22 -0
  130. data/lib/temporalio.rb +2 -7
  131. data/temporalio.gemspec +20 -38
  132. metadata +131 -596
  133. data/bridge/Cargo.lock +0 -2997
  134. data/bridge/Cargo.toml +0 -29
  135. data/bridge/sdk-core/ARCHITECTURE.md +0 -76
  136. data/bridge/sdk-core/Cargo.toml +0 -2
  137. data/bridge/sdk-core/LICENSE.txt +0 -23
  138. data/bridge/sdk-core/README.md +0 -117
  139. data/bridge/sdk-core/arch_docs/diagrams/README.md +0 -10
  140. data/bridge/sdk-core/arch_docs/diagrams/sticky_queues.puml +0 -40
  141. data/bridge/sdk-core/arch_docs/diagrams/workflow_internals.svg +0 -1
  142. data/bridge/sdk-core/arch_docs/sticky_queues.md +0 -51
  143. data/bridge/sdk-core/client/Cargo.toml +0 -40
  144. data/bridge/sdk-core/client/LICENSE.txt +0 -23
  145. data/bridge/sdk-core/client/src/lib.rs +0 -1462
  146. data/bridge/sdk-core/client/src/metrics.rs +0 -174
  147. data/bridge/sdk-core/client/src/raw.rs +0 -932
  148. data/bridge/sdk-core/client/src/retry.rs +0 -763
  149. data/bridge/sdk-core/client/src/workflow_handle/mod.rs +0 -185
  150. data/bridge/sdk-core/core/Cargo.toml +0 -129
  151. data/bridge/sdk-core/core/LICENSE.txt +0 -23
  152. data/bridge/sdk-core/core/benches/workflow_replay.rs +0 -76
  153. data/bridge/sdk-core/core/src/abstractions.rs +0 -355
  154. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +0 -1049
  155. data/bridge/sdk-core/core/src/core_tests/child_workflows.rs +0 -221
  156. data/bridge/sdk-core/core/src/core_tests/determinism.rs +0 -270
  157. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +0 -1046
  158. data/bridge/sdk-core/core/src/core_tests/mod.rs +0 -100
  159. data/bridge/sdk-core/core/src/core_tests/queries.rs +0 -893
  160. data/bridge/sdk-core/core/src/core_tests/replay_flag.rs +0 -65
  161. data/bridge/sdk-core/core/src/core_tests/workers.rs +0 -257
  162. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +0 -124
  163. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +0 -2433
  164. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +0 -609
  165. data/bridge/sdk-core/core/src/internal_flags.rs +0 -136
  166. data/bridge/sdk-core/core/src/lib.rs +0 -289
  167. data/bridge/sdk-core/core/src/pollers/mod.rs +0 -54
  168. data/bridge/sdk-core/core/src/pollers/poll_buffer.rs +0 -297
  169. data/bridge/sdk-core/core/src/protosext/mod.rs +0 -428
  170. data/bridge/sdk-core/core/src/replay/mod.rs +0 -215
  171. data/bridge/sdk-core/core/src/retry_logic.rs +0 -202
  172. data/bridge/sdk-core/core/src/telemetry/log_export.rs +0 -190
  173. data/bridge/sdk-core/core/src/telemetry/metrics.rs +0 -462
  174. data/bridge/sdk-core/core/src/telemetry/mod.rs +0 -423
  175. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +0 -83
  176. data/bridge/sdk-core/core/src/test_help/mod.rs +0 -939
  177. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +0 -536
  178. data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +0 -89
  179. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +0 -1278
  180. data/bridge/sdk-core/core/src/worker/activities.rs +0 -557
  181. data/bridge/sdk-core/core/src/worker/client/mocks.rs +0 -107
  182. data/bridge/sdk-core/core/src/worker/client.rs +0 -389
  183. data/bridge/sdk-core/core/src/worker/mod.rs +0 -677
  184. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +0 -35
  185. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +0 -99
  186. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +0 -1111
  187. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +0 -964
  188. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +0 -294
  189. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +0 -168
  190. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +0 -918
  191. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +0 -137
  192. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +0 -158
  193. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +0 -130
  194. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +0 -1525
  195. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +0 -324
  196. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -179
  197. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +0 -659
  198. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +0 -439
  199. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +0 -435
  200. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +0 -175
  201. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +0 -249
  202. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +0 -85
  203. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +0 -1280
  204. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +0 -269
  205. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +0 -213
  206. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +0 -1305
  207. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +0 -1276
  208. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +0 -128
  209. data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +0 -125
  210. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +0 -85
  211. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +0 -117
  212. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +0 -24
  213. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +0 -715
  214. data/bridge/sdk-core/core-api/Cargo.toml +0 -33
  215. data/bridge/sdk-core/core-api/LICENSE.txt +0 -23
  216. data/bridge/sdk-core/core-api/src/errors.rs +0 -62
  217. data/bridge/sdk-core/core-api/src/lib.rs +0 -113
  218. data/bridge/sdk-core/core-api/src/telemetry.rs +0 -141
  219. data/bridge/sdk-core/core-api/src/worker.rs +0 -161
  220. data/bridge/sdk-core/etc/deps.svg +0 -162
  221. data/bridge/sdk-core/etc/dynamic-config.yaml +0 -2
  222. data/bridge/sdk-core/etc/otel-collector-config.yaml +0 -36
  223. data/bridge/sdk-core/etc/prometheus.yaml +0 -6
  224. data/bridge/sdk-core/etc/regen-depgraph.sh +0 -5
  225. data/bridge/sdk-core/fsm/Cargo.toml +0 -18
  226. data/bridge/sdk-core/fsm/LICENSE.txt +0 -23
  227. data/bridge/sdk-core/fsm/README.md +0 -3
  228. data/bridge/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +0 -27
  229. data/bridge/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +0 -23
  230. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +0 -650
  231. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +0 -8
  232. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.rs +0 -18
  233. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +0 -12
  234. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dynamic_dest_pass.rs +0 -41
  235. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.rs +0 -14
  236. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.stderr +0 -11
  237. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_arg_pass.rs +0 -32
  238. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_pass.rs +0 -31
  239. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/medium_complex_pass.rs +0 -46
  240. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.rs +0 -29
  241. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +0 -12
  242. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/simple_pass.rs +0 -32
  243. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.rs +0 -18
  244. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +0 -5
  245. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.rs +0 -11
  246. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +0 -5
  247. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.rs +0 -11
  248. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +0 -5
  249. data/bridge/sdk-core/fsm/rustfsm_trait/Cargo.toml +0 -14
  250. data/bridge/sdk-core/fsm/rustfsm_trait/LICENSE.txt +0 -23
  251. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +0 -254
  252. data/bridge/sdk-core/fsm/src/lib.rs +0 -2
  253. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  254. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  255. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  256. data/bridge/sdk-core/histories/fail_wf_task.bin +0 -0
  257. data/bridge/sdk-core/histories/timer_workflow_history.bin +0 -0
  258. data/bridge/sdk-core/integ-with-otel.sh +0 -7
  259. data/bridge/sdk-core/protos/api_upstream/README.md +0 -9
  260. data/bridge/sdk-core/protos/api_upstream/api-linter.yaml +0 -40
  261. data/bridge/sdk-core/protos/api_upstream/buf.yaml +0 -9
  262. data/bridge/sdk-core/protos/api_upstream/build/go.mod +0 -7
  263. data/bridge/sdk-core/protos/api_upstream/build/go.sum +0 -5
  264. data/bridge/sdk-core/protos/api_upstream/build/tools.go +0 -29
  265. data/bridge/sdk-core/protos/api_upstream/dependencies/gogoproto/gogo.proto +0 -141
  266. data/bridge/sdk-core/protos/api_upstream/go.mod +0 -6
  267. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +0 -89
  268. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +0 -248
  269. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +0 -123
  270. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -47
  271. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +0 -52
  272. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +0 -56
  273. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +0 -170
  274. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +0 -123
  275. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +0 -51
  276. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +0 -50
  277. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +0 -41
  278. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +0 -60
  279. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -59
  280. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +0 -56
  281. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +0 -122
  282. data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +0 -108
  283. data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +0 -114
  284. data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +0 -56
  285. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +0 -787
  286. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +0 -99
  287. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +0 -124
  288. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -80
  289. data/bridge/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +0 -57
  290. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +0 -61
  291. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +0 -55
  292. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +0 -379
  293. data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +0 -63
  294. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +0 -108
  295. data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +0 -111
  296. data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +0 -59
  297. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +0 -146
  298. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +0 -1199
  299. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +0 -415
  300. data/bridge/sdk-core/protos/grpc/health/v1/health.proto +0 -63
  301. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +0 -79
  302. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +0 -80
  303. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -78
  304. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +0 -16
  305. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +0 -31
  306. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +0 -31
  307. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +0 -270
  308. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +0 -305
  309. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -35
  310. data/bridge/sdk-core/protos/testsrv_upstream/api-linter.yaml +0 -38
  311. data/bridge/sdk-core/protos/testsrv_upstream/buf.yaml +0 -13
  312. data/bridge/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +0 -141
  313. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -63
  314. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -90
  315. data/bridge/sdk-core/rustfmt.toml +0 -1
  316. data/bridge/sdk-core/sdk/Cargo.toml +0 -48
  317. data/bridge/sdk-core/sdk/LICENSE.txt +0 -23
  318. data/bridge/sdk-core/sdk/src/activity_context.rs +0 -230
  319. data/bridge/sdk-core/sdk/src/app_data.rs +0 -37
  320. data/bridge/sdk-core/sdk/src/interceptors.rs +0 -50
  321. data/bridge/sdk-core/sdk/src/lib.rs +0 -861
  322. data/bridge/sdk-core/sdk/src/payload_converter.rs +0 -11
  323. data/bridge/sdk-core/sdk/src/workflow_context/options.rs +0 -295
  324. data/bridge/sdk-core/sdk/src/workflow_context.rs +0 -694
  325. data/bridge/sdk-core/sdk/src/workflow_future.rs +0 -500
  326. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +0 -33
  327. data/bridge/sdk-core/sdk-core-protos/LICENSE.txt +0 -23
  328. data/bridge/sdk-core/sdk-core-protos/build.rs +0 -142
  329. data/bridge/sdk-core/sdk-core-protos/src/constants.rs +0 -7
  330. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +0 -557
  331. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +0 -234
  332. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +0 -2088
  333. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +0 -48
  334. data/bridge/sdk-core/sdk-core-protos/src/utilities.rs +0 -14
  335. data/bridge/sdk-core/test-utils/Cargo.toml +0 -38
  336. data/bridge/sdk-core/test-utils/src/canned_histories.rs +0 -1389
  337. data/bridge/sdk-core/test-utils/src/histfetch.rs +0 -28
  338. data/bridge/sdk-core/test-utils/src/lib.rs +0 -709
  339. data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +0 -50
  340. data/bridge/sdk-core/test-utils/src/workflows.rs +0 -29
  341. data/bridge/sdk-core/tests/fuzzy_workflow.rs +0 -130
  342. data/bridge/sdk-core/tests/heavy_tests.rs +0 -265
  343. data/bridge/sdk-core/tests/integ_tests/client_tests.rs +0 -36
  344. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +0 -150
  345. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +0 -223
  346. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +0 -239
  347. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +0 -90
  348. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +0 -314
  349. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +0 -151
  350. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +0 -902
  351. data/bridge/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
  352. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +0 -60
  353. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +0 -51
  354. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +0 -51
  355. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +0 -64
  356. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +0 -47
  357. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +0 -669
  358. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +0 -54
  359. data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +0 -92
  360. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +0 -228
  361. data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +0 -94
  362. data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +0 -171
  363. data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +0 -85
  364. data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +0 -120
  365. data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +0 -77
  366. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +0 -596
  367. data/bridge/sdk-core/tests/main.rs +0 -103
  368. data/bridge/sdk-core/tests/runner.rs +0 -132
  369. data/bridge/sdk-core/tests/wf_input_replay.rs +0 -32
  370. data/bridge/src/connection.rs +0 -202
  371. data/bridge/src/lib.rs +0 -494
  372. data/bridge/src/runtime.rs +0 -54
  373. data/bridge/src/test_server.rs +0 -153
  374. data/bridge/src/worker.rs +0 -197
  375. data/ext/Rakefile +0 -9
  376. data/lib/gen/dependencies/gogoproto/gogo_pb.rb +0 -14
  377. data/lib/gen/temporal/api/batch/v1/message_pb.rb +0 -50
  378. data/lib/gen/temporal/api/command/v1/message_pb.rb +0 -160
  379. data/lib/gen/temporal/api/common/v1/message_pb.rb +0 -73
  380. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +0 -33
  381. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +0 -37
  382. data/lib/gen/temporal/api/enums/v1/common_pb.rb +0 -42
  383. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +0 -68
  384. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +0 -79
  385. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +0 -37
  386. data/lib/gen/temporal/api/enums/v1/query_pb.rb +0 -31
  387. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +0 -24
  388. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +0 -28
  389. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +0 -30
  390. data/lib/gen/temporal/api/enums/v1/update_pb.rb +0 -25
  391. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +0 -89
  392. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +0 -84
  393. data/lib/gen/temporal/api/failure/v1/message_pb.rb +0 -83
  394. data/lib/gen/temporal/api/filter/v1/message_pb.rb +0 -40
  395. data/lib/gen/temporal/api/history/v1/message_pb.rb +0 -498
  396. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +0 -64
  397. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +0 -88
  398. data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +0 -20
  399. data/lib/gen/temporal/api/protocol/v1/message_pb.rb +0 -30
  400. data/lib/gen/temporal/api/query/v1/message_pb.rb +0 -38
  401. data/lib/gen/temporal/api/replication/v1/message_pb.rb +0 -37
  402. data/lib/gen/temporal/api/schedule/v1/message_pb.rb +0 -149
  403. data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +0 -23
  404. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +0 -73
  405. data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +0 -49
  406. data/lib/gen/temporal/api/testservice/v1/service_pb.rb +0 -21
  407. data/lib/gen/temporal/api/update/v1/message_pb.rb +0 -72
  408. data/lib/gen/temporal/api/version/v1/message_pb.rb +0 -41
  409. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +0 -111
  410. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +0 -798
  411. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +0 -20
  412. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +0 -62
  413. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +0 -61
  414. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +0 -61
  415. data/lib/gen/temporal/sdk/core/common/common_pb.rb +0 -26
  416. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +0 -40
  417. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +0 -31
  418. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +0 -171
  419. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +0 -200
  420. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +0 -41
  421. data/lib/temporalio/bridge/connect_options.rb +0 -15
  422. data/lib/temporalio/bridge/error.rb +0 -8
  423. data/lib/temporalio/bridge/retry_config.rb +0 -24
  424. data/lib/temporalio/bridge/tls_options.rb +0 -19
  425. data/lib/temporalio/bridge.rb +0 -14
  426. data/lib/temporalio/client/implementation.rb +0 -340
  427. data/lib/temporalio/connection/retry_config.rb +0 -44
  428. data/lib/temporalio/connection/service.rb +0 -20
  429. data/lib/temporalio/connection/test_service.rb +0 -92
  430. data/lib/temporalio/connection/tls_options.rb +0 -51
  431. data/lib/temporalio/connection/workflow_service.rb +0 -731
  432. data/lib/temporalio/connection.rb +0 -86
  433. data/lib/temporalio/data_converter.rb +0 -191
  434. data/lib/temporalio/error/workflow_failure.rb +0 -19
  435. data/lib/temporalio/errors.rb +0 -40
  436. data/lib/temporalio/failure_converter/base.rb +0 -26
  437. data/lib/temporalio/failure_converter/basic.rb +0 -319
  438. data/lib/temporalio/failure_converter.rb +0 -7
  439. data/lib/temporalio/interceptor/activity_inbound.rb +0 -22
  440. data/lib/temporalio/interceptor/activity_outbound.rb +0 -24
  441. data/lib/temporalio/interceptor/chain.rb +0 -28
  442. data/lib/temporalio/interceptor/client.rb +0 -127
  443. data/lib/temporalio/interceptor.rb +0 -22
  444. data/lib/temporalio/payload_codec/base.rb +0 -32
  445. data/lib/temporalio/payload_converter/base.rb +0 -24
  446. data/lib/temporalio/payload_converter/bytes.rb +0 -27
  447. data/lib/temporalio/payload_converter/composite.rb +0 -49
  448. data/lib/temporalio/payload_converter/encoding_base.rb +0 -35
  449. data/lib/temporalio/payload_converter/json.rb +0 -26
  450. data/lib/temporalio/payload_converter/nil.rb +0 -26
  451. data/lib/temporalio/payload_converter.rb +0 -14
  452. data/lib/temporalio/retry_state.rb +0 -35
  453. data/lib/temporalio/testing/time_skipping_handle.rb +0 -32
  454. data/lib/temporalio/testing/time_skipping_interceptor.rb +0 -23
  455. data/lib/temporalio/timeout_type.rb +0 -29
  456. data/lib/temporalio/worker/activity_runner.rb +0 -114
  457. data/lib/temporalio/worker/activity_worker.rb +0 -164
  458. data/lib/temporalio/worker/reactor.rb +0 -46
  459. data/lib/temporalio/worker/runner.rb +0 -63
  460. data/lib/temporalio/worker/sync_worker.rb +0 -124
  461. data/lib/temporalio/worker/thread_pool_executor.rb +0 -51
  462. data/lib/temporalio/workflow/async.rb +0 -46
  463. data/lib/temporalio/workflow/execution_info.rb +0 -54
  464. data/lib/temporalio/workflow/execution_status.rb +0 -36
  465. data/lib/temporalio/workflow/future.rb +0 -138
  466. data/lib/temporalio/workflow/id_reuse_policy.rb +0 -36
  467. data/lib/temporalio/workflow/info.rb +0 -76
  468. data/lib/temporalio/workflow/query_reject_condition.rb +0 -33
  469. data/lib/thermite_patch.rb +0 -23
@@ -1,1278 +0,0 @@
1
- use crate::{
2
- abstractions::{dbg_panic, MeteredSemaphore, OwnedMeteredSemPermit, UsedMeteredSemPermit},
3
- protosext::ValidScheduleLA,
4
- retry_logic::RetryPolicyExt,
5
- worker::workflow::HeartbeatTimeoutMsg,
6
- MetricsContext, TaskToken,
7
- };
8
- use futures::{stream::BoxStream, Stream};
9
- use futures_util::{future, future::AbortRegistration, stream, StreamExt};
10
- use parking_lot::{Mutex, MutexGuard};
11
- use std::{
12
- collections::{hash_map::Entry, HashMap},
13
- fmt::{Debug, Formatter},
14
- pin::Pin,
15
- task::{Context, Poll},
16
- time::{Duration, Instant, SystemTime},
17
- };
18
- use temporal_sdk_core_protos::{
19
- coresdk::{
20
- activity_result::{Cancellation, Failure as ActFail, Success},
21
- activity_task::{activity_task, ActivityCancelReason, ActivityTask, Cancel, Start},
22
- },
23
- temporal::api::{common::v1::WorkflowExecution, enums::v1::TimeoutType},
24
- };
25
- use tokio::{
26
- sync::{
27
- mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
28
- Notify,
29
- },
30
- task::JoinHandle,
31
- time::sleep,
32
- };
33
- use tokio_stream::wrappers::UnboundedReceiverStream;
34
- use tokio_util::sync::CancellationToken;
35
-
36
- #[allow(clippy::large_enum_variant)] // Timeouts are relatively rare
37
- #[derive(Debug)]
38
- pub(crate) enum DispatchOrTimeoutLA {
39
- /// Send the activity task to lang
40
- Dispatch(ActivityTask),
41
- /// Notify the machines (and maybe lang) that this LA has timed out
42
- Timeout {
43
- run_id: String,
44
- resolution: LocalActivityResolution,
45
- task: Option<ActivityTask>,
46
- },
47
- }
48
-
49
- #[derive(Debug)]
50
- pub(crate) struct LocalInFlightActInfo {
51
- pub la_info: NewLocalAct,
52
- pub dispatch_time: Instant,
53
- pub attempt: u32,
54
- _permit: UsedMeteredSemPermit,
55
- }
56
-
57
- #[derive(Debug, Clone)]
58
- #[cfg_attr(
59
- feature = "save_wf_inputs",
60
- derive(serde::Serialize, serde::Deserialize)
61
- )]
62
- pub(crate) enum LocalActivityExecutionResult {
63
- Completed(Success),
64
- Failed(ActFail),
65
- TimedOut(ActFail),
66
- Cancelled(Cancellation),
67
- }
68
- impl LocalActivityExecutionResult {
69
- pub(crate) fn empty_cancel() -> Self {
70
- Self::Cancelled(Cancellation::from_details(None))
71
- }
72
- pub(crate) fn timeout(tt: TimeoutType) -> Self {
73
- Self::TimedOut(ActFail::timeout(tt))
74
- }
75
- }
76
-
77
- #[derive(Debug, Clone)]
78
- #[cfg_attr(
79
- feature = "save_wf_inputs",
80
- derive(serde::Serialize, serde::Deserialize)
81
- )]
82
- pub(crate) struct LocalActivityResolution {
83
- pub seq: u32,
84
- pub result: LocalActivityExecutionResult,
85
- pub runtime: Duration,
86
- pub attempt: u32,
87
- pub backoff: Option<prost_types::Duration>,
88
- pub original_schedule_time: Option<SystemTime>,
89
- }
90
-
91
- #[derive(Clone)]
92
- pub(crate) struct NewLocalAct {
93
- pub schedule_cmd: ValidScheduleLA,
94
- pub workflow_type: String,
95
- pub workflow_exec_info: WorkflowExecution,
96
- pub schedule_time: SystemTime,
97
- }
98
- impl Debug for NewLocalAct {
99
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
100
- write!(
101
- f,
102
- "LocalActivity({}, {})",
103
- self.schedule_cmd.seq, self.schedule_cmd.activity_type
104
- )
105
- }
106
- }
107
-
108
- #[derive(Debug, derive_more::From)]
109
- #[allow(clippy::large_enum_variant)]
110
- pub(crate) enum LocalActRequest {
111
- New(NewLocalAct),
112
- Cancel(ExecutingLAId),
113
- #[from(ignore)]
114
- CancelAllInRun(String),
115
- StartHeartbeatTimeout {
116
- send_on_elapse: HeartbeatTimeoutMsg,
117
- deadline: Instant,
118
- abort_reg: AbortRegistration,
119
- },
120
- /// Tell the LA manager that a workflow task was responded to (completed or failed) for a
121
- /// certain run id
122
- #[from(ignore)]
123
- IndicateWorkflowTaskCompleted(String),
124
- }
125
-
126
- #[derive(Debug, Clone, Eq, PartialEq, Hash)]
127
- pub(crate) struct ExecutingLAId {
128
- pub run_id: String,
129
- pub seq_num: u32,
130
- }
131
-
132
- pub(crate) struct LocalActivityManager {
133
- /// Just so we can provide activity tasks the same namespace as the worker
134
- namespace: String,
135
- /// Sink for new activity execution requests
136
- act_req_tx: UnboundedSender<NewOrRetry>,
137
- /// Cancels need a different queue since they should be taken first, and don't take a permit
138
- cancels_req_tx: UnboundedSender<CancelOrTimeout>,
139
- /// For the emission of heartbeat timeouts, back into the workflow machines. This channel
140
- /// needs to come in from above us, because we cannot rely on callers getting the next
141
- /// activation as a way to deliver heartbeats.
142
- heartbeat_timeout_tx: UnboundedSender<HeartbeatTimeoutMsg>,
143
- /// Wakes every time a complete is processed
144
- complete_notify: Notify,
145
- /// Set once workflows have finished shutting down, and thus we know we will no longer receive
146
- /// any requests to spawn new LAs
147
- workflows_have_shut_down: CancellationToken,
148
-
149
- rcvs: tokio::sync::Mutex<RcvChans>,
150
- shutdown_complete_tok: CancellationToken,
151
- dat: Mutex<LAMData>,
152
- }
153
-
154
- struct LocalActivityInfo {
155
- task_token: TaskToken,
156
- /// Tasks for the current backoff until the next retry, if any.
157
- backing_off_task: Option<JoinHandle<()>>,
158
- /// Tasks / info about timeouts associated with this LA. May be empty for very brief periods
159
- /// while the LA id has been generated, but it has not yet been scheduled.
160
- timeout_bag: Option<TimeoutBag>,
161
- /// True once the first workflow task this LA started in has elapsed
162
- first_wft_has_ended: bool,
163
- /// Attempts at executing this LA during the current WFT
164
- attempts_in_wft: usize,
165
- }
166
-
167
- struct LAMData {
168
- /// Maps local activity identifiers to information about them
169
- la_info: HashMap<ExecutingLAId, LocalActivityInfo>,
170
- /// Activities that have been issued to lang but not yet completed
171
- outstanding_activity_tasks: HashMap<TaskToken, LocalInFlightActInfo>,
172
- next_tt_num: u32,
173
- }
174
-
175
- impl LAMData {
176
- fn gen_next_token(&mut self) -> TaskToken {
177
- self.next_tt_num += 1;
178
- TaskToken::new_local_activity_token(self.next_tt_num.to_le_bytes())
179
- }
180
- }
181
-
182
- impl LocalActivityManager {
183
- pub(crate) fn new(
184
- max_concurrent: usize,
185
- namespace: String,
186
- heartbeat_timeout_tx: UnboundedSender<HeartbeatTimeoutMsg>,
187
- metrics_context: MetricsContext,
188
- ) -> Self {
189
- let (act_req_tx, act_req_rx) = unbounded_channel();
190
- let (cancels_req_tx, cancels_req_rx) = unbounded_channel();
191
- let shutdown_complete_tok = CancellationToken::new();
192
- let semaphore = MeteredSemaphore::new(
193
- max_concurrent,
194
- metrics_context,
195
- MetricsContext::available_task_slots,
196
- );
197
- Self {
198
- namespace,
199
- rcvs: tokio::sync::Mutex::new(RcvChans::new(
200
- act_req_rx,
201
- semaphore,
202
- cancels_req_rx,
203
- shutdown_complete_tok.clone(),
204
- )),
205
- act_req_tx,
206
- cancels_req_tx,
207
- heartbeat_timeout_tx,
208
- complete_notify: Notify::new(),
209
- shutdown_complete_tok,
210
- dat: Mutex::new(LAMData {
211
- outstanding_activity_tasks: Default::default(),
212
- la_info: Default::default(),
213
- next_tt_num: 0,
214
- }),
215
- workflows_have_shut_down: Default::default(),
216
- }
217
- }
218
-
219
- #[cfg(test)]
220
- fn test(max_concurrent: usize) -> Self {
221
- let (hb_tx, _hb_rx) = unbounded_channel();
222
- Self::new(
223
- max_concurrent,
224
- "fake_ns".to_string(),
225
- hb_tx,
226
- MetricsContext::no_op(),
227
- )
228
- }
229
-
230
- #[cfg(test)]
231
- pub(crate) fn num_outstanding(&self) -> usize {
232
- self.dat.lock().outstanding_activity_tasks.len()
233
- }
234
-
235
- #[cfg(test)]
236
- fn num_in_backoff(&self) -> usize {
237
- self.dat
238
- .lock()
239
- .la_info
240
- .values()
241
- .filter(|lai| lai.backing_off_task.is_some())
242
- .count()
243
- }
244
-
245
- pub(crate) fn enqueue(
246
- &self,
247
- reqs: impl IntoIterator<Item = LocalActRequest>,
248
- ) -> Vec<LocalActivityResolution> {
249
- if self.workflows_have_shut_down.is_cancelled() {
250
- dbg_panic!("Tried to enqueue local activity after workflows were shut down");
251
- return vec![];
252
- }
253
- let mut immediate_resolutions = vec![];
254
- for req in reqs {
255
- match req {
256
- LocalActRequest::New(act) => {
257
- debug!(local_activity=?act, "Queuing local activity");
258
- let id = ExecutingLAId {
259
- run_id: act.workflow_exec_info.run_id.clone(),
260
- seq_num: act.schedule_cmd.seq,
261
- };
262
- let mut dlock = self.dat.lock();
263
- let tt = dlock.gen_next_token();
264
- match dlock.la_info.entry(id) {
265
- Entry::Occupied(o) => {
266
- // Do not queue local activities which are in fact already executing.
267
- // This can happen during evictions.
268
- debug!(
269
- "Tried to queue already-executing local activity {:?}",
270
- o.key()
271
- );
272
- continue;
273
- }
274
- Entry::Vacant(ve) => {
275
- // Insert the task token now, before we may or may not dispatch the
276
- // activity, so we can enforce idempotency. Prevents two identical LAs
277
- // ending up in the queue at once.
278
- let lai = ve.insert(LocalActivityInfo {
279
- task_token: tt,
280
- backing_off_task: None,
281
- timeout_bag: None,
282
- first_wft_has_ended: false,
283
- attempts_in_wft: 0,
284
- });
285
-
286
- // Set up timeouts for the new activity
287
- match TimeoutBag::new(&act, self.cancels_req_tx.clone()) {
288
- Ok(tb) => {
289
- lai.timeout_bag = Some(tb);
290
-
291
- self.act_req_tx.send(NewOrRetry::New(act)).expect(
292
- "Receive half of LA request channel cannot be dropped",
293
- );
294
- }
295
- Err(res) => immediate_resolutions.push(res),
296
- }
297
- }
298
- }
299
- }
300
- LocalActRequest::StartHeartbeatTimeout {
301
- send_on_elapse,
302
- deadline,
303
- abort_reg,
304
- } => {
305
- let chan = self.heartbeat_timeout_tx.clone();
306
- tokio::spawn(future::Abortable::new(
307
- async move {
308
- tokio::time::sleep_until(deadline.into()).await;
309
- let _ = chan.send(send_on_elapse);
310
- },
311
- abort_reg,
312
- ));
313
- }
314
- LocalActRequest::Cancel(id) => {
315
- debug!(id=?id, "Cancelling local activity");
316
- let mut dlock = self.dat.lock();
317
- if let Some(lai) = dlock.la_info.get_mut(&id) {
318
- if let Some(immediate_res) = self.cancel_one_la(id.seq_num, lai) {
319
- immediate_resolutions.push(immediate_res);
320
- }
321
- }
322
- }
323
- LocalActRequest::CancelAllInRun(run_id) => {
324
- debug!(run_id=%run_id, "Cancelling all local activities for run");
325
- let mut dlock = self.dat.lock();
326
- // Even if we've got 100k+ LAs this should only take a ms or two. Not worth
327
- // adding another map to keep in sync.
328
- let las_for_run = dlock
329
- .la_info
330
- .iter_mut()
331
- .filter(|(id, _)| id.run_id == run_id);
332
- for (laid, lainf) in las_for_run {
333
- if let Some(immediate_res) = self.cancel_one_la(laid.seq_num, lainf) {
334
- immediate_resolutions.push(immediate_res);
335
- }
336
- }
337
- }
338
- LocalActRequest::IndicateWorkflowTaskCompleted(run_id) => {
339
- let mut dlock = self.dat.lock();
340
- let las_for_run = dlock
341
- .la_info
342
- .iter_mut()
343
- .filter(|(id, _)| id.run_id == run_id);
344
- for (_, lainf) in las_for_run {
345
- lainf.first_wft_has_ended = true;
346
- lainf.attempts_in_wft = 0;
347
- }
348
- }
349
- }
350
- }
351
- immediate_resolutions
352
- }
353
-
354
- /// Returns the next pending local-activity related action, or None if shutdown has initiated
355
- /// and there are no more remaining actions to take.
356
- pub(crate) async fn next_pending(&self) -> Option<DispatchOrTimeoutLA> {
357
- let (new_or_retry, permit) = match self.rcvs.lock().await.next().await? {
358
- NewOrCancel::Cancel(c) => {
359
- return match c {
360
- CancelOrTimeout::Cancel(c) => Some(DispatchOrTimeoutLA::Dispatch(c)),
361
- CancelOrTimeout::Timeout {
362
- run_id,
363
- resolution,
364
- dispatch_cancel,
365
- } => {
366
- let task = if dispatch_cancel {
367
- let tt = self
368
- .dat
369
- .lock()
370
- .la_info
371
- .get(&ExecutingLAId {
372
- run_id: run_id.clone(),
373
- seq_num: resolution.seq,
374
- })
375
- .as_ref()
376
- .map(|lai| lai.task_token.clone());
377
- if let Some(task_token) = tt {
378
- self.complete(&task_token, &resolution.result);
379
- Some(ActivityTask {
380
- task_token: task_token.0,
381
- variant: Some(activity_task::Variant::Cancel(Cancel {
382
- reason: ActivityCancelReason::TimedOut as i32,
383
- })),
384
- })
385
- } else {
386
- None
387
- }
388
- } else {
389
- None
390
- };
391
- Some(DispatchOrTimeoutLA::Timeout {
392
- run_id,
393
- resolution,
394
- task,
395
- })
396
- }
397
- };
398
- }
399
- NewOrCancel::New(n, perm) => (n, perm),
400
- };
401
-
402
- // It is important that there are no await points after receiving from the channel, as
403
- // it would mean dropping this future would cause us to drop the activity request.
404
- let (new_la, attempt) = match new_or_retry {
405
- NewOrRetry::New(n) => {
406
- let explicit_attempt_num_or_1 = n.schedule_cmd.attempt.max(1);
407
- (n, explicit_attempt_num_or_1)
408
- }
409
- NewOrRetry::Retry { in_flight, attempt } => (in_flight, attempt),
410
- };
411
- let la_info_for_in_flight_map = new_la.clone();
412
- let id = ExecutingLAId {
413
- run_id: new_la.workflow_exec_info.run_id.clone(),
414
- seq_num: new_la.schedule_cmd.seq,
415
- };
416
- let orig_sched_time = new_la.schedule_cmd.original_schedule_time;
417
- let sa = new_la.schedule_cmd;
418
-
419
- let mut dat = self.dat.lock();
420
- // If this request originated from a local backoff task, clear the entry for it. We
421
- // don't await the handle because we know it must already be done, and there's no
422
- // meaningful value.
423
- dat.la_info
424
- .get_mut(&id)
425
- .map(|lai| lai.backing_off_task.take());
426
-
427
- // If this task sat in the queue for too long, return a timeout for it instead
428
- if let Some(s2s) = sa.schedule_to_start_timeout.as_ref() {
429
- let sat_for = new_la.schedule_time.elapsed().unwrap_or_default();
430
- if sat_for > *s2s {
431
- return Some(DispatchOrTimeoutLA::Timeout {
432
- run_id: new_la.workflow_exec_info.run_id,
433
- resolution: LocalActivityResolution {
434
- seq: sa.seq,
435
- result: LocalActivityExecutionResult::timeout(TimeoutType::ScheduleToStart),
436
- runtime: sat_for,
437
- attempt,
438
- backoff: None,
439
- original_schedule_time: orig_sched_time,
440
- },
441
- task: None,
442
- });
443
- }
444
- }
445
-
446
- let la_info = dat.la_info.get_mut(&id).expect("Activity must exist");
447
- let tt = la_info.task_token.clone();
448
- if let Some(to) = la_info.timeout_bag.as_mut() {
449
- to.mark_started();
450
- }
451
- dat.outstanding_activity_tasks.insert(
452
- tt.clone(),
453
- LocalInFlightActInfo {
454
- la_info: la_info_for_in_flight_map,
455
- dispatch_time: Instant::now(),
456
- attempt,
457
- _permit: permit.into_used(),
458
- },
459
- );
460
-
461
- let (schedule_to_close, start_to_close) = sa.close_timeouts.into_sched_and_start();
462
- Some(DispatchOrTimeoutLA::Dispatch(ActivityTask {
463
- task_token: tt.0,
464
- variant: Some(activity_task::Variant::Start(Start {
465
- workflow_namespace: self.namespace.clone(),
466
- workflow_type: new_la.workflow_type,
467
- workflow_execution: Some(new_la.workflow_exec_info),
468
- activity_id: sa.activity_id,
469
- activity_type: sa.activity_type,
470
- header_fields: sa.headers,
471
- input: sa.arguments,
472
- heartbeat_details: vec![],
473
- scheduled_time: Some(new_la.schedule_time.into()),
474
- current_attempt_scheduled_time: Some(new_la.schedule_time.into()),
475
- started_time: Some(SystemTime::now().into()),
476
- attempt,
477
- schedule_to_close_timeout: schedule_to_close.and_then(|d| d.try_into().ok()),
478
- start_to_close_timeout: start_to_close.and_then(|d| d.try_into().ok()),
479
- heartbeat_timeout: None,
480
- retry_policy: Some(sa.retry_policy),
481
- is_local: true,
482
- })),
483
- }))
484
- }
485
-
486
- /// Mark a local activity as having completed (pass, fail, or cancelled)
487
- pub(crate) fn complete(
488
- &self,
489
- task_token: &TaskToken,
490
- status: &LocalActivityExecutionResult,
491
- ) -> LACompleteAction {
492
- let mut dlock = self.dat.lock();
493
- if let Some(info) = dlock.outstanding_activity_tasks.remove(task_token) {
494
- if self.workflows_have_shut_down.is_cancelled() {
495
- // If workflows are already shut down, the results of all this don't matter.
496
- // Just say we're done if there's nothing outstanding any more.
497
- self.set_shutdown_complete_if_ready(&mut dlock);
498
- }
499
-
500
- let exec_id = ExecutingLAId {
501
- run_id: info.la_info.workflow_exec_info.run_id.clone(),
502
- seq_num: info.la_info.schedule_cmd.seq,
503
- };
504
- let maybe_old_lai = dlock.la_info.remove(&exec_id);
505
- if let Some(ref oldlai) = maybe_old_lai {
506
- if let Some(ref bot) = oldlai.backing_off_task {
507
- dbg_panic!("Just-resolved LA should not have backoff task");
508
- bot.abort();
509
- }
510
- }
511
-
512
- match status {
513
- LocalActivityExecutionResult::Completed(_)
514
- | LocalActivityExecutionResult::TimedOut(_)
515
- | LocalActivityExecutionResult::Cancelled { .. } => {
516
- // Timeouts are included in this branch since they are not retried
517
- self.complete_notify.notify_one();
518
- LACompleteAction::Report(info)
519
- }
520
- LocalActivityExecutionResult::Failed(f) => {
521
- if let Some(backoff_dur) = info.la_info.schedule_cmd.retry_policy.should_retry(
522
- info.attempt as usize,
523
- f.failure
524
- .as_ref()
525
- .and_then(|f| f.maybe_application_failure()),
526
- ) {
527
- let will_use_timer =
528
- backoff_dur > info.la_info.schedule_cmd.local_retry_threshold;
529
- debug!(run_id = %info.la_info.workflow_exec_info.run_id,
530
- seq_num = %info.la_info.schedule_cmd.seq,
531
- attempt = %info.attempt,
532
- will_use_timer,
533
- "Local activity failed, will retry after backing off for {:?}",
534
- backoff_dur
535
- );
536
- if will_use_timer {
537
- // We want this to be reported, as the workflow will mark this
538
- // failure down, then start a timer for backoff.
539
- return LACompleteAction::LangDoesTimerBackoff(
540
- backoff_dur.try_into().expect("backoff fits into proto"),
541
- info,
542
- );
543
- }
544
- // Immediately create a new task token for the to-be-retried LA
545
- let tt = dlock.gen_next_token();
546
- // Send the retry request after waiting the backoff duration
547
- let send_chan = self.act_req_tx.clone();
548
- let jh = tokio::spawn(async move {
549
- tokio::time::sleep(backoff_dur).await;
550
-
551
- send_chan
552
- .send(NewOrRetry::Retry {
553
- in_flight: info.la_info,
554
- attempt: info.attempt + 1,
555
- })
556
- .expect("Receive half of LA request channel cannot be dropped");
557
- });
558
- dlock.la_info.insert(
559
- exec_id,
560
- LocalActivityInfo {
561
- task_token: tt,
562
- backing_off_task: Some(jh),
563
- first_wft_has_ended: maybe_old_lai
564
- .as_ref()
565
- .map(|old| old.first_wft_has_ended)
566
- .unwrap_or_default(),
567
- attempts_in_wft: maybe_old_lai
568
- .as_ref()
569
- .map(|old| old.attempts_in_wft + 1)
570
- .unwrap_or(1),
571
- timeout_bag: maybe_old_lai.and_then(|old| old.timeout_bag),
572
- },
573
- );
574
-
575
- LACompleteAction::WillBeRetried
576
- } else {
577
- LACompleteAction::Report(info)
578
- }
579
- }
580
- }
581
- } else {
582
- LACompleteAction::Untracked
583
- }
584
- }
585
-
586
- pub(crate) fn workflows_have_shutdown(&self) {
587
- self.workflows_have_shut_down.cancel();
588
- self.set_shutdown_complete_if_ready(&mut self.dat.lock());
589
- }
590
-
591
- pub(crate) async fn wait_all_outstanding_tasks_finished(&self) {
592
- while !self.set_shutdown_complete_if_ready(&mut self.dat.lock()) {
593
- self.complete_notify.notified().await;
594
- }
595
- }
596
-
597
- /// Try to close the activity stream as soon as worker shutdown is initiated.
598
- /// This is required for activity-only workers where since workflows are not polled and the activity poller might
599
- /// get "stuck".
600
- pub(crate) fn shutdown_initiated(&self) {
601
- self.set_shutdown_complete_if_ready(&mut self.dat.lock());
602
- }
603
-
604
- pub(crate) fn get_nonfirst_attempt_count(&self, for_run_id: &str) -> usize {
605
- let dlock = self.dat.lock();
606
- dlock
607
- .la_info
608
- .iter()
609
- .filter(|(id, info)| id.run_id == for_run_id && info.first_wft_has_ended)
610
- .map(|(_, info)| info.attempts_in_wft)
611
- .sum()
612
- }
613
-
614
- fn set_shutdown_complete_if_ready(&self, dlock: &mut MutexGuard<LAMData>) -> bool {
615
- let nothing_outstanding = dlock.outstanding_activity_tasks.is_empty();
616
- if nothing_outstanding {
617
- self.shutdown_complete_tok.cancel();
618
- }
619
- nothing_outstanding
620
- }
621
-
622
- fn cancel_one_la(
623
- &self,
624
- seq: u32,
625
- lai: &mut LocalActivityInfo,
626
- ) -> Option<LocalActivityResolution> {
627
- // First check if this ID is currently backing off, if so abort the backoff
628
- // task
629
- if let Some(t) = lai.backing_off_task.take() {
630
- t.abort();
631
- return Some(LocalActivityResolution {
632
- seq,
633
- result: LocalActivityExecutionResult::Cancelled(Cancellation::from_details(None)),
634
- runtime: Duration::from_secs(0),
635
- attempt: 0,
636
- backoff: None,
637
- original_schedule_time: None,
638
- });
639
- }
640
-
641
- self.cancels_req_tx
642
- .send(CancelOrTimeout::Cancel(ActivityTask {
643
- task_token: lai.task_token.0.clone(),
644
- variant: Some(activity_task::Variant::Cancel(Cancel {
645
- reason: ActivityCancelReason::Cancelled as i32,
646
- })),
647
- }))
648
- .expect("Receive half of LA cancel channel cannot be dropped");
649
- None
650
- }
651
- }
652
-
653
- #[derive(Debug)]
654
- #[allow(clippy::large_enum_variant)] // Most will be reported
655
- pub(crate) enum LACompleteAction {
656
- /// Caller should report the status to the workflow
657
- Report(LocalInFlightActInfo),
658
- /// Lang needs to be told to do the schedule-a-timer-then-rerun hack
659
- LangDoesTimerBackoff(prost_types::Duration, LocalInFlightActInfo),
660
- /// The activity will be re-enqueued for another attempt (and so status should not be reported
661
- /// to the workflow)
662
- WillBeRetried,
663
- /// The activity was unknown
664
- Untracked,
665
- }
666
-
667
- #[derive(Debug)]
668
- enum NewOrRetry {
669
- New(NewLocalAct),
670
- Retry {
671
- in_flight: NewLocalAct,
672
- attempt: u32,
673
- },
674
- }
675
-
676
- #[allow(clippy::large_enum_variant)]
677
- #[derive(Debug, Clone)]
678
- enum CancelOrTimeout {
679
- Cancel(ActivityTask),
680
- Timeout {
681
- run_id: String,
682
- resolution: LocalActivityResolution,
683
- dispatch_cancel: bool,
684
- },
685
- }
686
-
687
- #[allow(clippy::large_enum_variant)]
688
- enum NewOrCancel {
689
- New(NewOrRetry, OwnedMeteredSemPermit),
690
- Cancel(CancelOrTimeout),
691
- }
692
-
693
- #[pin_project::pin_project]
694
- struct RcvChans {
695
- #[pin]
696
- inner: BoxStream<'static, NewOrCancel>,
697
- }
698
-
699
- impl RcvChans {
700
- fn new(
701
- new_reqs: UnboundedReceiver<NewOrRetry>,
702
- new_sem: MeteredSemaphore,
703
- cancels: UnboundedReceiver<CancelOrTimeout>,
704
- shutdown_completed: CancellationToken,
705
- ) -> Self {
706
- let cancel_stream = UnboundedReceiverStream::new(cancels).map(NewOrCancel::Cancel);
707
- let new_stream = UnboundedReceiverStream::new(new_reqs)
708
- // Get a permit for each new activity request
709
- .zip(stream::unfold(new_sem, |new_sem| async move {
710
- let permit = new_sem
711
- .acquire_owned()
712
- .await
713
- .expect("Local activity semaphore is never closed");
714
- Some((permit, new_sem))
715
- }))
716
- .map(|(req, permit)| NewOrCancel::New(req, permit));
717
- Self {
718
- inner: tokio_stream::StreamExt::merge(cancel_stream, new_stream)
719
- .take_until(async move { shutdown_completed.cancelled().await })
720
- .boxed(),
721
- }
722
- }
723
- }
724
- impl Stream for RcvChans {
725
- type Item = NewOrCancel;
726
-
727
- fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
728
- let this = self.project();
729
- this.inner.poll_next(cx)
730
- }
731
- }
732
-
733
- struct TimeoutBag {
734
- sched_to_close_handle: JoinHandle<()>,
735
- start_to_close_dur_and_dat: Option<(Duration, CancelOrTimeout)>,
736
- start_to_close_handle: Option<JoinHandle<()>>,
737
- cancel_chan: UnboundedSender<CancelOrTimeout>,
738
- }
739
-
740
- impl TimeoutBag {
741
- /// Create new timeout tasks for the provided local activity. This must be called as soon
742
- /// as request to schedule it arrives.
743
- ///
744
- /// Returns error in the event the activity is *already* timed out
745
- fn new(
746
- new_la: &NewLocalAct,
747
- cancel_chan: UnboundedSender<CancelOrTimeout>,
748
- ) -> Result<TimeoutBag, LocalActivityResolution> {
749
- let (schedule_to_close, start_to_close) =
750
- new_la.schedule_cmd.close_timeouts.into_sched_and_start();
751
-
752
- let sched_time = new_la
753
- .schedule_cmd
754
- .original_schedule_time
755
- .unwrap_or(new_la.schedule_time);
756
- let resolution = LocalActivityResolution {
757
- seq: new_la.schedule_cmd.seq,
758
- result: LocalActivityExecutionResult::timeout(TimeoutType::ScheduleToClose),
759
- runtime: Default::default(),
760
- attempt: new_la.schedule_cmd.attempt,
761
- backoff: None,
762
- original_schedule_time: new_la.schedule_cmd.original_schedule_time,
763
- };
764
- // Remove any time already elapsed since the scheduling time
765
- let schedule_to_close = schedule_to_close
766
- .map(|s2c| s2c.saturating_sub(sched_time.elapsed().unwrap_or_default()));
767
- if let Some(ref s2c) = schedule_to_close {
768
- if s2c.is_zero() {
769
- return Err(resolution);
770
- }
771
- }
772
- let timeout_dat = CancelOrTimeout::Timeout {
773
- run_id: new_la.workflow_exec_info.run_id.clone(),
774
- resolution,
775
- dispatch_cancel: true,
776
- };
777
- let start_to_close_dur_and_dat = start_to_close.map(|d| (d, timeout_dat.clone()));
778
- let fut_dat = schedule_to_close.map(|s2c| (s2c, timeout_dat));
779
-
780
- let cancel_chan_clone = cancel_chan.clone();
781
- let scheduling = tokio::spawn(async move {
782
- if let Some((timeout, dat)) = fut_dat {
783
- sleep(timeout).await;
784
- cancel_chan_clone
785
- .send(dat)
786
- .expect("receive half not dropped");
787
- }
788
- });
789
- Ok(TimeoutBag {
790
- sched_to_close_handle: scheduling,
791
- start_to_close_dur_and_dat,
792
- start_to_close_handle: None,
793
- cancel_chan,
794
- })
795
- }
796
-
797
- /// Must be called once the associated local activity has been started / dispatched to lang.
798
- fn mark_started(&mut self) {
799
- if let Some((start_to_close, mut dat)) = self.start_to_close_dur_and_dat.take() {
800
- let started_t = Instant::now();
801
- let cchan = self.cancel_chan.clone();
802
- self.start_to_close_handle = Some(tokio::spawn(async move {
803
- sleep(start_to_close).await;
804
- if let CancelOrTimeout::Timeout { resolution, .. } = &mut dat {
805
- resolution.result =
806
- LocalActivityExecutionResult::timeout(TimeoutType::StartToClose);
807
- resolution.runtime = started_t.elapsed();
808
- }
809
-
810
- cchan.send(dat).expect("receive half not dropped");
811
- }));
812
- }
813
- }
814
- }
815
-
816
- impl Drop for TimeoutBag {
817
- fn drop(&mut self) {
818
- self.sched_to_close_handle.abort();
819
- if let Some(x) = self.start_to_close_handle.as_ref() {
820
- x.abort()
821
- }
822
- }
823
- }
824
-
825
- #[cfg(test)]
826
- mod tests {
827
- use super::*;
828
- use crate::{prost_dur, protosext::LACloseTimeouts};
829
- use futures_util::FutureExt;
830
- use temporal_sdk_core_protos::temporal::api::{
831
- common::v1::RetryPolicy,
832
- failure::v1::{failure::FailureInfo, ApplicationFailureInfo, Failure},
833
- };
834
- use tokio::task::yield_now;
835
-
836
- impl DispatchOrTimeoutLA {
837
- fn unwrap(self) -> ActivityTask {
838
- match self {
839
- DispatchOrTimeoutLA::Dispatch(t) => t,
840
- _ => {
841
- panic!("Non-dispatched action returned")
842
- }
843
- }
844
- }
845
- }
846
-
847
- #[tokio::test]
848
- async fn max_concurrent_respected() {
849
- let lam = LocalActivityManager::test(1);
850
- lam.enqueue((1..=50).map(|i| {
851
- NewLocalAct {
852
- schedule_cmd: ValidScheduleLA {
853
- seq: i,
854
- activity_id: i.to_string(),
855
- ..Default::default()
856
- },
857
- workflow_type: "".to_string(),
858
- workflow_exec_info: Default::default(),
859
- schedule_time: SystemTime::now(),
860
- }
861
- .into()
862
- }));
863
- for i in 1..=50 {
864
- let next = lam.next_pending().await.unwrap().unwrap();
865
- assert_matches!(
866
- next.variant.unwrap(),
867
- activity_task::Variant::Start(Start {activity_id, ..})
868
- if activity_id == i.to_string()
869
- );
870
- let next_tt = TaskToken(next.task_token);
871
- let complete_branch = async {
872
- lam.complete(
873
- &next_tt,
874
- &LocalActivityExecutionResult::Completed(Default::default()),
875
- )
876
- };
877
- tokio::select! {
878
- // Next call will not resolve until we complete the first
879
- _ = lam.next_pending() => {
880
- panic!("Branch must not be selected")
881
- }
882
- _ = complete_branch => {}
883
- }
884
- }
885
- }
886
-
887
- #[tokio::test]
888
- async fn no_work_doesnt_deadlock_with_complete() {
889
- let lam = LocalActivityManager::test(5);
890
- lam.enqueue([NewLocalAct {
891
- schedule_cmd: ValidScheduleLA {
892
- seq: 1,
893
- activity_id: 1.to_string(),
894
- ..Default::default()
895
- },
896
- workflow_type: "".to_string(),
897
- workflow_exec_info: Default::default(),
898
- schedule_time: SystemTime::now(),
899
- }
900
- .into()]);
901
-
902
- let next = lam.next_pending().await.unwrap().unwrap();
903
- let tt = TaskToken(next.task_token);
904
- tokio::select! {
905
- biased;
906
-
907
- _ = lam.next_pending() => {
908
- panic!("Complete branch must win")
909
- }
910
- _ = async {
911
- // Spin until the receive lock has been grabbed by the call to pending, to ensure
912
- // it's advanced enough
913
- while lam.rcvs.try_lock().is_ok() { yield_now().await; }
914
- lam.complete(&tt, &LocalActivityExecutionResult::Completed(Default::default()));
915
- } => (),
916
- };
917
- }
918
-
919
- #[tokio::test]
920
- async fn can_cancel_in_flight() {
921
- let lam = LocalActivityManager::test(5);
922
- lam.enqueue([NewLocalAct {
923
- schedule_cmd: ValidScheduleLA {
924
- seq: 1,
925
- activity_id: 1.to_string(),
926
- ..Default::default()
927
- },
928
- workflow_type: "".to_string(),
929
- workflow_exec_info: WorkflowExecution {
930
- workflow_id: "".to_string(),
931
- run_id: "run_id".to_string(),
932
- },
933
- schedule_time: SystemTime::now(),
934
- }
935
- .into()]);
936
- lam.next_pending().await.unwrap().unwrap();
937
-
938
- lam.enqueue([LocalActRequest::Cancel(ExecutingLAId {
939
- run_id: "run_id".to_string(),
940
- seq_num: 1,
941
- })]);
942
- let next = lam.next_pending().await.unwrap().unwrap();
943
- assert_matches!(next.variant.unwrap(), activity_task::Variant::Cancel(_));
944
- }
945
-
946
- #[tokio::test]
947
- async fn respects_timer_backoff_threshold() {
948
- let lam = LocalActivityManager::test(1);
949
- lam.enqueue([NewLocalAct {
950
- schedule_cmd: ValidScheduleLA {
951
- seq: 1,
952
- activity_id: 1.to_string(),
953
- attempt: 5,
954
- retry_policy: RetryPolicy {
955
- initial_interval: Some(prost_dur!(from_secs(1))),
956
- backoff_coefficient: 10.0,
957
- maximum_interval: Some(prost_dur!(from_secs(10))),
958
- maximum_attempts: 10,
959
- non_retryable_error_types: vec![],
960
- },
961
- local_retry_threshold: Duration::from_secs(5),
962
- ..Default::default()
963
- },
964
- workflow_type: "".to_string(),
965
- workflow_exec_info: Default::default(),
966
- schedule_time: SystemTime::now(),
967
- }
968
- .into()]);
969
-
970
- let next = lam.next_pending().await.unwrap().unwrap();
971
- let tt = TaskToken(next.task_token);
972
- let res = lam.complete(
973
- &tt,
974
- &LocalActivityExecutionResult::Failed(Default::default()),
975
- );
976
- assert_matches!(res, LACompleteAction::LangDoesTimerBackoff(dur, info)
977
- if dur.seconds == 10 && info.attempt == 5
978
- )
979
- }
980
-
981
- #[tokio::test]
982
- async fn respects_non_retryable_error_types() {
983
- let lam = LocalActivityManager::test(1);
984
- lam.enqueue([NewLocalAct {
985
- schedule_cmd: ValidScheduleLA {
986
- seq: 1,
987
- activity_id: "1".to_string(),
988
- attempt: 1,
989
- retry_policy: RetryPolicy {
990
- initial_interval: Some(prost_dur!(from_secs(1))),
991
- backoff_coefficient: 10.0,
992
- maximum_interval: Some(prost_dur!(from_secs(10))),
993
- maximum_attempts: 10,
994
- non_retryable_error_types: vec!["TestError".to_string()],
995
- },
996
- local_retry_threshold: Duration::from_secs(5),
997
- ..Default::default()
998
- },
999
- workflow_type: "".to_string(),
1000
- workflow_exec_info: Default::default(),
1001
- schedule_time: SystemTime::now(),
1002
- }
1003
- .into()]);
1004
-
1005
- let next = lam.next_pending().await.unwrap().unwrap();
1006
- let tt = TaskToken(next.task_token);
1007
- let res = lam.complete(
1008
- &tt,
1009
- &LocalActivityExecutionResult::Failed(ActFail {
1010
- failure: Some(Failure {
1011
- failure_info: Some(FailureInfo::ApplicationFailureInfo(
1012
- ApplicationFailureInfo {
1013
- r#type: "TestError".to_string(),
1014
- non_retryable: false,
1015
- ..Default::default()
1016
- },
1017
- )),
1018
- ..Default::default()
1019
- }),
1020
- }),
1021
- );
1022
- assert_matches!(res, LACompleteAction::Report(_));
1023
- }
1024
-
1025
- #[tokio::test]
1026
- async fn can_cancel_during_local_backoff() {
1027
- let lam = LocalActivityManager::test(1);
1028
- lam.enqueue([NewLocalAct {
1029
- schedule_cmd: ValidScheduleLA {
1030
- seq: 1,
1031
- activity_id: 1.to_string(),
1032
- attempt: 5,
1033
- retry_policy: RetryPolicy {
1034
- initial_interval: Some(prost_dur!(from_secs(10))),
1035
- backoff_coefficient: 1.0,
1036
- maximum_interval: Some(prost_dur!(from_secs(10))),
1037
- maximum_attempts: 10,
1038
- non_retryable_error_types: vec![],
1039
- },
1040
- local_retry_threshold: Duration::from_secs(500),
1041
- ..Default::default()
1042
- },
1043
- workflow_type: "".to_string(),
1044
- workflow_exec_info: WorkflowExecution {
1045
- workflow_id: "".to_string(),
1046
- run_id: "run_id".to_string(),
1047
- },
1048
- schedule_time: SystemTime::now(),
1049
- }
1050
- .into()]);
1051
-
1052
- let next = lam.next_pending().await.unwrap().unwrap();
1053
- let tt = TaskToken(next.task_token);
1054
- lam.complete(
1055
- &tt,
1056
- &LocalActivityExecutionResult::Failed(Default::default()),
1057
- );
1058
- // Cancel the activity, which is performing local backoff
1059
- let immediate_res = lam.enqueue([LocalActRequest::Cancel(ExecutingLAId {
1060
- run_id: "run_id".to_string(),
1061
- seq_num: 1,
1062
- })]);
1063
- // It should not be present in the backoff tasks
1064
- assert_eq!(lam.num_in_backoff(), 0);
1065
- assert_eq!(lam.num_outstanding(), 0);
1066
- // It should return a resolution to cancel
1067
- assert_eq!(immediate_res.len(), 1);
1068
- assert_matches!(
1069
- immediate_res[0].result,
1070
- LocalActivityExecutionResult::Cancelled { .. }
1071
- );
1072
- }
1073
-
1074
- #[tokio::test]
1075
- async fn local_backoff_clears_handle_map_when_started() {
1076
- let lam = LocalActivityManager::test(1);
1077
- lam.enqueue([NewLocalAct {
1078
- schedule_cmd: ValidScheduleLA {
1079
- seq: 1,
1080
- activity_id: 1.to_string(),
1081
- attempt: 5,
1082
- retry_policy: RetryPolicy {
1083
- initial_interval: Some(prost_dur!(from_millis(10))),
1084
- backoff_coefficient: 1.0,
1085
- ..Default::default()
1086
- },
1087
- local_retry_threshold: Duration::from_secs(500),
1088
- ..Default::default()
1089
- },
1090
- workflow_type: "".to_string(),
1091
- workflow_exec_info: WorkflowExecution {
1092
- workflow_id: "".to_string(),
1093
- run_id: "run_id".to_string(),
1094
- },
1095
- schedule_time: SystemTime::now(),
1096
- }
1097
- .into()]);
1098
-
1099
- let next = lam.next_pending().await.unwrap().unwrap();
1100
- let tt = TaskToken(next.task_token);
1101
- lam.complete(
1102
- &tt,
1103
- &LocalActivityExecutionResult::Failed(Default::default()),
1104
- );
1105
- lam.next_pending().await.unwrap().unwrap();
1106
- assert_eq!(lam.num_in_backoff(), 0);
1107
- assert_eq!(lam.num_outstanding(), 1);
1108
- }
1109
-
1110
- #[tokio::test]
1111
- async fn sched_to_start_timeout() {
1112
- let lam = LocalActivityManager::test(1);
1113
- let timeout = Duration::from_millis(100);
1114
- lam.enqueue([NewLocalAct {
1115
- schedule_cmd: ValidScheduleLA {
1116
- seq: 1,
1117
- activity_id: 1.to_string(),
1118
- attempt: 5,
1119
- retry_policy: RetryPolicy {
1120
- initial_interval: Some(prost_dur!(from_millis(10))),
1121
- backoff_coefficient: 1.0,
1122
- ..Default::default()
1123
- },
1124
- local_retry_threshold: Duration::from_secs(500),
1125
- schedule_to_start_timeout: Some(timeout),
1126
- ..Default::default()
1127
- },
1128
- workflow_type: "".to_string(),
1129
- workflow_exec_info: WorkflowExecution {
1130
- workflow_id: "".to_string(),
1131
- run_id: "run_id".to_string(),
1132
- },
1133
- schedule_time: SystemTime::now(),
1134
- }
1135
- .into()]);
1136
-
1137
- // Wait more than the timeout before grabbing the task
1138
- sleep(timeout + Duration::from_millis(10)).await;
1139
-
1140
- assert_matches!(
1141
- lam.next_pending().await.unwrap(),
1142
- DispatchOrTimeoutLA::Timeout { .. }
1143
- );
1144
- assert_eq!(lam.num_in_backoff(), 0);
1145
- assert_eq!(lam.num_outstanding(), 0);
1146
- }
1147
-
1148
- #[rstest::rstest]
1149
- #[case::schedule(true)]
1150
- #[case::start(false)]
1151
- #[tokio::test]
1152
- async fn local_x_to_close_timeout(#[case] is_schedule: bool) {
1153
- let lam = LocalActivityManager::test(1);
1154
- let timeout = Duration::from_millis(100);
1155
- let close_timeouts = if is_schedule {
1156
- LACloseTimeouts::ScheduleOnly(timeout)
1157
- } else {
1158
- LACloseTimeouts::StartOnly(timeout)
1159
- };
1160
- lam.enqueue([NewLocalAct {
1161
- schedule_cmd: ValidScheduleLA {
1162
- seq: 1,
1163
- activity_id: 1.to_string(),
1164
- attempt: 5,
1165
- retry_policy: RetryPolicy {
1166
- initial_interval: Some(prost_dur!(from_millis(10))),
1167
- backoff_coefficient: 1.0,
1168
- ..Default::default()
1169
- },
1170
- local_retry_threshold: Duration::from_secs(500),
1171
- close_timeouts,
1172
- ..Default::default()
1173
- },
1174
- workflow_type: "".to_string(),
1175
- workflow_exec_info: WorkflowExecution {
1176
- workflow_id: "".to_string(),
1177
- run_id: "run_id".to_string(),
1178
- },
1179
- schedule_time: SystemTime::now(),
1180
- }
1181
- .into()]);
1182
-
1183
- lam.next_pending().await.unwrap().unwrap();
1184
- assert_eq!(lam.num_in_backoff(), 0);
1185
- assert_eq!(lam.num_outstanding(), 1);
1186
-
1187
- sleep(timeout + Duration::from_millis(10)).await;
1188
- assert_matches!(
1189
- lam.next_pending().await.unwrap(),
1190
- DispatchOrTimeoutLA::Timeout { .. }
1191
- );
1192
- assert_eq!(lam.num_outstanding(), 0);
1193
- }
1194
-
1195
- #[tokio::test]
1196
- async fn idempotency_enforced() {
1197
- let lam = LocalActivityManager::test(10);
1198
- let new_la = NewLocalAct {
1199
- schedule_cmd: ValidScheduleLA {
1200
- seq: 1,
1201
- activity_id: 1.to_string(),
1202
- ..Default::default()
1203
- },
1204
- workflow_type: "".to_string(),
1205
- workflow_exec_info: WorkflowExecution {
1206
- workflow_id: "".to_string(),
1207
- run_id: "run_id".to_string(),
1208
- },
1209
- schedule_time: SystemTime::now(),
1210
- };
1211
- // Verify only one will get queued
1212
- lam.enqueue([new_la.clone().into(), new_la.clone().into()]);
1213
- lam.next_pending().await.unwrap().unwrap();
1214
- assert_eq!(lam.num_outstanding(), 1);
1215
- // There should be nothing else in the queue
1216
- assert!(lam.rcvs.lock().await.next().now_or_never().is_none());
1217
-
1218
- // Verify that if we now enqueue the same act again, after the task is outstanding, we still
1219
- // don't add it.
1220
- lam.enqueue([new_la.into()]);
1221
- assert_eq!(lam.num_outstanding(), 1);
1222
- assert!(lam.rcvs.lock().await.next().now_or_never().is_none());
1223
- }
1224
-
1225
- #[tokio::test]
1226
- async fn nonfirst_la_attempt_count_is_accurate() {
1227
- let run_id = "run_id";
1228
- let lam = LocalActivityManager::test(10);
1229
- let new_la = NewLocalAct {
1230
- schedule_cmd: ValidScheduleLA {
1231
- seq: 1,
1232
- activity_id: 1.to_string(),
1233
- retry_policy: RetryPolicy {
1234
- initial_interval: Some(prost_dur!(from_millis(1))),
1235
- backoff_coefficient: 1.0,
1236
- ..Default::default()
1237
- },
1238
- local_retry_threshold: Duration::from_secs(500),
1239
- ..Default::default()
1240
- },
1241
- workflow_type: "".to_string(),
1242
- workflow_exec_info: WorkflowExecution {
1243
- workflow_id: "".to_string(),
1244
- run_id: run_id.to_string(),
1245
- },
1246
- schedule_time: SystemTime::now(),
1247
- };
1248
- lam.enqueue([new_la.clone().into()]);
1249
- let spinfail = || async {
1250
- for _ in 1..=10 {
1251
- let next = lam.next_pending().await.unwrap().unwrap();
1252
- let tt = TaskToken(next.task_token);
1253
- lam.complete(
1254
- &tt,
1255
- &LocalActivityExecutionResult::Failed(Default::default()),
1256
- );
1257
- }
1258
- };
1259
-
1260
- // Fail a bunch of times
1261
- spinfail().await;
1262
- // Nonfirst attempt count should still be zero
1263
- let count = lam.get_nonfirst_attempt_count(run_id);
1264
- assert_eq!(count, 0);
1265
-
1266
- for _ in 1..=2 {
1267
- // This should work over multiple WFTs
1268
- // say the first wft was completed
1269
- lam.enqueue([LocalActRequest::IndicateWorkflowTaskCompleted(
1270
- run_id.to_string(),
1271
- )]);
1272
- // Do some more attempts
1273
- spinfail().await;
1274
- let count = lam.get_nonfirst_attempt_count(run_id);
1275
- assert_eq!(count, 10);
1276
- }
1277
- }
1278
- }