@temporalio/core-bridge 1.15.0 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/Cargo.lock +172 -70
  2. package/lib/native.d.ts +1 -1
  3. package/package.json +2 -2
  4. package/releases/aarch64-apple-darwin/index.node +0 -0
  5. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  6. package/releases/x86_64-apple-darwin/index.node +0 -0
  7. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  8. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  9. package/sdk-core/.github/workflows/per-pr.yml +6 -6
  10. package/sdk-core/AGENTS.md +41 -30
  11. package/sdk-core/Cargo.toml +3 -0
  12. package/sdk-core/README.md +15 -9
  13. package/sdk-core/crates/client/Cargo.toml +4 -0
  14. package/sdk-core/crates/client/README.md +139 -0
  15. package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
  16. package/sdk-core/crates/client/src/callback_based.rs +7 -0
  17. package/sdk-core/crates/client/src/errors.rs +294 -0
  18. package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +280 -159
  19. package/sdk-core/crates/client/src/lib.rs +920 -1326
  20. package/sdk-core/crates/client/src/metrics.rs +24 -33
  21. package/sdk-core/crates/client/src/options_structs.rs +457 -0
  22. package/sdk-core/crates/client/src/replaceable.rs +5 -4
  23. package/sdk-core/crates/client/src/request_extensions.rs +8 -9
  24. package/sdk-core/crates/client/src/retry.rs +99 -54
  25. package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +1 -1
  26. package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
  27. package/sdk-core/crates/common/Cargo.toml +61 -2
  28. package/sdk-core/crates/common/build.rs +742 -12
  29. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
  30. package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
  31. package/sdk-core/crates/common/protos/api_upstream/buf.yaml +0 -3
  32. package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
  33. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +1166 -770
  34. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +1243 -750
  35. package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +2 -2
  36. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +4 -3
  37. package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
  38. package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +4 -0
  39. package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
  40. package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +16 -1
  41. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -6
  42. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +88 -33
  43. package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +4 -2
  44. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +4 -0
  45. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +5 -5
  46. package/sdk-core/crates/common/src/activity_definition.rs +20 -0
  47. package/sdk-core/crates/common/src/data_converters.rs +770 -0
  48. package/sdk-core/crates/common/src/envconfig.rs +5 -0
  49. package/sdk-core/crates/common/src/lib.rs +15 -211
  50. package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
  51. package/sdk-core/crates/common/src/priority.rs +110 -0
  52. package/sdk-core/crates/common/src/protos/canned_histories.rs +3 -0
  53. package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
  54. package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
  55. package/sdk-core/crates/common/src/protos/mod.rs +122 -27
  56. package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
  57. package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
  58. package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +5 -7
  59. package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
  60. package/sdk-core/crates/common/src/telemetry/metrics.rs +268 -223
  61. package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
  62. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
  63. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
  64. package/sdk-core/crates/common/src/telemetry.rs +264 -4
  65. package/sdk-core/crates/common/src/worker.rs +68 -603
  66. package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
  67. package/sdk-core/crates/macros/Cargo.toml +5 -1
  68. package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
  69. package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
  70. package/sdk-core/crates/macros/src/lib.rs +138 -512
  71. package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
  72. package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
  73. package/sdk-core/crates/sdk/Cargo.toml +19 -6
  74. package/sdk-core/crates/sdk/README.md +415 -0
  75. package/sdk-core/crates/sdk/src/activities.rs +417 -0
  76. package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
  77. package/sdk-core/crates/sdk/src/lib.rs +757 -442
  78. package/sdk-core/crates/sdk/src/workflow_context/options.rs +45 -35
  79. package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
  80. package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
  81. package/sdk-core/crates/sdk/src/workflows.rs +711 -0
  82. package/sdk-core/crates/sdk-core/Cargo.toml +57 -64
  83. package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +41 -35
  84. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
  85. package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
  86. package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
  87. package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +13 -15
  88. package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
  89. package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
  90. package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
  91. package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +493 -26
  92. package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +4 -8
  93. package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +7 -7
  94. package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
  95. package/sdk-core/crates/sdk-core/src/lib.rs +41 -111
  96. package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
  97. package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +118 -19
  98. package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
  99. package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
  100. package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +179 -196
  101. package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -280
  102. package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +6 -9
  103. package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
  104. package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
  105. package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
  106. package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +9 -5
  107. package/sdk-core/crates/sdk-core/src/worker/client.rs +103 -81
  108. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +7 -11
  109. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1124 -229
  110. package/sdk-core/crates/sdk-core/src/worker/nexus.rs +145 -23
  111. package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
  112. package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
  113. package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +13 -13
  114. package/sdk-core/crates/sdk-core/src/worker/tuner.rs +28 -8
  115. package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
  116. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
  117. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +19 -4
  118. package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +14 -18
  119. package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +4 -6
  120. package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
  121. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
  122. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
  123. package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
  124. package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
  125. package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
  126. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
  127. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
  128. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
  129. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
  130. package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
  131. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
  132. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
  133. package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
  134. package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
  135. package/sdk-core/crates/sdk-core/tests/common/mod.rs +241 -196
  136. package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
  137. package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +3 -5
  138. package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -64
  139. package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +298 -252
  140. package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
  141. package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
  142. package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
  143. package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +16 -12
  144. package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +48 -40
  145. package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +327 -255
  146. package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
  147. package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +147 -126
  148. package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
  149. package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -453
  150. package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
  151. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +360 -231
  152. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +248 -185
  153. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -43
  154. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
  155. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +428 -315
  156. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -56
  157. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -28
  158. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -243
  159. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
  160. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +101 -42
  161. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -147
  162. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -28
  163. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1036
  164. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -41
  165. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +397 -238
  166. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +414 -189
  167. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
  168. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
  169. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +154 -137
  170. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -105
  171. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -38
  172. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -40
  173. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -54
  174. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +363 -226
  175. package/sdk-core/crates/sdk-core/tests/main.rs +17 -15
  176. package/sdk-core/crates/sdk-core/tests/manual_tests.rs +207 -152
  177. package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +65 -34
  178. package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
  179. package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
  180. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
  181. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
  182. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
  183. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
  184. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
  185. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
  186. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
  187. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
  188. package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +7 -1
  189. package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +14 -14
  190. package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +83 -74
  191. package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +9 -14
  192. package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +1 -2
  193. package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +13 -13
  194. package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +6 -6
  195. package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +3 -4
  196. package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +62 -75
  197. package/sdk-core/rustfmt.toml +2 -1
  198. package/src/client.rs +205 -318
  199. package/src/metrics.rs +22 -30
  200. package/src/runtime.rs +4 -5
  201. package/src/worker.rs +16 -19
  202. package/ts/native.ts +1 -1
  203. package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
  204. package/sdk-core/crates/common/src/errors.rs +0 -85
  205. package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
  206. package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
  207. package/sdk-core/crates/sdk/src/app_data.rs +0 -37
  208. package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
  209. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
@@ -5,27 +5,37 @@
5
5
  //! We can use `clap` if this needs more arguments / other stuff later on.
6
6
 
7
7
  use prost::Message;
8
- use temporalio_client::{ClientOptions, WorkflowClientTrait};
8
+ use temporalio_client::{
9
+ Client, ClientOptions, Connection, ConnectionOptions, NamespacedClient, WorkflowExecutionInfo,
10
+ WorkflowFetchHistoryOptions,
11
+ };
12
+ use temporalio_common::protos::temporal::api::history::v1::History;
9
13
  use url::Url;
10
14
 
11
15
  #[tokio::main]
12
16
  async fn main() -> Result<(), anyhow::Error> {
13
- let url = Url::try_from("http://localhost:7233").unwrap();
14
- let copts = ClientOptions::builder()
17
+ let copts = ConnectionOptions::new(Url::try_from("http://localhost:7233").unwrap())
15
18
  .client_name("histfetch")
16
19
  .client_version("0.0")
17
- .target_url(url)
18
20
  .build();
19
- let client = copts.connect("default", None).await?;
21
+ let connection = Connection::connect(copts).await?;
22
+ let client = Client::new(connection, ClientOptions::new("default").build())?;
20
23
  let wf_id = std::env::args()
21
24
  .nth(1)
22
25
  .expect("must provide workflow id as only argument");
23
- let run_id = std::env::args().nth(2);
24
- let hist = client
25
- .get_workflow_execution_history(wf_id.clone(), run_id, vec![])
26
+ let run_id = std::env::args().nth(2).filter(|s| !s.is_empty());
27
+ let handle = WorkflowExecutionInfo {
28
+ namespace: client.namespace(),
29
+ workflow_id: wf_id.clone(),
30
+ run_id,
31
+ first_execution_run_id: None,
32
+ }
33
+ .bind_untyped(client);
34
+ let events = handle
35
+ .fetch_history(WorkflowFetchHistoryOptions::default())
26
36
  .await?
27
- .history
28
- .expect("history field must be populated");
37
+ .into_events();
38
+ let hist = History { events };
29
39
  // Serialize history to file
30
40
  let byteified = hist.encode_to_vec();
31
41
  tokio::fs::write(format!("{wf_id}_history.bin"), &byteified).await?;
@@ -2,7 +2,9 @@
2
2
  #![allow(clippy::upper_case_acronyms)]
3
3
 
4
4
  //! This crate provides a basis for creating new Temporal SDKs without completely starting from
5
- //! scratch
5
+ //! scratch. APIs provided by this crate are not considered stable and may break at any time.
6
+ //!
7
+ //! If you are looking for the Temporal Rust SDK, please use `temporalio-sdk`.
6
8
 
7
9
  #[cfg(test)]
8
10
  #[macro_use]
@@ -32,41 +34,38 @@ mod core_tests;
32
34
  #[macro_use]
33
35
  pub mod test_help;
34
36
 
35
- pub(crate) use temporalio_common::errors;
36
-
37
- pub use pollers::{
38
- Client, ClientOptions, ClientTlsOptions, RetryClient, RetryOptions, TlsOptions,
39
- WorkflowClientTrait,
37
+ pub use crate::worker::client::{
38
+ PollActivityOptions, PollOptions, PollWorkflowOptions, WorkerClient, WorkflowTaskCompletion,
40
39
  };
40
+ pub use pollers::{Client, ClientOptions, ClientTlsOptions, RetryOptions, TlsOptions};
41
41
  pub use temporalio_common::protos::TaskToken;
42
42
  pub use url::Url;
43
43
  pub use worker::{
44
- FixedSizeSlotSupplier, ResourceBasedSlotsOptions, ResourceBasedSlotsOptionsBuilder,
45
- ResourceBasedTuner, ResourceSlotOptions, SlotSupplierOptions, TunerBuilder, TunerHolder,
46
- TunerHolderOptions, TunerHolderOptionsBuilder, Worker, WorkerConfig, WorkerConfigBuilder,
44
+ ActivitySlotKind, CompleteActivityError, CompleteNexusError, CompleteWfError,
45
+ FixedSizeSlotSupplier, LocalActivitySlotKind, NexusSlotKind, PollError, PollerBehavior,
46
+ ResourceBasedSlotsOptions, ResourceBasedSlotsOptionsBuilder, ResourceBasedTuner,
47
+ ResourceSlotOptions, SlotInfo, SlotInfoTrait, SlotKind, SlotKindType, SlotMarkUsedContext,
48
+ SlotReleaseContext, SlotReservationContext, SlotSupplier, SlotSupplierOptions,
49
+ SlotSupplierPermit, TunerBuilder, TunerHolder, TunerHolderOptions, TunerHolderOptionsBuilder,
50
+ Worker, WorkerConfig, WorkerConfigBuilder, WorkerTuner, WorkerValidationError,
51
+ WorkerVersioningStrategy, WorkflowErrorType, WorkflowSlotKind,
47
52
  };
48
53
 
49
- /// Expose [WorkerClient] symbols
50
- pub use crate::worker::client::{
51
- PollActivityOptions, PollOptions, PollWorkflowOptions, WorkerClient, WorkflowTaskCompletion,
52
- };
53
54
  use crate::{
54
55
  replay::{HistoryForReplay, ReplayWorkerInput},
55
- telemetry::{
56
- TelemetryInstance, metrics::MetricsContext, remove_trace_subscriber_for_current_thread,
57
- set_trace_subscriber_for_current_thread, telemetry_init,
58
- },
56
+ telemetry::metrics::MetricsContext,
59
57
  worker::client::WorkerClientBag,
60
58
  };
61
59
  use anyhow::bail;
62
60
  use futures_util::Stream;
63
61
  use std::{sync::Arc, time::Duration};
64
- use temporalio_client::{ConfiguredClient, NamespacedClient, SharedReplaceableClient};
62
+ use temporalio_client::{Connection, SharedReplaceableClient};
65
63
  use temporalio_common::{
66
- Worker as WorkerTrait,
67
- errors::{CompleteActivityError, PollError},
68
64
  protos::coresdk::ActivityHeartbeat,
69
- telemetry::TelemetryOptions,
65
+ telemetry::{
66
+ TelemetryInstance, TelemetryOptions, remove_trace_subscriber_for_current_thread,
67
+ set_trace_subscriber_for_current_thread, telemetry_init,
68
+ },
70
69
  };
71
70
 
72
71
  /// Initialize a worker bound to a task queue.
@@ -75,44 +74,37 @@ use temporalio_common::{
75
74
  /// After the worker is initialized, you should use [CoreRuntime::tokio_handle] to run the worker's
76
75
  /// async functions.
77
76
  ///
78
- /// Lang implementations may pass in a [ConfiguredClient] directly (or a
79
- /// [RetryClient] wrapping one, or a handful of other variants of the same idea). When they do so,
80
- /// this function will always overwrite the client retry configuration, force the client to use the
81
- /// namespace defined in the worker config, and set the client identity appropriately. IE: Use
82
- /// [ClientOptions::connect_no_namespace], not [ClientOptions::connect].
83
- pub fn init_worker<CT>(
77
+ /// Lang implementations must pass in a [Client] When they do so, this function will always
78
+ /// overwrite the client retry configuration, force the client to use the namespace defined in the
79
+ /// worker config, and set the client identity appropriately.
80
+ pub fn init_worker(
84
81
  runtime: &CoreRuntime,
85
82
  worker_config: WorkerConfig,
86
- client: CT,
87
- ) -> Result<Worker, anyhow::Error>
88
- where
89
- CT: Into<sealed::AnyClient>,
90
- {
83
+ mut connection: Connection,
84
+ ) -> Result<Worker, anyhow::Error> {
91
85
  let namespace = worker_config.namespace.clone();
92
86
  if namespace.is_empty() {
93
87
  bail!("Worker namespace cannot be empty");
94
88
  }
95
89
 
96
- let client = RetryClient::new(
97
- SharedReplaceableClient::new(init_worker_client(
98
- worker_config.namespace.clone(),
99
- worker_config.client_identity_override.clone(),
100
- client,
101
- )),
102
- RetryOptions::default(),
90
+ *connection.retry_options_mut() = RetryOptions::default();
91
+ init_worker_client(
92
+ &mut connection,
93
+ worker_config.client_identity_override.clone(),
103
94
  );
104
- let client_ident = client.identity();
105
- let sticky_q = sticky_q_name_for_worker(&client_ident, worker_config.max_cached_workflows);
106
-
95
+ let client = SharedReplaceableClient::new(connection);
96
+ let client_ident = client.inner_cow().identity().to_owned();
107
97
  if client_ident.is_empty() {
108
98
  bail!("Client identity cannot be empty. Either lang or user should be setting this value");
109
99
  }
100
+ let sticky_q = sticky_q_name_for_worker(&client_ident, worker_config.max_cached_workflows);
110
101
 
102
+ let worker_instance_key = uuid::Uuid::new_v4();
111
103
  let client_bag = Arc::new(WorkerClientBag::new(
112
104
  client,
113
105
  namespace.clone(),
114
- client_ident.clone(),
115
106
  worker_config.versioning_strategy.clone(),
107
+ worker_instance_key,
116
108
  ));
117
109
 
118
110
  Worker::new(
@@ -141,19 +133,13 @@ where
141
133
  rwi.into_core_worker()
142
134
  }
143
135
 
144
- pub(crate) fn init_worker_client<CT>(
145
- namespace: String,
136
+ pub(crate) fn init_worker_client(
137
+ connection: &mut Connection,
146
138
  client_identity_override: Option<String>,
147
- client: CT,
148
- ) -> Client
149
- where
150
- CT: Into<sealed::AnyClient>,
151
- {
152
- let mut client = Client::new(*client.into().into_inner(), namespace.clone());
139
+ ) {
153
140
  if let Some(ref id_override) = client_identity_override {
154
- client.options_mut().identity.clone_from(id_override);
141
+ connection.identity_mut().clone_from(id_override);
155
142
  }
156
- client
157
143
  }
158
144
 
159
145
  /// Creates a unique sticky queue name for a worker, iff the config allows for 1 or more cached
@@ -173,63 +159,6 @@ pub(crate) fn sticky_q_name_for_worker(
173
159
  }
174
160
  }
175
161
 
176
- mod sealed {
177
- use super::*;
178
- use temporalio_client::{SharedReplaceableClient, TemporalServiceClient};
179
-
180
- /// Allows passing different kinds of clients into things that want to be flexible. Motivating
181
- /// use-case was worker initialization.
182
- ///
183
- /// Needs to exist in this crate to avoid blanket impl conflicts.
184
- pub struct AnyClient {
185
- pub(crate) inner: Box<ConfiguredClient<TemporalServiceClient>>,
186
- }
187
- impl AnyClient {
188
- pub(crate) fn into_inner(self) -> Box<ConfiguredClient<TemporalServiceClient>> {
189
- self.inner
190
- }
191
- }
192
-
193
- impl From<ConfiguredClient<TemporalServiceClient>> for AnyClient {
194
- fn from(c: ConfiguredClient<TemporalServiceClient>) -> Self {
195
- Self { inner: Box::new(c) }
196
- }
197
- }
198
-
199
- impl From<Client> for AnyClient {
200
- fn from(c: Client) -> Self {
201
- c.into_inner().into()
202
- }
203
- }
204
-
205
- impl<T> From<RetryClient<T>> for AnyClient
206
- where
207
- T: Into<AnyClient>,
208
- {
209
- fn from(c: RetryClient<T>) -> Self {
210
- c.into_inner().into()
211
- }
212
- }
213
-
214
- impl<T> From<SharedReplaceableClient<T>> for AnyClient
215
- where
216
- T: Into<AnyClient> + Clone + Send + Sync,
217
- {
218
- fn from(c: SharedReplaceableClient<T>) -> Self {
219
- c.inner_clone().into()
220
- }
221
- }
222
-
223
- impl<T> From<Arc<T>> for AnyClient
224
- where
225
- T: Into<AnyClient> + Clone,
226
- {
227
- fn from(c: Arc<T>) -> Self {
228
- Arc::unwrap_or_clone(c).into()
229
- }
230
- }
231
- }
232
-
233
162
  /// Holds shared state/components needed to back instances of workers and clients. More than one
234
163
  /// may be instantiated, but typically only one is needed. More than one runtime instance may be
235
164
  /// useful if multiple different telemetry settings are required.
@@ -240,7 +169,8 @@ pub struct CoreRuntime {
240
169
  heartbeat_interval: Option<Duration>,
241
170
  }
242
171
 
243
- /// Holds telemetry options, as well as worker heartbeat_interval. Construct with [RuntimeOptions::builder]
172
+ /// Holds telemetry options, as well as worker heartbeat_interval. Construct with
173
+ /// [RuntimeOptions::builder]
244
174
  #[derive(Default, bon::Builder)]
245
175
  #[builder(finish_fn(vis = "", name = build_internal))]
246
176
  #[non_exhaustive]
@@ -3,23 +3,18 @@ mod poll_buffer;
3
3
  pub(crate) use poll_buffer::{
4
4
  ActivityTaskOptions, LongPollBuffer, WorkflowTaskOptions, WorkflowTaskPoller,
5
5
  };
6
- pub use temporalio_client::{
7
- Client, ClientOptions, ClientTlsOptions, RetryClient, RetryOptions, TlsOptions,
8
- WorkflowClientTrait,
9
- };
6
+ pub use temporalio_client::{Client, ClientOptions, ClientTlsOptions, RetryOptions, TlsOptions};
10
7
 
11
8
  use crate::{
12
9
  abstractions::{OwnedMeteredSemPermit, TrackedOwnedMeteredSemPermit},
13
10
  telemetry::metrics::MetricsContext,
11
+ worker::{ActivitySlotKind, NexusSlotKind, SlotKind, WorkflowSlotKind},
14
12
  };
15
13
  use anyhow::{anyhow, bail};
16
14
  use futures_util::{Stream, stream};
17
15
  use std::{fmt::Debug, marker::PhantomData};
18
- use temporalio_common::{
19
- protos::temporal::api::workflowservice::v1::{
20
- PollActivityTaskQueueResponse, PollNexusTaskQueueResponse, PollWorkflowTaskQueueResponse,
21
- },
22
- worker::{ActivitySlotKind, NexusSlotKind, SlotKind, WorkflowSlotKind},
16
+ use temporalio_common::protos::temporal::api::workflowservice::v1::{
17
+ PollActivityTaskQueueResponse, PollNexusTaskQueueResponse, PollWorkflowTaskQueueResponse,
23
18
  };
24
19
  use tokio::select;
25
20
  use tokio_util::sync::CancellationToken;
@@ -2,7 +2,8 @@ use crate::{
2
2
  abstractions::{ActiveCounter, MeteredPermitDealer, OwnedMeteredSemPermit, dbg_panic},
3
3
  pollers::{self, Poller},
4
4
  worker::{
5
- WFTPollerShared,
5
+ ActivitySlotKind, NexusSlotKind, PollerBehavior, SlotKind, WFTPollerShared,
6
+ WorkflowSlotKind,
6
7
  client::{PollActivityOptions, PollOptions, PollWorkflowOptions, WorkerClient},
7
8
  },
8
9
  };
@@ -23,15 +24,11 @@ use std::{
23
24
  use temporalio_client::{
24
25
  ERROR_RETURNED_DUE_TO_SHORT_CIRCUIT, request_extensions::NoRetryOnMatching,
25
26
  };
26
- use temporalio_common::{
27
- protos::temporal::api::{
28
- taskqueue::v1::PollerScalingDecision,
29
- workflowservice::v1::{
30
- PollActivityTaskQueueResponse, PollNexusTaskQueueResponse,
31
- PollWorkflowTaskQueueResponse,
32
- },
27
+ use temporalio_common::protos::temporal::api::{
28
+ taskqueue::v1::PollerScalingDecision,
29
+ workflowservice::v1::{
30
+ PollActivityTaskQueueResponse, PollNexusTaskQueueResponse, PollWorkflowTaskQueueResponse,
33
31
  },
34
- worker::{ActivitySlotKind, NexusSlotKind, PollerBehavior, SlotKind, WorkflowSlotKind},
35
32
  };
36
33
  use tokio::{
37
34
  sync::{
@@ -80,6 +77,7 @@ impl LongPollBuffer<PollWorkflowTaskQueueResponse, WorkflowSlotKind> {
80
77
  num_pollers_handler: Option<impl Fn(usize) + Send + Sync + 'static>,
81
78
  options: WorkflowTaskOptions,
82
79
  last_successful_poll_time: Arc<AtomicCell<Option<SystemTime>>>,
80
+ graceful_poll_shutdown: Arc<AtomicBool>,
83
81
  ) -> Self {
84
82
  let is_sticky = sticky_queue.is_some();
85
83
  let poll_scaler = PollScaler::new(
@@ -142,6 +140,7 @@ impl LongPollBuffer<PollWorkflowTaskQueueResponse, WorkflowSlotKind> {
142
140
  poll_scaler,
143
141
  pre_permit_delay,
144
142
  post_poll_fn,
143
+ graceful_poll_shutdown,
145
144
  )
146
145
  }
147
146
  }
@@ -157,6 +156,7 @@ impl LongPollBuffer<PollActivityTaskQueueResponse, ActivitySlotKind> {
157
156
  num_pollers_handler: Option<impl Fn(usize) + Send + Sync + 'static>,
158
157
  options: ActivityTaskOptions,
159
158
  last_successful_poll_time: Arc<AtomicCell<Option<SystemTime>>>,
159
+ graceful_poll_shutdown: Arc<AtomicBool>,
160
160
  ) -> Self {
161
161
  let pre_permit_delay = options
162
162
  .max_worker_acts_per_second
@@ -209,6 +209,7 @@ impl LongPollBuffer<PollActivityTaskQueueResponse, ActivitySlotKind> {
209
209
  poll_scaler,
210
210
  pre_permit_delay,
211
211
  None::<fn(&PollActivityTaskQueueResponse)>,
212
+ graceful_poll_shutdown,
212
213
  )
213
214
  }
214
215
  }
@@ -224,6 +225,7 @@ impl LongPollBuffer<PollNexusTaskQueueResponse, NexusSlotKind> {
224
225
  num_pollers_handler: Option<impl Fn(usize) + Send + Sync + 'static>,
225
226
  last_successful_poll_time: Arc<AtomicCell<Option<SystemTime>>>,
226
227
  send_heartbeat: bool,
228
+ graceful_poll_shutdown: Arc<AtomicBool>,
227
229
  ) -> Self {
228
230
  let no_retry = if matches!(poller_behavior, PollerBehavior::Autoscaling { .. }) {
229
231
  Some(NoRetryOnMatching {
@@ -260,12 +262,13 @@ impl LongPollBuffer<PollNexusTaskQueueResponse, NexusSlotKind> {
260
262
  ),
261
263
  None::<fn() -> BoxFuture<'static, ()>>,
262
264
  None::<fn(&PollNexusTaskQueueResponse)>,
265
+ graceful_poll_shutdown,
263
266
  )
264
267
  }
265
268
  }
266
269
 
267
270
  // Simple way to test this w/o plumbing options through. This will be removed after
268
- // the proper server implementation for teminating polls on worker shutdown exists.
271
+ // the proper server implementation for terminating polls on worker shutdown exists.
269
272
  #[cfg(test)]
270
273
  use std::cell::RefCell;
271
274
  #[cfg(test)]
@@ -285,6 +288,7 @@ where
285
288
  mut poll_scaler: PollScaler<F>,
286
289
  pre_permit_delay: Option<impl Fn() -> DelayFut + Send + Sync + 'static>,
287
290
  post_poll_fn: Option<impl Fn(&T) + Send + Sync + 'static>,
291
+ graceful_shutdown: Arc<AtomicBool>,
288
292
  ) -> Self
289
293
  where
290
294
  FT: Future<Output = pollers::Result<T>> + Send,
@@ -355,19 +359,22 @@ where
355
359
  } else {
356
360
  None
357
361
  };
362
+ let graceful_shutdown = graceful_shutdown.clone();
358
363
  let poll_task = tokio::spawn(async move {
359
364
  let shutdown_clone = shutdown.clone();
360
365
 
361
- // If the interrupt wait is specified, don't resolve the future that would
362
- // interrupt the poll until after the wait period.
363
- let poll_interruptor = shutdown.cancelled().then(|_| async move {
364
- if let Some(w) = poll_shutdown_interrupt_wait {
365
- tokio::time::sleep(w).await;
366
+ let r = if graceful_shutdown.load(Ordering::Relaxed) {
367
+ pf(timeout_override).await
368
+ } else {
369
+ let poll_interruptor = shutdown.cancelled().then(|_| async move {
370
+ if let Some(w) = poll_shutdown_interrupt_wait {
371
+ tokio::time::sleep(w).await;
372
+ }
373
+ });
374
+ tokio::select! {
375
+ r = pf(timeout_override) => r,
376
+ _ = poll_interruptor => return,
366
377
  }
367
- });
368
- let r = tokio::select! {
369
- r = pf(timeout_override) => r,
370
- _ = poll_interruptor => return,
371
378
  };
372
379
  if let Ok(r) = &r
373
380
  && let Some(ppf) = post_pf.as_ref()
@@ -846,6 +853,7 @@ mod tests {
846
853
  wft_poller_shared: Some(Arc::new(WFTPollerShared::new(Some(10)))),
847
854
  },
848
855
  Arc::new(AtomicCell::new(None)),
856
+ Arc::new(AtomicBool::new(false)),
849
857
  );
850
858
 
851
859
  // Poll a bunch of times, "interrupting" it each time, we should only actually have polled
@@ -902,6 +910,7 @@ mod tests {
902
910
  wft_poller_shared: Some(Arc::new(WFTPollerShared::new(Some(1)))),
903
911
  },
904
912
  Arc::new(AtomicCell::new(None)),
913
+ Arc::new(AtomicBool::new(false)),
905
914
  );
906
915
 
907
916
  // Should not see error, unwraps should get empty response
@@ -978,6 +987,7 @@ mod tests {
978
987
  wft_poller_shared: Some(Arc::new(WFTPollerShared::new(Some(10)))),
979
988
  },
980
989
  Arc::new(AtomicCell::new(None)),
990
+ Arc::new(AtomicBool::new(false)),
981
991
  );
982
992
 
983
993
  let first_task = pb.poll().await.expect("Should get first task");
@@ -1083,6 +1093,7 @@ mod tests {
1083
1093
  wft_poller_shared: Some(Arc::new(WFTPollerShared::new(Some(10)))),
1084
1094
  },
1085
1095
  Arc::new(AtomicCell::new(None)),
1096
+ Arc::new(AtomicBool::new(false)),
1086
1097
  ));
1087
1098
 
1088
1099
  // Trigger the first poll to initialize and get the scaling decision
@@ -1111,4 +1122,92 @@ mod tests {
1111
1122
  .shutdown()
1112
1123
  .await;
1113
1124
  }
1125
+
1126
+ #[rstest]
1127
+ #[case::graceful(true)]
1128
+ #[case::legacy(false)]
1129
+ #[tokio::test]
1130
+ async fn inflight_poll_survives_shutdown_only_when_graceful(#[case] graceful: bool) {
1131
+ let mut mock_client = mock_manual_worker_client();
1132
+ let task_started = Arc::new(Notify::new());
1133
+ let task_started_clone = task_started.clone();
1134
+ let task_complete = Arc::new(Notify::new());
1135
+ let task_complete_clone = task_complete.clone();
1136
+ let call_count = Arc::new(AtomicUsize::new(0));
1137
+ let call_count_clone = call_count.clone();
1138
+
1139
+ mock_client
1140
+ .expect_poll_workflow_task()
1141
+ .returning(move |_, _| {
1142
+ let count = call_count_clone.fetch_add(1, Ordering::SeqCst);
1143
+ let started = task_started_clone.clone();
1144
+ let complete = task_complete_clone.clone();
1145
+ async move {
1146
+ match count {
1147
+ 0 => Ok(PollWorkflowTaskQueueResponse {
1148
+ task_token: vec![1],
1149
+ ..Default::default()
1150
+ }),
1151
+ _ => {
1152
+ started.notify_one();
1153
+ complete.notified().await;
1154
+ Ok(PollWorkflowTaskQueueResponse {
1155
+ task_token: vec![2],
1156
+ ..Default::default()
1157
+ })
1158
+ }
1159
+ }
1160
+ }
1161
+ .boxed()
1162
+ });
1163
+
1164
+ let shutdown_token = CancellationToken::new();
1165
+ let pb = LongPollBuffer::new_workflow_task(
1166
+ Arc::new(mock_client),
1167
+ "sometq".to_string(),
1168
+ None,
1169
+ PollerBehavior::SimpleMaximum(1),
1170
+ fixed_size_permit_dealer(10),
1171
+ shutdown_token.clone(),
1172
+ None::<fn(usize)>,
1173
+ WorkflowTaskOptions {
1174
+ wft_poller_shared: None,
1175
+ },
1176
+ Arc::new(AtomicCell::new(None)),
1177
+ Arc::new(AtomicBool::new(graceful)),
1178
+ );
1179
+
1180
+ let first = pb.poll().await.unwrap().unwrap();
1181
+ assert_eq!(first.0.task_token, vec![1]);
1182
+
1183
+ // Wait for second poll to be in-flight
1184
+ task_started.notified().await;
1185
+
1186
+ shutdown_token.cancel();
1187
+
1188
+ if graceful {
1189
+ // Release the poll — simulates server returning empty after ShutdownWorker
1190
+ task_complete.notify_one();
1191
+
1192
+ // Graceful: in-flight poll survives, second task is received
1193
+ let second = tokio::time::timeout(Duration::from_secs(2), pb.poll())
1194
+ .await
1195
+ .expect("graceful poll should complete")
1196
+ .unwrap()
1197
+ .unwrap();
1198
+ assert_eq!(second.0.task_token, vec![2]);
1199
+ } else {
1200
+ // Don't release — the poll should be killed by shutdown token before completing.
1201
+ // Buffer drains to None because the killed poll sends no result.
1202
+ let result = tokio::time::timeout(Duration::from_secs(2), pb.poll())
1203
+ .await
1204
+ .expect("legacy poll should resolve quickly");
1205
+ assert!(
1206
+ result.is_none(),
1207
+ "Legacy shutdown should kill in-flight poll, buffer returns None"
1208
+ );
1209
+ }
1210
+
1211
+ pb.shutdown().await;
1212
+ }
1114
1213
  }
@@ -1,10 +1,10 @@
1
1
  pub(crate) mod protocol_messages;
2
2
 
3
3
  use crate::{
4
- CompleteActivityError, TaskToken,
4
+ TaskToken,
5
5
  protosext::protocol_messages::IncomingProtocolMessage,
6
6
  retry_logic::ValidatedRetryPolicy,
7
- worker::{LEGACY_QUERY_ID, LocalActivityExecutionResult},
7
+ worker::{CompleteActivityError, LEGACY_QUERY_ID, LocalActivityExecutionResult},
8
8
  };
9
9
  use anyhow::anyhow;
10
10
  use itertools::Itertools;
@@ -3,9 +3,9 @@
3
3
  //! users during testing.
4
4
 
5
5
  use crate::{
6
- Worker,
6
+ Worker, WorkerConfig,
7
7
  worker::{
8
- PostActivateHookData,
8
+ PollerBehavior, PostActivateHookData,
9
9
  client::mocks::{MockManualWorkerClient, mock_manual_worker_client},
10
10
  },
11
11
  };
@@ -30,7 +30,7 @@ use temporalio_common::{
30
30
  },
31
31
  },
32
32
  },
33
- worker::{PollerBehavior, WorkerConfig, WorkerTaskTypes},
33
+ worker::WorkerTaskTypes,
34
34
  };
35
35
  use tokio::sync::{Mutex as TokioMutex, mpsc, mpsc::UnboundedSender};
36
36
  use tokio_stream::wrappers::UnboundedReceiverStream;
@@ -126,11 +126,20 @@ where
126
126
 
127
127
  /// A history which will be used during replay verification. Since histories do not include the
128
128
  /// workflow id, it must be manually attached.
129
- #[derive(Debug, Clone, derive_more::Constructor)]
129
+ #[derive(Debug, Clone)]
130
130
  pub struct HistoryForReplay {
131
131
  hist: History,
132
132
  workflow_id: String,
133
133
  }
134
+ impl HistoryForReplay {
135
+ /// Create a new history from replay from something that looks like a history and a workflow id.
136
+ pub fn new(history: impl Into<History>, workflow_id: impl Into<String>) -> Self {
137
+ Self {
138
+ hist: history.into(),
139
+ workflow_id: workflow_id.into(),
140
+ }
141
+ }
142
+ }
134
143
  impl From<TestHistoryBuilder> for HistoryForReplay {
135
144
  fn from(thb: TestHistoryBuilder) -> Self {
136
145
  thb.get_full_history_info().unwrap().into()
@@ -138,7 +147,7 @@ impl From<TestHistoryBuilder> for HistoryForReplay {
138
147
  }
139
148
  impl From<HistoryInfo> for HistoryForReplay {
140
149
  fn from(histinfo: HistoryInfo) -> Self {
141
- HistoryForReplay::new(histinfo.into(), "fake".to_owned())
150
+ HistoryForReplay::new(histinfo, "fake".to_owned())
142
151
  }
143
152
  }
144
153