@temporalio/core-bridge 1.13.1 → 1.14.0

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 (422) hide show
  1. package/Cargo.lock +350 -436
  2. package/Cargo.toml +14 -13
  3. package/{sdk-core/fsm/rustfsm_procmacro/LICENSE.txt → LICENSE} +5 -5
  4. package/README.md +0 -1
  5. package/bridge-macros/Cargo.toml +16 -0
  6. package/bridge-macros/src/derive_js_function.rs +126 -0
  7. package/bridge-macros/src/derive_tryfromjs.rs +138 -0
  8. package/bridge-macros/src/derive_tryintojs.rs +151 -0
  9. package/bridge-macros/src/lib.rs +42 -0
  10. package/lib/native.d.ts +23 -9
  11. package/package.json +6 -5
  12. package/releases/aarch64-apple-darwin/index.node +0 -0
  13. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  14. package/releases/x86_64-apple-darwin/index.node +0 -0
  15. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  16. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  17. package/sdk-core/.cargo/config.toml +78 -12
  18. package/sdk-core/.clippy.toml +1 -0
  19. package/sdk-core/.github/workflows/heavy.yml +2 -0
  20. package/sdk-core/.github/workflows/per-pr.yml +90 -21
  21. package/sdk-core/AGENTS.md +17 -19
  22. package/sdk-core/ARCHITECTURE.md +44 -48
  23. package/sdk-core/Cargo.toml +25 -7
  24. package/sdk-core/README.md +16 -15
  25. package/sdk-core/arch_docs/diagrams/TimerMachine_Coverage.puml +14 -0
  26. package/sdk-core/arch_docs/diagrams/deps.svg +102 -0
  27. package/sdk-core/arch_docs/diagrams/initial_event_history.png +0 -0
  28. package/sdk-core/arch_docs/sdks_intro.md +299 -0
  29. package/sdk-core/{client → crates/client}/Cargo.toml +15 -16
  30. package/sdk-core/{client → crates/client}/src/callback_based.rs +1 -2
  31. package/sdk-core/{client → crates/client}/src/lib.rs +594 -457
  32. package/sdk-core/{client → crates/client}/src/metrics.rs +32 -8
  33. package/sdk-core/crates/client/src/proxy.rs +209 -0
  34. package/sdk-core/{client → crates/client}/src/raw.rs +648 -328
  35. package/sdk-core/crates/client/src/replaceable.rs +253 -0
  36. package/sdk-core/crates/client/src/request_extensions.rs +40 -0
  37. package/sdk-core/{client → crates/client}/src/retry.rs +32 -22
  38. package/sdk-core/crates/client/src/worker/mod.rs +1468 -0
  39. package/sdk-core/{client → crates/client}/src/workflow_handle/mod.rs +24 -21
  40. package/sdk-core/{core-api → crates/common}/Cargo.toml +21 -12
  41. package/sdk-core/{sdk-core-protos → crates/common}/build.rs +10 -23
  42. package/sdk-core/crates/common/protos/api_cloud_upstream/VERSION +1 -0
  43. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/account/v1/message.proto +18 -0
  44. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +38 -11
  45. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +21 -4
  46. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +6 -6
  47. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/sink/v1/message.proto +22 -0
  48. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/create-release.yml +13 -0
  49. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/openapi/openapiv2.json +254 -5
  50. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/openapi/openapiv3.yaml +234 -5
  51. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/common/v1/message.proto +1 -1
  52. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/deployment/v1/message.proto +6 -0
  53. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -2
  54. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -2
  55. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -6
  56. package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  57. package/sdk-core/{core-api → crates/common}/src/envconfig.rs +155 -56
  58. package/sdk-core/{core-api → crates/common}/src/errors.rs +8 -1
  59. package/sdk-core/{fsm/rustfsm_trait/src/lib.rs → crates/common/src/fsm_trait.rs} +1 -27
  60. package/sdk-core/{core-api → crates/common}/src/lib.rs +92 -9
  61. package/sdk-core/{test-utils/src → crates/common/src/protos}/canned_histories.rs +5 -5
  62. package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/history_builder.rs +3 -3
  63. package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/history_info.rs +2 -2
  64. package/sdk-core/{sdk-core-protos/src/lib.rs → crates/common/src/protos/mod.rs} +43 -26
  65. package/sdk-core/crates/common/src/protos/test_utils.rs +89 -0
  66. package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/utilities.rs +14 -5
  67. package/sdk-core/{core-api → crates/common}/src/telemetry/metrics.rs +449 -51
  68. package/sdk-core/{core-api → crates/common}/src/telemetry.rs +16 -1
  69. package/sdk-core/{core-api → crates/common}/src/worker.rs +112 -18
  70. package/sdk-core/crates/common/tests/worker_task_types_test.rs +129 -0
  71. package/sdk-core/crates/macros/Cargo.toml +23 -0
  72. package/sdk-core/{fsm/rustfsm_procmacro → crates/macros}/src/lib.rs +12 -12
  73. package/sdk-core/{sdk → crates/sdk}/Cargo.toml +18 -12
  74. package/sdk-core/{sdk → crates/sdk}/src/activity_context.rs +9 -7
  75. package/sdk-core/{sdk → crates/sdk}/src/app_data.rs +1 -1
  76. package/sdk-core/{sdk → crates/sdk}/src/interceptors.rs +2 -5
  77. package/sdk-core/{sdk → crates/sdk}/src/lib.rs +43 -42
  78. package/sdk-core/{sdk → crates/sdk}/src/workflow_context/options.rs +12 -3
  79. package/sdk-core/{sdk → crates/sdk}/src/workflow_context.rs +21 -19
  80. package/sdk-core/{sdk → crates/sdk}/src/workflow_future.rs +2 -2
  81. package/sdk-core/crates/sdk-core/Cargo.toml +222 -0
  82. package/sdk-core/{core/benches/workflow_replay.rs → crates/sdk-core/benches/workflow_replay_bench.rs} +15 -10
  83. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +32 -0
  84. package/sdk-core/crates/sdk-core/machine_coverage/CancelExternalMachine_Coverage.puml +9 -0
  85. package/sdk-core/crates/sdk-core/machine_coverage/CancelWorkflowMachine_Coverage.puml +6 -0
  86. package/sdk-core/crates/sdk-core/machine_coverage/ChildWorkflowMachine_Coverage.puml +27 -0
  87. package/sdk-core/crates/sdk-core/machine_coverage/CompleteWorkflowMachine_Coverage.puml +6 -0
  88. package/sdk-core/crates/sdk-core/machine_coverage/ContinueAsNewWorkflowMachine_Coverage.puml +6 -0
  89. package/sdk-core/crates/sdk-core/machine_coverage/FailWorkflowMachine_Coverage.puml +6 -0
  90. package/sdk-core/crates/sdk-core/machine_coverage/LocalActivityMachine_Coverage.puml +23 -0
  91. package/sdk-core/crates/sdk-core/machine_coverage/ModifyWorkflowPropertiesMachine_Coverage.puml +5 -0
  92. package/sdk-core/crates/sdk-core/machine_coverage/PatchMachine_Coverage.puml +8 -0
  93. package/sdk-core/crates/sdk-core/machine_coverage/SignalExternalMachine_Coverage.puml +12 -0
  94. package/sdk-core/crates/sdk-core/machine_coverage/TimerMachine_Coverage.puml +13 -0
  95. package/sdk-core/crates/sdk-core/machine_coverage/UpdateMachine_Coverage.puml +19 -0
  96. package/sdk-core/crates/sdk-core/machine_coverage/UpsertSearchAttributesMachine_Coverage.puml +5 -0
  97. package/sdk-core/crates/sdk-core/machine_coverage/WorkflowTaskMachine_Coverage.puml +11 -0
  98. package/sdk-core/{core → crates/sdk-core}/src/abstractions.rs +62 -6
  99. package/sdk-core/crates/sdk-core/src/antithesis.rs +60 -0
  100. package/sdk-core/{core → crates/sdk-core}/src/core_tests/activity_tasks.rs +85 -250
  101. package/sdk-core/{core → crates/sdk-core}/src/core_tests/mod.rs +13 -16
  102. package/sdk-core/{core → crates/sdk-core}/src/core_tests/queries.rs +25 -24
  103. package/sdk-core/{core → crates/sdk-core}/src/core_tests/replay_flag.rs +11 -68
  104. package/sdk-core/{core → crates/sdk-core}/src/core_tests/updates.rs +21 -20
  105. package/sdk-core/{core → crates/sdk-core}/src/core_tests/workers.rs +242 -16
  106. package/sdk-core/{core → crates/sdk-core}/src/core_tests/workflow_cancels.rs +10 -7
  107. package/sdk-core/{core → crates/sdk-core}/src/core_tests/workflow_tasks.rs +150 -326
  108. package/sdk-core/{core → crates/sdk-core}/src/debug_client.rs +1 -1
  109. package/sdk-core/{core → crates/sdk-core}/src/ephemeral_server/mod.rs +18 -6
  110. package/sdk-core/{test-utils → crates/sdk-core}/src/histfetch.rs +9 -4
  111. package/sdk-core/{core → crates/sdk-core}/src/internal_flags.rs +15 -4
  112. package/sdk-core/{core → crates/sdk-core}/src/lib.rs +128 -72
  113. package/sdk-core/{core → crates/sdk-core}/src/pollers/mod.rs +13 -11
  114. package/sdk-core/{core → crates/sdk-core}/src/pollers/poll_buffer.rs +53 -18
  115. package/sdk-core/{core → crates/sdk-core}/src/protosext/mod.rs +14 -6
  116. package/sdk-core/{core → crates/sdk-core}/src/protosext/protocol_messages.rs +5 -12
  117. package/sdk-core/{core → crates/sdk-core}/src/replay/mod.rs +14 -11
  118. package/sdk-core/crates/sdk-core/src/retry_logic.rs +390 -0
  119. package/sdk-core/{core → crates/sdk-core}/src/telemetry/log_export.rs +2 -2
  120. package/sdk-core/{core → crates/sdk-core}/src/telemetry/metrics.rs +80 -33
  121. package/sdk-core/{core → crates/sdk-core}/src/telemetry/mod.rs +12 -6
  122. package/sdk-core/{core → crates/sdk-core}/src/telemetry/otel.rs +1 -1
  123. package/sdk-core/{core → crates/sdk-core}/src/telemetry/prometheus_meter.rs +14 -14
  124. package/sdk-core/{core → crates/sdk-core}/src/telemetry/prometheus_server.rs +2 -2
  125. package/sdk-core/{core/src/test_help/mod.rs → crates/sdk-core/src/test_help/integ_helpers.rs} +284 -329
  126. package/sdk-core/crates/sdk-core/src/test_help/mod.rs +13 -0
  127. package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +220 -0
  128. package/sdk-core/{core → crates/sdk-core}/src/worker/activities/activity_heartbeat_manager.rs +44 -8
  129. package/sdk-core/{core → crates/sdk-core}/src/worker/activities/local_activities.rs +33 -31
  130. package/sdk-core/{core → crates/sdk-core}/src/worker/activities.rs +31 -15
  131. package/sdk-core/{core → crates/sdk-core}/src/worker/client/mocks.rs +28 -15
  132. package/sdk-core/{core → crates/sdk-core}/src/worker/client.rs +275 -145
  133. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +246 -0
  134. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1462 -0
  135. package/sdk-core/{core → crates/sdk-core}/src/worker/nexus.rs +24 -12
  136. package/sdk-core/{core → crates/sdk-core}/src/worker/slot_provider.rs +18 -10
  137. package/sdk-core/{core → crates/sdk-core}/src/worker/tuner/fixed_size.rs +5 -1
  138. package/sdk-core/{core → crates/sdk-core}/src/worker/tuner/resource_based.rs +453 -57
  139. package/sdk-core/{core → crates/sdk-core}/src/worker/tuner.rs +179 -3
  140. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/driven_workflow.rs +1 -1
  141. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/history_update.rs +5 -267
  142. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/activity_state_machine.rs +147 -90
  143. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/cancel_external_state_machine.rs +8 -91
  144. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/cancel_nexus_op_state_machine.rs +14 -12
  145. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +97 -0
  146. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/child_workflow_state_machine.rs +32 -229
  147. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/complete_workflow_state_machine.rs +13 -8
  148. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +6 -50
  149. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/fail_workflow_state_machine.rs +6 -7
  150. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/local_activity_state_machine.rs +39 -584
  151. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/mod.rs +22 -17
  152. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +4 -74
  153. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/nexus_operation_state_machine.rs +118 -21
  154. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/patch_state_machine.rs +273 -0
  155. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/signal_external_state_machine.rs +9 -151
  156. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/timer_state_machine.rs +27 -132
  157. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/transition_coverage.rs +1 -2
  158. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/update_state_machine.rs +19 -13
  159. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +25 -80
  160. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/workflow_machines/local_acts.rs +1 -1
  161. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/workflow_machines.rs +68 -72
  162. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/workflow_task_state_machine.rs +13 -15
  163. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/managed_run.rs +55 -37
  164. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/mod.rs +171 -61
  165. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/run_cache.rs +10 -7
  166. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/wft_extraction.rs +4 -2
  167. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/wft_poller.rs +15 -4
  168. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/workflow_stream.rs +38 -19
  169. package/sdk-core/crates/sdk-core/tests/c_bridge_smoke_test.c +10 -0
  170. package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +25 -0
  171. package/sdk-core/crates/sdk-core/tests/common/fake_grpc_server.rs +106 -0
  172. package/sdk-core/crates/sdk-core/tests/common/http_proxy.rs +134 -0
  173. package/sdk-core/{test-utils/src/lib.rs → crates/sdk-core/tests/common/mod.rs} +286 -334
  174. package/sdk-core/{test-utils/src → crates/sdk-core/tests/common}/workflows.rs +6 -4
  175. package/sdk-core/crates/sdk-core/tests/fsm_procmacro.rs +6 -0
  176. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/dupe_transitions_fail.rs +1 -3
  177. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/dupe_transitions_fail.stderr +12 -0
  178. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/dynamic_dest_pass.rs +2 -4
  179. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/forgot_name_fail.rs +1 -3
  180. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/forgot_name_fail.stderr +4 -4
  181. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/handler_arg_pass.rs +2 -4
  182. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/handler_pass.rs +2 -4
  183. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/medium_complex_pass.rs +2 -4
  184. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/no_handle_conversions_require_into_fail.rs +2 -4
  185. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/no_handle_conversions_require_into_fail.stderr +15 -0
  186. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/simple_pass.rs +2 -4
  187. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/struct_event_variant_fail.rs +1 -3
  188. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/struct_event_variant_fail.stderr +5 -0
  189. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/tuple_more_item_event_variant_fail.rs +1 -3
  190. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/tuple_more_item_event_variant_fail.stderr +5 -0
  191. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/tuple_zero_item_event_variant_fail.rs +1 -3
  192. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/tuple_zero_item_event_variant_fail.stderr +5 -0
  193. package/sdk-core/{tests → crates/sdk-core/tests}/global_metric_tests.rs +22 -22
  194. package/sdk-core/{tests → crates/sdk-core/tests/heavy_tests}/fuzzy_workflow.rs +4 -4
  195. package/sdk-core/{tests → crates/sdk-core/tests}/heavy_tests.rs +25 -14
  196. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/activity_functions.rs +1 -1
  197. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/client_tests.rs +115 -123
  198. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/ephemeral_server_tests.rs +19 -15
  199. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/heartbeat_tests.rs +24 -20
  200. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/metrics_tests.rs +241 -67
  201. package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +273 -0
  202. package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +513 -0
  203. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/queries_tests.rs +13 -11
  204. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/update_tests.rs +47 -29
  205. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/visibility_tests.rs +49 -27
  206. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +1061 -0
  207. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +920 -0
  208. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/worker_versioning_tests.rs +58 -40
  209. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/activities.rs +268 -30
  210. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/appdata_propagation.rs +4 -4
  211. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +155 -0
  212. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +121 -0
  213. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +717 -0
  214. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +109 -0
  215. package/sdk-core/{core/src/core_tests → crates/sdk-core/tests/integ_tests/workflow_tests}/determinism.rs +108 -20
  216. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/eager.rs +10 -5
  217. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +2884 -0
  218. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +119 -0
  219. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/nexus.rs +174 -46
  220. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +740 -0
  221. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/replay.rs +78 -27
  222. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/resets.rs +46 -28
  223. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +294 -0
  224. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/stickyness.rs +9 -8
  225. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +249 -0
  226. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/upsert_search_attrs.rs +72 -7
  227. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests.rs +97 -33
  228. package/sdk-core/{tests → crates/sdk-core/tests}/main.rs +40 -25
  229. package/sdk-core/{tests → crates/sdk-core/tests}/manual_tests.rs +25 -15
  230. package/sdk-core/{tests → crates/sdk-core/tests}/runner.rs +23 -41
  231. package/sdk-core/{tests → crates/sdk-core/tests}/shared_tests/mod.rs +11 -6
  232. package/sdk-core/{tests → crates/sdk-core/tests}/shared_tests/priority.rs +6 -6
  233. package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +59 -0
  234. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/include/temporal-sdk-core-c-bridge.h +215 -44
  235. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/client.rs +515 -214
  236. package/sdk-core/crates/sdk-core-c-bridge/src/envconfig.rs +314 -0
  237. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/lib.rs +2 -1
  238. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/metric.rs +1 -1
  239. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/random.rs +4 -4
  240. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/runtime.rs +42 -28
  241. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/testing.rs +2 -5
  242. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/tests/context.rs +42 -41
  243. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/tests/mod.rs +38 -34
  244. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/tests/utils.rs +10 -11
  245. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/worker.rs +427 -121
  246. package/sdk-core/docker-cgroup-tests.sh +24 -0
  247. package/sdk-core/{docker → etc/docker}/docker-compose-ci.yaml +9 -9
  248. package/sdk-core/{docker → etc/docker}/docker-compose-telem.yaml +11 -11
  249. package/sdk-core/{docker → etc/docker}/docker-compose.yaml +8 -8
  250. package/sdk-core/{integ-with-otel.sh → etc/integ-with-otel.sh} +1 -1
  251. package/sdk-core/etc/regen-depgraph.sh +2 -2
  252. package/src/client.rs +117 -49
  253. package/src/helpers/callbacks.rs +4 -4
  254. package/src/helpers/errors.rs +7 -1
  255. package/src/helpers/handles.rs +1 -0
  256. package/src/helpers/try_from_js.rs +5 -4
  257. package/src/lib.rs +3 -2
  258. package/src/logs.rs +1 -1
  259. package/src/metrics.rs +6 -3
  260. package/src/runtime.rs +41 -24
  261. package/src/testing.rs +3 -3
  262. package/src/worker.rs +77 -44
  263. package/ts/native.ts +26 -9
  264. package/LICENSE.md +0 -23
  265. package/sdk-core/arch_docs/diagrams/workflow_internals.svg +0 -1
  266. package/sdk-core/client/src/proxy.rs +0 -90
  267. package/sdk-core/client/src/worker_registry/mod.rs +0 -266
  268. package/sdk-core/core/Cargo.toml +0 -146
  269. package/sdk-core/core/src/core_tests/child_workflows.rs +0 -281
  270. package/sdk-core/core/src/core_tests/local_activities.rs +0 -1442
  271. package/sdk-core/core/src/retry_logic.rs +0 -224
  272. package/sdk-core/core/src/worker/heartbeat.rs +0 -231
  273. package/sdk-core/core/src/worker/mod.rs +0 -980
  274. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +0 -165
  275. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +0 -801
  276. package/sdk-core/core-c-bridge/Cargo.toml +0 -51
  277. package/sdk-core/etc/deps.svg +0 -162
  278. package/sdk-core/fsm/Cargo.toml +0 -21
  279. package/sdk-core/fsm/README.md +0 -3
  280. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +0 -27
  281. package/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +0 -8
  282. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +0 -12
  283. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +0 -15
  284. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +0 -5
  285. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +0 -5
  286. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +0 -5
  287. package/sdk-core/fsm/rustfsm_trait/Cargo.toml +0 -14
  288. package/sdk-core/fsm/rustfsm_trait/LICENSE.txt +0 -21
  289. package/sdk-core/fsm/src/lib.rs +0 -2
  290. package/sdk-core/sdk-core-protos/Cargo.toml +0 -37
  291. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +0 -1
  292. package/sdk-core/test-utils/Cargo.toml +0 -38
  293. package/sdk-core/test-utils/src/interceptors.rs +0 -46
  294. package/sdk-core/tests/cloud_tests.rs +0 -23
  295. package/sdk-core/tests/integ_tests/polling_tests.rs +0 -294
  296. package/sdk-core/tests/integ_tests/worker_tests.rs +0 -203
  297. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +0 -74
  298. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +0 -57
  299. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +0 -246
  300. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +0 -65
  301. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +0 -85
  302. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +0 -908
  303. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +0 -51
  304. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +0 -206
  305. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +0 -164
  306. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +0 -123
  307. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/.github/workflows/build.yaml +0 -0
  308. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/.github/workflows/push-to-buf.yml +0 -0
  309. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/CODEOWNERS +0 -0
  310. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/LICENSE +0 -0
  311. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/Makefile +0 -0
  312. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/README.md +0 -0
  313. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/buf.gen.yaml +0 -0
  314. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/buf.lock +0 -0
  315. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/buf.yaml +0 -0
  316. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/connectivityrule/v1/message.proto +0 -0
  317. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +0 -0
  318. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +0 -0
  319. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/nexus/v1/message.proto +0 -0
  320. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +0 -0
  321. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/resource/v1/message.proto +0 -0
  322. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/usage/v1/message.proto +0 -0
  323. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/CODEOWNERS +0 -0
  324. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  325. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/ci.yml +0 -0
  326. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/publish-docs.yml +0 -0
  327. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/push-to-buf.yml +0 -0
  328. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/trigger-api-go-delete-release.yml +0 -0
  329. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/trigger-api-go-publish-release.yml +0 -0
  330. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +0 -0
  331. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/LICENSE +0 -0
  332. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/Makefile +0 -0
  333. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/README.md +0 -0
  334. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/api-linter.yaml +0 -0
  335. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/buf.gen.yaml +0 -0
  336. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/buf.lock +0 -0
  337. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/buf.yaml +0 -0
  338. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/api/annotations.proto +0 -0
  339. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/api/http.proto +0 -0
  340. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/any.proto +0 -0
  341. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/descriptor.proto +0 -0
  342. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/duration.proto +0 -0
  343. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/empty.proto +0 -0
  344. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/struct.proto +0 -0
  345. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/timestamp.proto +0 -0
  346. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/wrappers.proto +0 -0
  347. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/openapi/payload_description.txt +0 -0
  348. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/activity/v1/message.proto +0 -0
  349. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/batch/v1/message.proto +0 -0
  350. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/command/v1/message.proto +0 -0
  351. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -0
  352. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/command_type.proto +0 -0
  353. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/common.proto +0 -0
  354. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/deployment.proto +0 -0
  355. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/event_type.proto +0 -0
  356. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +0 -0
  357. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/namespace.proto +0 -0
  358. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/nexus.proto +0 -0
  359. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/query.proto +0 -0
  360. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/reset.proto +0 -0
  361. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/schedule.proto +0 -0
  362. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -0
  363. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/update.proto +0 -0
  364. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/workflow.proto +0 -0
  365. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/errordetails/v1/message.proto +0 -0
  366. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/export/v1/message.proto +0 -0
  367. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/failure/v1/message.proto +0 -0
  368. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/filter/v1/message.proto +0 -0
  369. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/history/v1/message.proto +0 -0
  370. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/nexus/v1/message.proto +0 -0
  371. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +0 -0
  372. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -0
  373. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/protocol/v1/message.proto +0 -0
  374. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/query/v1/message.proto +0 -0
  375. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/replication/v1/message.proto +0 -0
  376. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/rules/v1/message.proto +0 -0
  377. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/schedule/v1/message.proto +0 -0
  378. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/enhanced_stack_trace.proto +0 -0
  379. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +0 -0
  380. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/user_metadata.proto +0 -0
  381. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/worker_config.proto +0 -0
  382. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +0 -0
  383. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +0 -0
  384. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/update/v1/message.proto +0 -0
  385. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/version/v1/message.proto +0 -0
  386. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/worker/v1/message.proto +0 -0
  387. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/workflow/v1/message.proto +0 -0
  388. /package/sdk-core/{sdk-core-protos → crates/common}/protos/google/rpc/status.proto +0 -0
  389. /package/sdk-core/{sdk-core-protos → crates/common}/protos/grpc/health/v1/health.proto +0 -0
  390. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/activity_result/activity_result.proto +0 -0
  391. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/activity_task/activity_task.proto +0 -0
  392. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -0
  393. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/common/common.proto +0 -0
  394. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/core_interface.proto +0 -0
  395. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/external_data/external_data.proto +0 -0
  396. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/nexus/nexus.proto +0 -0
  397. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +0 -0
  398. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -0
  399. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/Makefile +0 -0
  400. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/api-linter.yaml +0 -0
  401. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/buf.yaml +0 -0
  402. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -0
  403. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -0
  404. /package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/constants.rs +0 -0
  405. /package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/task_token.rs +0 -0
  406. /package/sdk-core/{fsm → crates/macros}/LICENSE.txt +0 -0
  407. /package/sdk-core/{core → crates/sdk-core}/src/abstractions/take_cell.rs +0 -0
  408. /package/sdk-core/{core → crates/sdk-core}/src/worker/slot_supplier.rs +0 -0
  409. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/ends_empty_wft_complete.bin +0 -0
  410. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/evict_while_la_running_no_interference-16_history.bin +0 -0
  411. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/evict_while_la_running_no_interference-23_history.bin +0 -0
  412. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/evict_while_la_running_no_interference-85_history.bin +0 -0
  413. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/fail_wf_task.bin +0 -0
  414. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-0_history.bin +0 -0
  415. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-1_history.bin +0 -0
  416. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-2_history.bin +0 -0
  417. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-3_history.bin +0 -0
  418. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/old_change_marker_format.bin +0 -0
  419. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/timer_workflow_history.bin +0 -0
  420. /package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/priority.rs +0 -0
  421. /package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/build.rs +0 -0
  422. /package/sdk-core/{cargo-tokio-console.sh → etc/cargo-tokio-console.sh} +0 -0
@@ -0,0 +1,920 @@
1
+ use crate::{
2
+ common::{
3
+ CoreWfStarter, fake_grpc_server::fake_server, get_integ_runtime_options,
4
+ get_integ_server_options, get_integ_telem_options, mock_sdk_cfg,
5
+ },
6
+ shared_tests,
7
+ };
8
+ use assert_matches::assert_matches;
9
+ use futures_util::FutureExt;
10
+ use std::{
11
+ cell::Cell,
12
+ sync::{
13
+ Arc, Mutex,
14
+ atomic::{
15
+ AtomicBool, AtomicU8,
16
+ Ordering::{self, Relaxed},
17
+ },
18
+ },
19
+ time::Duration,
20
+ };
21
+ use temporalio_client::WorkflowOptions;
22
+ use temporalio_common::{
23
+ Worker,
24
+ errors::WorkerValidationError,
25
+ protos::{
26
+ DEFAULT_WORKFLOW_TYPE, TestHistoryBuilder, canned_histories,
27
+ coresdk::{
28
+ ActivityTaskCompletion,
29
+ activity_result::ActivityExecutionResult,
30
+ workflow_completion::{
31
+ Failure, WorkflowActivationCompletion, workflow_activation_completion::Status,
32
+ },
33
+ },
34
+ temporal::api::{
35
+ command::v1::command::Attributes,
36
+ common::v1::WorkerVersionStamp,
37
+ enums::v1::{
38
+ EventType, WorkflowTaskFailedCause, WorkflowTaskFailedCause::GrpcMessageTooLarge,
39
+ },
40
+ failure::v1::Failure as InnerFailure,
41
+ history::v1::{
42
+ ActivityTaskScheduledEventAttributes, history_event,
43
+ history_event::Attributes::{
44
+ self as EventAttributes, WorkflowTaskFailedEventAttributes,
45
+ },
46
+ },
47
+ workflowservice::v1::{
48
+ GetWorkflowExecutionHistoryResponse, PollActivityTaskQueueResponse,
49
+ RespondActivityTaskCompletedResponse,
50
+ },
51
+ },
52
+ },
53
+ worker::{
54
+ ActivitySlotKind, LocalActivitySlotKind, PollerBehavior, SlotInfo, SlotInfoTrait,
55
+ SlotMarkUsedContext, SlotReleaseContext, SlotReservationContext, SlotSupplier,
56
+ SlotSupplierPermit, WorkerConfigBuilder, WorkerTaskTypes, WorkerVersioningStrategy,
57
+ WorkflowSlotKind,
58
+ },
59
+ };
60
+ use temporalio_sdk::{
61
+ ActivityOptions, LocalActivityOptions, WfContext, interceptors::WorkerInterceptor,
62
+ };
63
+ use temporalio_sdk_core::{
64
+ CoreRuntime, ResourceBasedTuner, ResourceSlotOptions, TunerBuilder, init_worker,
65
+ test_help::{
66
+ FakeWfResponses, MockPollCfg, ResponseType, build_mock_pollers, drain_pollers_and_shutdown,
67
+ hist_to_poll_resp, mock_worker, mock_worker_client,
68
+ },
69
+ };
70
+ use tokio::sync::{Barrier, Notify, Semaphore};
71
+ use tokio_util::sync::CancellationToken;
72
+ use uuid::Uuid;
73
+
74
+ #[tokio::test]
75
+ async fn worker_validation_fails_on_nonexistent_namespace() {
76
+ let opts = get_integ_server_options();
77
+ let runtime =
78
+ CoreRuntime::new_assume_tokio(get_integ_runtime_options(get_integ_telem_options()))
79
+ .unwrap();
80
+ let retrying_client = opts
81
+ .connect_no_namespace(runtime.telemetry().get_temporal_metric_meter())
82
+ .await
83
+ .unwrap();
84
+
85
+ let worker = init_worker(
86
+ &runtime,
87
+ WorkerConfigBuilder::default()
88
+ .namespace("i_dont_exist")
89
+ .task_queue("Wheee!")
90
+ .versioning_strategy(WorkerVersioningStrategy::None {
91
+ build_id: "blah".to_owned(),
92
+ })
93
+ .task_types(WorkerTaskTypes::all())
94
+ .build()
95
+ .unwrap(),
96
+ retrying_client,
97
+ )
98
+ .unwrap();
99
+
100
+ let res = worker.validate().await;
101
+ assert_matches!(
102
+ res,
103
+ Err(WorkerValidationError::NamespaceDescribeError { .. })
104
+ );
105
+ }
106
+
107
+ #[tokio::test]
108
+ async fn worker_handles_unknown_workflow_types_gracefully() {
109
+ let wf_type = "worker_handles_unknown_workflow_types_gracefully";
110
+ let mut starter = CoreWfStarter::new(wf_type);
111
+ let mut worker = starter.worker().await;
112
+
113
+ let run_id = worker
114
+ .submit_wf(
115
+ format!("wce-{}", Uuid::new_v4()),
116
+ "unregistered".to_string(),
117
+ vec![],
118
+ WorkflowOptions::default(),
119
+ )
120
+ .await
121
+ .unwrap();
122
+
123
+ struct GracefulAsserter {
124
+ notify: Arc<Notify>,
125
+ run_id: String,
126
+ unregistered_failure_seen: Cell<bool>,
127
+ }
128
+ #[async_trait::async_trait(?Send)]
129
+ impl WorkerInterceptor for GracefulAsserter {
130
+ async fn on_workflow_activation_completion(
131
+ &self,
132
+ completion: &WorkflowActivationCompletion,
133
+ ) {
134
+ if matches!(
135
+ completion,
136
+ WorkflowActivationCompletion {
137
+ status: Some(Status::Failed(Failure {
138
+ failure: Some(InnerFailure { message, .. }),
139
+ ..
140
+ })),
141
+ run_id,
142
+ } if message == "Workflow type unregistered not found" && *run_id == self.run_id
143
+ ) {
144
+ self.unregistered_failure_seen.set(true);
145
+ }
146
+ // If we've seen the failure, and the completion is a success for the same run, we're done
147
+ if matches!(
148
+ completion,
149
+ WorkflowActivationCompletion {
150
+ status: Some(Status::Successful(..)),
151
+ run_id,
152
+ } if self.unregistered_failure_seen.get() && *run_id == self.run_id
153
+ ) {
154
+ // Shutdown the worker
155
+ self.notify.notify_one();
156
+ }
157
+ }
158
+ fn on_shutdown(&self, _: &temporalio_sdk::Worker) {}
159
+ }
160
+
161
+ let inner = worker.inner_mut();
162
+ let notify = Arc::new(Notify::new());
163
+ inner.set_worker_interceptor(GracefulAsserter {
164
+ notify: notify.clone(),
165
+ run_id,
166
+ unregistered_failure_seen: Cell::new(false),
167
+ });
168
+ tokio::join!(async { inner.run().await.unwrap() }, async move {
169
+ notify.notified().await;
170
+ let worker = starter.get_worker().await.clone();
171
+ drain_pollers_and_shutdown(&worker).await;
172
+ });
173
+ }
174
+
175
+ #[tokio::test]
176
+ async fn resource_based_few_pollers_guarantees_non_sticky_poll() {
177
+ let wf_name = "resource_based_few_pollers_guarantees_non_sticky_poll";
178
+ let mut starter = CoreWfStarter::new(wf_name);
179
+ starter
180
+ .worker_config
181
+ .clear_max_outstanding_opts()
182
+ .task_types(WorkerTaskTypes::workflow_only())
183
+ // 3 pollers so the minimum slots of 2 can both be handed out to a sticky poller
184
+ .workflow_task_poller_behavior(PollerBehavior::SimpleMaximum(3_usize));
185
+ // Set the limits to zero so it's essentially unwilling to hand out slots
186
+ let mut tuner = ResourceBasedTuner::new(0.0, 0.0);
187
+ tuner.with_workflow_slots_options(ResourceSlotOptions::new(2, 10, Duration::from_millis(0)));
188
+ starter.worker_config.tuner(Arc::new(tuner));
189
+ let mut worker = starter.worker().await;
190
+
191
+ // Workflow doesn't actually need to do anything. We just need to see that we don't get stuck
192
+ // by assigning all slots to sticky pollers.
193
+ worker.register_wf(
194
+ wf_name.to_owned(),
195
+ |_: WfContext| async move { Ok(().into()) },
196
+ );
197
+ for i in 0..20 {
198
+ worker
199
+ .submit_wf(
200
+ format!("{wf_name}_{i}"),
201
+ wf_name.to_owned(),
202
+ vec![],
203
+ WorkflowOptions::default(),
204
+ )
205
+ .await
206
+ .unwrap();
207
+ }
208
+ worker.run_until_done().await.unwrap();
209
+ }
210
+
211
+ #[tokio::test]
212
+ async fn oversize_grpc_message() {
213
+ use crate::common::{NAMESPACE, prom_metrics};
214
+ let wf_name = "oversize_grpc_message";
215
+ // Enable Prometheus metrics for this test and capture the address
216
+ let (telemopts, addr, _aborter) = prom_metrics(None);
217
+ let runtime = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
218
+ let mut starter = CoreWfStarter::new_with_runtime(wf_name, runtime);
219
+ starter
220
+ .worker_config
221
+ .task_types(WorkerTaskTypes::workflow_only());
222
+ let mut core = starter.worker().await;
223
+
224
+ static OVERSIZE_GRPC_MESSAGE_RUN: AtomicBool = AtomicBool::new(false);
225
+ core.register_wf(wf_name.to_owned(), |_ctx: WfContext| async move {
226
+ if OVERSIZE_GRPC_MESSAGE_RUN.load(Relaxed) {
227
+ Ok(vec![].into())
228
+ } else {
229
+ OVERSIZE_GRPC_MESSAGE_RUN.store(true, Relaxed);
230
+ let result: Vec<u8> = vec![0; 5000000];
231
+ Ok(result.into())
232
+ }
233
+ });
234
+ starter.start_with_worker(wf_name, &mut core).await;
235
+ core.run_until_done().await.unwrap();
236
+
237
+ assert!(starter.get_history().await.events.iter().any(|e| {
238
+ e.event_type == EventType::WorkflowTaskFailed as i32
239
+ && if let WorkflowTaskFailedEventAttributes(attr) = e.attributes.as_ref().unwrap() {
240
+ attr.cause == GrpcMessageTooLarge as i32
241
+ && attr.failure.as_ref().unwrap().message == "GRPC Message too large"
242
+ } else {
243
+ false
244
+ }
245
+ }));
246
+
247
+ // Verify the workflow task failure metric includes the GrpcMessageTooLarge reason
248
+ let tq = starter.get_task_queue();
249
+ crate::common::eventually(
250
+ || async {
251
+ let body = crate::integ_tests::metrics_tests::get_text(format!("http://{addr}/metrics")).await;
252
+ if body.contains(&format!(
253
+ "temporal_workflow_task_execution_failed{{failure_reason=\"GrpcMessageTooLarge\",namespace=\"{NAMESPACE}\",service_name=\"temporal-core-sdk\",task_queue=\"{tq}\"}} 1"
254
+ )) {
255
+ Ok(())
256
+ } else {
257
+ Err(())
258
+ }
259
+ },
260
+ Duration::from_secs(2),
261
+ )
262
+ .await
263
+ .unwrap();
264
+ }
265
+
266
+ #[tokio::test]
267
+ async fn grpc_message_too_large_test() {
268
+ shared_tests::grpc_message_too_large().await
269
+ }
270
+
271
+ #[tokio::test]
272
+ async fn activity_tasks_from_completion_reserve_slots() {
273
+ let wf_id = "fake_wf_id";
274
+ let mut t = TestHistoryBuilder::default();
275
+ t.add_by_type(EventType::WorkflowExecutionStarted);
276
+ t.add_full_wf_task();
277
+ let schedid = t.add(EventAttributes::ActivityTaskScheduledEventAttributes(
278
+ ActivityTaskScheduledEventAttributes {
279
+ activity_id: "1".to_string(),
280
+ activity_type: Some("act1".into()),
281
+ ..Default::default()
282
+ },
283
+ ));
284
+ let startid = t.add_activity_task_started(schedid);
285
+ t.add_activity_task_completed(schedid, startid, b"hi".into());
286
+ t.add_full_wf_task();
287
+ let schedid = t.add(EventAttributes::ActivityTaskScheduledEventAttributes(
288
+ ActivityTaskScheduledEventAttributes {
289
+ activity_id: "2".to_string(),
290
+ activity_type: Some("act2".into()),
291
+ ..Default::default()
292
+ },
293
+ ));
294
+ let startid = t.add_activity_task_started(schedid);
295
+ t.add_activity_task_completed(schedid, startid, b"hi".into());
296
+ t.add_full_wf_task();
297
+ t.add_workflow_execution_completed();
298
+
299
+ let mut mock = mock_worker_client();
300
+ // Set up two tasks to be returned via normal activity polling
301
+ let act_tasks = vec![
302
+ PollActivityTaskQueueResponse {
303
+ task_token: vec![1],
304
+ activity_id: "act1".to_string(),
305
+ ..Default::default()
306
+ }
307
+ .into(),
308
+ PollActivityTaskQueueResponse {
309
+ task_token: vec![2],
310
+ activity_id: "act2".to_string(),
311
+ ..Default::default()
312
+ }
313
+ .into(),
314
+ ];
315
+ mock.expect_complete_activity_task()
316
+ .times(2)
317
+ .returning(|_, _| Ok(RespondActivityTaskCompletedResponse::default()));
318
+ let barr: &'static Barrier = Box::leak(Box::new(Barrier::new(2)));
319
+ let mut mh = MockPollCfg::from_resp_batches(
320
+ wf_id,
321
+ t,
322
+ [
323
+ ResponseType::ToTaskNum(1),
324
+ // We don't want the second task to be delivered until *after* the activity tasks
325
+ // have been completed, so that the second activity schedule will have slots available
326
+ ResponseType::UntilResolved(
327
+ async {
328
+ barr.wait().await;
329
+ barr.wait().await;
330
+ }
331
+ .boxed(),
332
+ 2,
333
+ ),
334
+ ResponseType::AllHistory,
335
+ ],
336
+ mock,
337
+ );
338
+ mh.completion_mock_fn = Some(Box::new(|wftc| {
339
+ // Make sure when we see the completion with the schedule act command that it does
340
+ // not have the eager execution flag set the first time, and does the second.
341
+ if let Some(Attributes::ScheduleActivityTaskCommandAttributes(attrs)) = wftc
342
+ .commands
343
+ .first()
344
+ .and_then(|cmd| cmd.attributes.as_ref())
345
+ {
346
+ if attrs.activity_id == "1" {
347
+ assert!(!attrs.request_eager_execution);
348
+ } else {
349
+ assert!(attrs.request_eager_execution);
350
+ }
351
+ }
352
+ Ok(Default::default())
353
+ }));
354
+ mh.activity_responses = Some(act_tasks);
355
+ let mut mock = build_mock_pollers(mh);
356
+ mock.worker_cfg(|cfg| {
357
+ cfg.max_cached_workflows = 2;
358
+ cfg.max_outstanding_activities = Some(2);
359
+ });
360
+ let core = Arc::new(mock_worker(mock));
361
+ let mut worker = crate::common::TestWorker::new(core.clone());
362
+
363
+ // First poll for activities twice, occupying both slots
364
+ let at1 = core.poll_activity_task().await.unwrap();
365
+ let at2 = core.poll_activity_task().await.unwrap();
366
+ let workflow_complete_token = CancellationToken::new();
367
+ let workflow_complete_token_clone = workflow_complete_token.clone();
368
+
369
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, move |ctx: WfContext| {
370
+ let complete_token = workflow_complete_token.clone();
371
+ async move {
372
+ ctx.activity(ActivityOptions {
373
+ activity_type: "act1".to_string(),
374
+ ..Default::default()
375
+ })
376
+ .await;
377
+ ctx.activity(ActivityOptions {
378
+ activity_type: "act2".to_string(),
379
+ ..Default::default()
380
+ })
381
+ .await;
382
+ complete_token.cancel();
383
+ Ok(().into())
384
+ }
385
+ });
386
+
387
+ worker
388
+ .submit_wf(
389
+ wf_id.to_owned(),
390
+ DEFAULT_WORKFLOW_TYPE,
391
+ vec![],
392
+ WorkflowOptions::default(),
393
+ )
394
+ .await
395
+ .unwrap();
396
+ let act_completer = async {
397
+ barr.wait().await;
398
+ core.complete_activity_task(ActivityTaskCompletion {
399
+ task_token: at1.task_token,
400
+ result: Some(ActivityExecutionResult::ok("hi".into())),
401
+ })
402
+ .await
403
+ .unwrap();
404
+ core.complete_activity_task(ActivityTaskCompletion {
405
+ task_token: at2.task_token,
406
+ result: Some(ActivityExecutionResult::ok("hi".into())),
407
+ })
408
+ .await
409
+ .unwrap();
410
+ barr.wait().await;
411
+ // Wait for workflow to complete in order for all eager activities to be requested before shutting down.
412
+ // After shutdown, no eager activities slots can be allocated.
413
+ workflow_complete_token_clone.cancelled().await;
414
+ core.initiate_shutdown();
415
+ // Even though this test requests eager activity tasks, none are returned in poll responses.
416
+ let err = core.poll_activity_task().await.unwrap_err();
417
+ assert_matches!(err, temporalio_common::errors::PollError::ShutDown);
418
+ };
419
+ // This wf poll should *not* set the flag that it wants tasks back since both slots are
420
+ // occupied
421
+ let run_fut = async { worker.run_until_done().await.unwrap() };
422
+ tokio::join!(run_fut, act_completer);
423
+ }
424
+
425
+ #[tokio::test]
426
+ async fn max_wft_respected() {
427
+ let total_wfs = 100;
428
+ let wf_ids: Vec<_> = (0..total_wfs).map(|i| format!("fake-wf-{i}")).collect();
429
+ let hists = wf_ids.iter().map(|wf_id| {
430
+ let hist = canned_histories::single_timer("1");
431
+ FakeWfResponses {
432
+ wf_id: wf_id.to_string(),
433
+ hist,
434
+ response_batches: vec![1.into(), 2.into()],
435
+ }
436
+ });
437
+ let mh = MockPollCfg::new(hists.into_iter().collect(), true, 0);
438
+ let mut worker = mock_sdk_cfg(mh, |cfg| {
439
+ cfg.max_cached_workflows = total_wfs as usize;
440
+ cfg.max_outstanding_workflow_tasks = Some(1);
441
+ });
442
+ let active_count: &'static _ = Box::leak(Box::new(Semaphore::new(1)));
443
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, move |ctx: WfContext| async move {
444
+ drop(
445
+ active_count
446
+ .try_acquire()
447
+ .expect("No multiple concurrent workflow tasks!"),
448
+ );
449
+ ctx.timer(Duration::from_secs(1)).await;
450
+ Ok(().into())
451
+ });
452
+
453
+ for wf_id in wf_ids {
454
+ worker
455
+ .submit_wf(wf_id, DEFAULT_WORKFLOW_TYPE, vec![], Default::default())
456
+ .await
457
+ .unwrap();
458
+ }
459
+ worker.run_until_done().await.unwrap();
460
+ }
461
+
462
+ #[rstest]
463
+ #[tokio::test]
464
+ async fn history_length_with_fail_and_timeout(
465
+ #[values(true, false)] use_cache: bool,
466
+ #[values(1, 2, 3)] history_responses_case: u8,
467
+ ) {
468
+ if !use_cache && history_responses_case == 3 {
469
+ eprintln!(
470
+ "Skipping history_length_with_fail_and_timeout::use_cache_2_false::history_responses_case_3_3 due to flaky hang"
471
+ );
472
+ return;
473
+ }
474
+ let wfid = "fake_wf_id";
475
+ let mut t = TestHistoryBuilder::default();
476
+ t.add_by_type(EventType::WorkflowExecutionStarted);
477
+ t.add_full_wf_task();
478
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
479
+ t.add_timer_fired(timer_started_event_id, "1".to_string());
480
+ t.add_workflow_task_scheduled_and_started();
481
+ t.add_workflow_task_failed_with_failure(WorkflowTaskFailedCause::Unspecified, "ahh".into());
482
+ t.add_workflow_task_scheduled_and_started();
483
+ t.add_workflow_task_timed_out();
484
+ t.add_full_wf_task();
485
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
486
+ t.add_timer_fired(timer_started_event_id, "2".to_string());
487
+ t.add_full_wf_task();
488
+ t.add_workflow_execution_completed();
489
+
490
+ let mut mock_client = mock_worker_client();
491
+ let history_responses = match history_responses_case {
492
+ 1 => vec![ResponseType::AllHistory],
493
+ 2 => vec![
494
+ ResponseType::ToTaskNum(1),
495
+ ResponseType::ToTaskNum(2),
496
+ ResponseType::AllHistory,
497
+ ],
498
+ 3 => {
499
+ let mut needs_fetch = hist_to_poll_resp(&t, wfid, ResponseType::ToTaskNum(2)).resp;
500
+ needs_fetch.next_page_token = vec![1];
501
+ // Truncate the history a bit in order to force incomplete WFT
502
+ needs_fetch.history.as_mut().unwrap().events.truncate(6);
503
+ let needs_fetch_resp = ResponseType::Raw(needs_fetch);
504
+ let mut empty_fetch_resp: GetWorkflowExecutionHistoryResponse =
505
+ t.get_history_info(1).unwrap().into();
506
+ empty_fetch_resp.history.as_mut().unwrap().events = vec![];
507
+ mock_client
508
+ .expect_get_workflow_execution_history()
509
+ .returning(move |_, _, _| Ok(empty_fetch_resp.clone()))
510
+ .times(1);
511
+ vec![
512
+ ResponseType::ToTaskNum(1),
513
+ needs_fetch_resp,
514
+ ResponseType::ToTaskNum(2),
515
+ ResponseType::AllHistory,
516
+ ]
517
+ }
518
+ _ => unreachable!(),
519
+ };
520
+
521
+ let mut mh = MockPollCfg::from_resp_batches(wfid, t, history_responses, mock_client);
522
+ if history_responses_case == 3 {
523
+ // Expect the failed pagination fetch
524
+ mh.num_expected_fails = 1;
525
+ }
526
+ let mut worker = mock_sdk_cfg(mh, |wc| {
527
+ if use_cache {
528
+ wc.max_cached_workflows = 1;
529
+ }
530
+ });
531
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, |ctx: WfContext| async move {
532
+ assert_eq!(ctx.history_length(), 3);
533
+ ctx.timer(Duration::from_secs(1)).await;
534
+ assert_eq!(ctx.history_length(), 14);
535
+ ctx.timer(Duration::from_secs(1)).await;
536
+ assert_eq!(ctx.history_length(), 19);
537
+ Ok(().into())
538
+ });
539
+ worker
540
+ .submit_wf(
541
+ wfid.to_owned(),
542
+ DEFAULT_WORKFLOW_TYPE.to_owned(),
543
+ vec![],
544
+ WorkflowOptions::default(),
545
+ )
546
+ .await
547
+ .unwrap();
548
+ worker.run_until_done().await.unwrap();
549
+ }
550
+
551
+ #[allow(deprecated)]
552
+ #[tokio::test]
553
+ async fn sets_build_id_from_wft_complete() {
554
+ let wfid = "fake_wf_id";
555
+
556
+ let mut t = TestHistoryBuilder::default();
557
+ t.add_by_type(EventType::WorkflowExecutionStarted);
558
+ t.add_full_wf_task();
559
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
560
+ t.add_timer_fired(timer_started_event_id, "1".to_string());
561
+ t.add_full_wf_task();
562
+ t.modify_event(t.current_event_id(), |he| {
563
+ if let history_event::Attributes::WorkflowTaskCompletedEventAttributes(a) =
564
+ he.attributes.as_mut().unwrap()
565
+ {
566
+ a.worker_version = Some(WorkerVersionStamp {
567
+ build_id: "enchi-cat".to_string(),
568
+ ..Default::default()
569
+ });
570
+ }
571
+ });
572
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
573
+ t.add_timer_fired(timer_started_event_id, "2".to_string());
574
+ t.add_workflow_task_scheduled_and_started();
575
+
576
+ let mock = mock_worker_client();
577
+ let mut worker = mock_sdk_cfg(
578
+ MockPollCfg::from_resp_batches(wfid, t, [ResponseType::AllHistory], mock),
579
+ |cfg| {
580
+ cfg.versioning_strategy = WorkerVersioningStrategy::None {
581
+ build_id: "fierce-predator".to_string(),
582
+ };
583
+ cfg.max_cached_workflows = 1;
584
+ },
585
+ );
586
+
587
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, |ctx: WfContext| async move {
588
+ // First task, it should be empty, since replaying and nothing in first WFT completed
589
+ assert_eq!(ctx.current_deployment_version(), None);
590
+ ctx.timer(Duration::from_secs(1)).await;
591
+ assert_eq!(
592
+ ctx.current_deployment_version().unwrap().build_id,
593
+ "enchi-cat"
594
+ );
595
+ ctx.timer(Duration::from_secs(1)).await;
596
+ // Not replaying at this point, so we should see the worker's build id
597
+ assert_eq!(
598
+ ctx.current_deployment_version().unwrap().build_id,
599
+ "fierce-predator"
600
+ );
601
+ ctx.timer(Duration::from_secs(1)).await;
602
+ assert_eq!(
603
+ ctx.current_deployment_version().unwrap().build_id,
604
+ "fierce-predator"
605
+ );
606
+ Ok(().into())
607
+ });
608
+ worker
609
+ .submit_wf(wfid, DEFAULT_WORKFLOW_TYPE, vec![], Default::default())
610
+ .await
611
+ .unwrap();
612
+ worker.run_until_done().await.unwrap();
613
+ }
614
+
615
+ #[derive(Debug, Clone)]
616
+ enum SlotEvent {
617
+ ReserveSlot {
618
+ slot_type: &'static str,
619
+ },
620
+ TryReserveSlot {
621
+ slot_type: &'static str,
622
+ },
623
+ MarkSlotUsed {
624
+ slot_type: &'static str,
625
+ is_sticky: bool,
626
+ workflow_type: Option<String>,
627
+ activity_type: Option<String>,
628
+ },
629
+ ReleaseSlot {
630
+ slot_type: &'static str,
631
+ },
632
+ }
633
+
634
+ struct TrackingSlotSupplier<SK> {
635
+ events: Arc<Mutex<Vec<SlotEvent>>>,
636
+ slot_type: &'static str,
637
+ _phantom: std::marker::PhantomData<SK>,
638
+ }
639
+
640
+ impl<SK> TrackingSlotSupplier<SK> {
641
+ fn new(slot_type: &'static str) -> Self {
642
+ Self {
643
+ events: Arc::new(Mutex::new(Vec::new())),
644
+ slot_type,
645
+ _phantom: std::marker::PhantomData,
646
+ }
647
+ }
648
+
649
+ fn get_events(&self) -> Vec<SlotEvent> {
650
+ self.events.lock().unwrap().clone()
651
+ }
652
+
653
+ fn add_event(&self, event: SlotEvent) {
654
+ self.events.lock().unwrap().push(event);
655
+ }
656
+
657
+ fn extract_slot_info(info: &dyn SlotInfoTrait) -> (bool, Option<String>, Option<String>) {
658
+ match info.downcast() {
659
+ SlotInfo::Workflow(w) => (w.is_sticky, Some(w.workflow_type.clone()), None),
660
+ SlotInfo::Activity(a) => (false, None, Some(a.activity_type.clone())),
661
+ SlotInfo::LocalActivity(a) => (false, None, Some(a.activity_type.clone())),
662
+ SlotInfo::Nexus(_) => (false, None, None),
663
+ }
664
+ }
665
+ }
666
+
667
+ #[async_trait::async_trait]
668
+ impl<SK> SlotSupplier for TrackingSlotSupplier<SK>
669
+ where
670
+ SK: temporalio_common::worker::SlotKind + Send + Sync,
671
+ SK::Info: SlotInfoTrait,
672
+ {
673
+ type SlotKind = SK;
674
+
675
+ async fn reserve_slot(&self, _ctx: &dyn SlotReservationContext) -> SlotSupplierPermit {
676
+ self.add_event(SlotEvent::ReserveSlot {
677
+ slot_type: self.slot_type,
678
+ });
679
+ SlotSupplierPermit::with_user_data(())
680
+ }
681
+
682
+ fn try_reserve_slot(&self, _ctx: &dyn SlotReservationContext) -> Option<SlotSupplierPermit> {
683
+ self.add_event(SlotEvent::TryReserveSlot {
684
+ slot_type: self.slot_type,
685
+ });
686
+ Some(SlotSupplierPermit::with_user_data(()))
687
+ }
688
+
689
+ fn mark_slot_used(&self, ctx: &dyn SlotMarkUsedContext<SlotKind = Self::SlotKind>) {
690
+ let (is_sticky, workflow_type, activity_type) = Self::extract_slot_info(ctx.info());
691
+ self.add_event(SlotEvent::MarkSlotUsed {
692
+ slot_type: self.slot_type,
693
+ is_sticky,
694
+ workflow_type,
695
+ activity_type,
696
+ });
697
+ }
698
+
699
+ fn release_slot(&self, _ctx: &dyn SlotReleaseContext<SlotKind = Self::SlotKind>) {
700
+ self.add_event(SlotEvent::ReleaseSlot {
701
+ slot_type: self.slot_type,
702
+ });
703
+ }
704
+ }
705
+
706
+ #[tokio::test]
707
+ async fn test_custom_slot_supplier_simple() {
708
+ let wf_supplier = Arc::new(TrackingSlotSupplier::<WorkflowSlotKind>::new("workflow"));
709
+ let activity_supplier = Arc::new(TrackingSlotSupplier::<ActivitySlotKind>::new("activity"));
710
+ let local_activity_supplier = Arc::new(TrackingSlotSupplier::<LocalActivitySlotKind>::new(
711
+ "local_activity",
712
+ ));
713
+
714
+ let mut starter = CoreWfStarter::new("test_custom_slot_supplier_simple");
715
+ starter.worker_config.clear_max_outstanding_opts();
716
+
717
+ let mut tb = TunerBuilder::default();
718
+ tb.workflow_slot_supplier(wf_supplier.clone());
719
+ tb.activity_slot_supplier(activity_supplier.clone());
720
+ tb.local_activity_slot_supplier(local_activity_supplier.clone());
721
+ starter.worker_config.tuner(Arc::new(tb.build()));
722
+
723
+ let mut worker = starter.worker().await;
724
+
725
+ worker.register_activity(
726
+ "SlotSupplierActivity",
727
+ |_: temporalio_sdk::ActContext, _: ()| async move { Ok(()) },
728
+ );
729
+ worker.register_wf(
730
+ "SlotSupplierWorkflow".to_owned(),
731
+ |ctx: WfContext| async move {
732
+ let _result = ctx
733
+ .activity(ActivityOptions {
734
+ activity_type: "SlotSupplierActivity".to_string(),
735
+ start_to_close_timeout: Some(Duration::from_secs(10)),
736
+ ..Default::default()
737
+ })
738
+ .await;
739
+ let _result = ctx
740
+ .local_activity(LocalActivityOptions {
741
+ activity_type: "SlotSupplierActivity".to_string(),
742
+ start_to_close_timeout: Some(Duration::from_secs(10)),
743
+ ..Default::default()
744
+ })
745
+ .await;
746
+ Ok(().into())
747
+ },
748
+ );
749
+
750
+ worker
751
+ .submit_wf(
752
+ "test-wf".to_owned(),
753
+ "SlotSupplierWorkflow".to_owned(),
754
+ vec![],
755
+ Default::default(),
756
+ )
757
+ .await
758
+ .unwrap();
759
+
760
+ worker.run_until_done().await.unwrap();
761
+
762
+ // Collect all events
763
+ let wf_events = wf_supplier.get_events();
764
+ let activity_events = activity_supplier.get_events();
765
+ let local_activity_events = local_activity_supplier.get_events();
766
+
767
+ // Verify workflow slot events - should have reserve, mark used, and release events
768
+ assert!(wf_events.iter().any(
769
+ |e| matches!(e, SlotEvent::ReserveSlot { slot_type, .. } if *slot_type == "workflow")
770
+ ));
771
+ assert!(wf_events.iter().any(
772
+ |e| matches!(e, SlotEvent::MarkSlotUsed { slot_type, .. } if *slot_type == "workflow")
773
+ ));
774
+ assert!(
775
+ wf_events
776
+ .iter()
777
+ .any(|e| matches!(e, SlotEvent::ReleaseSlot { slot_type } if *slot_type == "workflow"))
778
+ );
779
+
780
+ // Verify activity slot events - should have reserve, try_reserve (for eager execution), mark
781
+ // used, and release
782
+ assert!(activity_events.iter().any(
783
+ |e| matches!(e, SlotEvent::ReserveSlot { slot_type, .. } if *slot_type == "activity")
784
+ ));
785
+ assert!(
786
+ activity_events.iter().any(
787
+ |e| matches!(e, SlotEvent::TryReserveSlot { slot_type } if *slot_type == "activity")
788
+ )
789
+ );
790
+ assert!(activity_events.iter().any(
791
+ |e| matches!(e, SlotEvent::MarkSlotUsed { slot_type, .. } if *slot_type == "activity")
792
+ ));
793
+ assert!(
794
+ activity_events
795
+ .iter()
796
+ .any(|e| matches!(e, SlotEvent::ReleaseSlot { slot_type } if *slot_type == "activity"))
797
+ );
798
+
799
+ // Verify local activity slot events
800
+ assert!(local_activity_events.iter().any(
801
+ |e| matches!(e, SlotEvent::ReserveSlot { slot_type, .. } if *slot_type == "local_activity")
802
+ ));
803
+ assert!(local_activity_events.iter().any(
804
+ |e| matches!(e, SlotEvent::MarkSlotUsed { slot_type, .. } if *slot_type == "local_activity")
805
+ ));
806
+ assert!(local_activity_events.iter().any(
807
+ |e| matches!(e, SlotEvent::ReleaseSlot { slot_type } if *slot_type == "local_activity")
808
+ ));
809
+
810
+ assert!(
811
+ wf_events
812
+ .iter()
813
+ .any(|e| matches!(e, SlotEvent::MarkSlotUsed {
814
+ slot_type: "workflow",
815
+ workflow_type: Some(wf_type),
816
+ ..
817
+ } if wf_type == "SlotSupplierWorkflow"))
818
+ );
819
+ assert!(
820
+ activity_events
821
+ .iter()
822
+ .any(|e| matches!(e, SlotEvent::MarkSlotUsed {
823
+ slot_type: "activity",
824
+ activity_type: Some(act_type),
825
+ ..
826
+ } if act_type == "SlotSupplierActivity"))
827
+ );
828
+ assert!(
829
+ local_activity_events
830
+ .iter()
831
+ .any(|e| matches!(e, SlotEvent::MarkSlotUsed {
832
+ slot_type: "local_activity",
833
+ activity_type: Some(act_type),
834
+ ..
835
+ } if act_type == "SlotSupplierActivity"))
836
+ );
837
+ assert!(wf_events.iter().any(|e| matches!(
838
+ e,
839
+ SlotEvent::MarkSlotUsed {
840
+ slot_type: "workflow",
841
+ is_sticky: false,
842
+ ..
843
+ }
844
+ )));
845
+
846
+ // Verify that the number of reserve/try_reserve events matches the number of release events
847
+ let total_reserves = wf_events
848
+ .iter()
849
+ .filter(|e| {
850
+ matches!(
851
+ e,
852
+ SlotEvent::ReserveSlot { .. } | SlotEvent::TryReserveSlot { .. }
853
+ )
854
+ })
855
+ .count()
856
+ + activity_events
857
+ .iter()
858
+ .filter(|e| {
859
+ matches!(
860
+ e,
861
+ SlotEvent::ReserveSlot { .. } | SlotEvent::TryReserveSlot { .. }
862
+ )
863
+ })
864
+ .count()
865
+ + local_activity_events
866
+ .iter()
867
+ .filter(|e| {
868
+ matches!(
869
+ e,
870
+ SlotEvent::ReserveSlot { .. } | SlotEvent::TryReserveSlot { .. }
871
+ )
872
+ })
873
+ .count();
874
+
875
+ let total_releases = wf_events
876
+ .iter()
877
+ .filter(|e| matches!(e, SlotEvent::ReleaseSlot { .. }))
878
+ .count()
879
+ + activity_events
880
+ .iter()
881
+ .filter(|e| matches!(e, SlotEvent::ReleaseSlot { .. }))
882
+ .count()
883
+ + local_activity_events
884
+ .iter()
885
+ .filter(|e| matches!(e, SlotEvent::ReleaseSlot { .. }))
886
+ .count();
887
+
888
+ assert_eq!(
889
+ total_reserves, total_releases,
890
+ "Number of reserves should equal number of releases"
891
+ );
892
+ }
893
+
894
+ #[tokio::test]
895
+ async fn shutdown_worker_not_retried() {
896
+ let shutdown_call_count = Arc::new(AtomicU8::new(0));
897
+ let scc = shutdown_call_count.clone();
898
+ let fs = fake_server(move |req| {
899
+ if req.uri().to_string().contains("ShutdownWorker") {
900
+ scc.fetch_add(1, Ordering::Relaxed);
901
+ }
902
+ let s = tonic::Status::new(tonic::Code::Unknown, "bla").into_http();
903
+ async { s }.boxed()
904
+ })
905
+ .await;
906
+
907
+ let mut opts = get_integ_server_options();
908
+ let uri = format!("http://localhost:{}", fs.addr.port())
909
+ .parse()
910
+ .unwrap();
911
+ opts.target_url = uri;
912
+ opts.skip_get_system_info = true;
913
+ let client = opts.connect("ns", None).await.unwrap();
914
+
915
+ let wf_type = "shutdown_worker_not_retried";
916
+ let mut starter = CoreWfStarter::new_with_overrides(wf_type, None, Some(client));
917
+ let worker = starter.get_worker().await;
918
+ drain_pollers_and_shutdown(&worker).await;
919
+ assert_eq!(shutdown_call_count.load(Ordering::Relaxed), 1);
920
+ }