@temporalio/core-bridge 1.13.0 → 1.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/Cargo.lock +239 -382
  2. package/Cargo.toml +11 -11
  3. package/lib/native.d.ts +10 -3
  4. package/package.json +3 -3
  5. package/releases/aarch64-apple-darwin/index.node +0 -0
  6. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  7. package/releases/x86_64-apple-darwin/index.node +0 -0
  8. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  9. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  10. package/sdk-core/.cargo/config.toml +71 -11
  11. package/sdk-core/.clippy.toml +1 -0
  12. package/sdk-core/.github/workflows/heavy.yml +2 -0
  13. package/sdk-core/.github/workflows/per-pr.yml +50 -18
  14. package/sdk-core/ARCHITECTURE.md +44 -48
  15. package/sdk-core/Cargo.toml +26 -7
  16. package/sdk-core/README.md +4 -0
  17. package/sdk-core/arch_docs/diagrams/TimerMachine_Coverage.puml +14 -0
  18. package/sdk-core/arch_docs/diagrams/initial_event_history.png +0 -0
  19. package/sdk-core/arch_docs/sdks_intro.md +299 -0
  20. package/sdk-core/client/Cargo.toml +8 -7
  21. package/sdk-core/client/src/callback_based.rs +1 -2
  22. package/sdk-core/client/src/lib.rs +485 -299
  23. package/sdk-core/client/src/metrics.rs +32 -8
  24. package/sdk-core/client/src/proxy.rs +124 -5
  25. package/sdk-core/client/src/raw.rs +598 -307
  26. package/sdk-core/client/src/replaceable.rs +253 -0
  27. package/sdk-core/client/src/retry.rs +9 -6
  28. package/sdk-core/client/src/worker_registry/mod.rs +19 -3
  29. package/sdk-core/client/src/workflow_handle/mod.rs +20 -17
  30. package/sdk-core/core/Cargo.toml +100 -31
  31. package/sdk-core/core/src/core_tests/activity_tasks.rs +55 -225
  32. package/sdk-core/core/src/core_tests/mod.rs +2 -8
  33. package/sdk-core/core/src/core_tests/queries.rs +3 -5
  34. package/sdk-core/core/src/core_tests/replay_flag.rs +3 -62
  35. package/sdk-core/core/src/core_tests/updates.rs +4 -5
  36. package/sdk-core/core/src/core_tests/workers.rs +4 -3
  37. package/sdk-core/core/src/core_tests/workflow_cancels.rs +10 -7
  38. package/sdk-core/core/src/core_tests/workflow_tasks.rs +28 -291
  39. package/sdk-core/core/src/ephemeral_server/mod.rs +15 -3
  40. package/sdk-core/core/src/internal_flags.rs +11 -1
  41. package/sdk-core/core/src/lib.rs +50 -36
  42. package/sdk-core/core/src/pollers/mod.rs +5 -5
  43. package/sdk-core/core/src/pollers/poll_buffer.rs +2 -2
  44. package/sdk-core/core/src/protosext/mod.rs +13 -5
  45. package/sdk-core/core/src/protosext/protocol_messages.rs +4 -11
  46. package/sdk-core/core/src/retry_logic.rs +256 -108
  47. package/sdk-core/core/src/telemetry/metrics.rs +1 -0
  48. package/sdk-core/core/src/telemetry/mod.rs +8 -2
  49. package/sdk-core/core/src/telemetry/prometheus_meter.rs +2 -2
  50. package/sdk-core/core/src/test_help/integ_helpers.rs +971 -0
  51. package/sdk-core/core/src/test_help/mod.rs +10 -1100
  52. package/sdk-core/core/src/test_help/unit_helpers.rs +218 -0
  53. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +42 -6
  54. package/sdk-core/core/src/worker/activities/local_activities.rs +19 -19
  55. package/sdk-core/core/src/worker/activities.rs +10 -3
  56. package/sdk-core/core/src/worker/client/mocks.rs +3 -3
  57. package/sdk-core/core/src/worker/client.rs +130 -93
  58. package/sdk-core/core/src/worker/heartbeat.rs +12 -13
  59. package/sdk-core/core/src/worker/mod.rs +31 -21
  60. package/sdk-core/core/src/worker/nexus.rs +14 -3
  61. package/sdk-core/core/src/worker/slot_provider.rs +9 -0
  62. package/sdk-core/core/src/worker/tuner.rs +159 -0
  63. package/sdk-core/core/src/worker/workflow/history_update.rs +3 -265
  64. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -54
  65. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +0 -82
  66. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +0 -67
  67. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -192
  68. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +0 -43
  69. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +6 -554
  70. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -71
  71. package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +102 -3
  72. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +10 -539
  73. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +0 -139
  74. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -119
  75. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +6 -63
  76. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +9 -4
  77. package/sdk-core/core/src/worker/workflow/mod.rs +5 -1
  78. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +8 -3
  79. package/sdk-core/core-api/Cargo.toml +4 -4
  80. package/sdk-core/core-api/src/envconfig.rs +153 -54
  81. package/sdk-core/core-api/src/lib.rs +68 -0
  82. package/sdk-core/core-api/src/telemetry/metrics.rs +2 -1
  83. package/sdk-core/core-api/src/telemetry.rs +13 -0
  84. package/sdk-core/core-c-bridge/Cargo.toml +13 -8
  85. package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +184 -22
  86. package/sdk-core/core-c-bridge/src/client.rs +462 -184
  87. package/sdk-core/core-c-bridge/src/envconfig.rs +314 -0
  88. package/sdk-core/core-c-bridge/src/lib.rs +1 -0
  89. package/sdk-core/core-c-bridge/src/random.rs +4 -4
  90. package/sdk-core/core-c-bridge/src/runtime.rs +22 -23
  91. package/sdk-core/core-c-bridge/src/testing.rs +1 -4
  92. package/sdk-core/core-c-bridge/src/tests/context.rs +31 -31
  93. package/sdk-core/core-c-bridge/src/tests/mod.rs +32 -28
  94. package/sdk-core/core-c-bridge/src/tests/utils.rs +7 -7
  95. package/sdk-core/core-c-bridge/src/worker.rs +319 -66
  96. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -1
  97. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +5 -5
  98. package/sdk-core/sdk/Cargo.toml +8 -2
  99. package/sdk-core/sdk/src/activity_context.rs +1 -1
  100. package/sdk-core/sdk/src/app_data.rs +1 -1
  101. package/sdk-core/sdk/src/interceptors.rs +1 -4
  102. package/sdk-core/sdk/src/lib.rs +1 -5
  103. package/sdk-core/sdk/src/workflow_context/options.rs +10 -1
  104. package/sdk-core/sdk/src/workflow_future.rs +1 -1
  105. package/sdk-core/sdk-core-protos/Cargo.toml +6 -6
  106. package/sdk-core/sdk-core-protos/build.rs +10 -23
  107. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +9 -1
  108. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +254 -5
  109. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +234 -5
  110. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +1 -1
  111. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +6 -0
  112. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -2
  113. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -2
  114. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -6
  115. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  116. package/sdk-core/{test-utils → sdk-core-protos}/src/canned_histories.rs +5 -5
  117. package/sdk-core/sdk-core-protos/src/history_builder.rs +2 -2
  118. package/sdk-core/sdk-core-protos/src/lib.rs +25 -9
  119. package/sdk-core/sdk-core-protos/src/test_utils.rs +89 -0
  120. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -5
  121. package/sdk-core/tests/c_bridge_smoke_test.c +10 -0
  122. package/sdk-core/tests/cloud_tests.rs +10 -8
  123. package/sdk-core/tests/common/http_proxy.rs +134 -0
  124. package/sdk-core/{test-utils/src/lib.rs → tests/common/mod.rs} +214 -281
  125. package/sdk-core/{test-utils/src → tests/common}/workflows.rs +4 -3
  126. package/sdk-core/tests/fuzzy_workflow.rs +1 -1
  127. package/sdk-core/tests/global_metric_tests.rs +8 -7
  128. package/sdk-core/tests/heavy_tests.rs +7 -3
  129. package/sdk-core/tests/integ_tests/client_tests.rs +111 -24
  130. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +14 -9
  131. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +4 -4
  132. package/sdk-core/tests/integ_tests/metrics_tests.rs +114 -14
  133. package/sdk-core/tests/integ_tests/pagination_tests.rs +273 -0
  134. package/sdk-core/tests/integ_tests/polling_tests.rs +311 -93
  135. package/sdk-core/tests/integ_tests/queries_tests.rs +4 -4
  136. package/sdk-core/tests/integ_tests/update_tests.rs +13 -7
  137. package/sdk-core/tests/integ_tests/visibility_tests.rs +26 -9
  138. package/sdk-core/tests/integ_tests/worker_tests.rs +668 -13
  139. package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +40 -24
  140. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +244 -11
  141. package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +1 -1
  142. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +78 -2
  143. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +61 -2
  144. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +465 -7
  145. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +41 -2
  146. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +315 -3
  147. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
  148. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1990 -14
  149. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +65 -2
  150. package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +123 -23
  151. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +525 -3
  152. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +65 -16
  153. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +32 -23
  154. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +126 -5
  155. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +1 -2
  156. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +124 -8
  157. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +62 -2
  158. package/sdk-core/tests/integ_tests/workflow_tests.rs +67 -8
  159. package/sdk-core/tests/main.rs +26 -17
  160. package/sdk-core/tests/manual_tests.rs +5 -1
  161. package/sdk-core/tests/runner.rs +22 -40
  162. package/sdk-core/tests/shared_tests/mod.rs +1 -1
  163. package/sdk-core/tests/shared_tests/priority.rs +1 -1
  164. package/sdk-core/{core/benches/workflow_replay.rs → tests/workflow_replay_bench.rs} +10 -5
  165. package/src/client.rs +97 -20
  166. package/src/helpers/callbacks.rs +4 -4
  167. package/src/helpers/errors.rs +7 -1
  168. package/src/helpers/handles.rs +1 -0
  169. package/src/helpers/try_from_js.rs +4 -3
  170. package/src/lib.rs +3 -2
  171. package/src/metrics.rs +3 -0
  172. package/src/runtime.rs +5 -2
  173. package/src/worker.rs +9 -12
  174. package/ts/native.ts +13 -3
  175. package/sdk-core/arch_docs/diagrams/workflow_internals.svg +0 -1
  176. package/sdk-core/core/src/core_tests/child_workflows.rs +0 -281
  177. package/sdk-core/core/src/core_tests/determinism.rs +0 -318
  178. package/sdk-core/core/src/core_tests/local_activities.rs +0 -1442
  179. package/sdk-core/test-utils/Cargo.toml +0 -38
  180. package/sdk-core/test-utils/src/histfetch.rs +0 -28
  181. package/sdk-core/test-utils/src/interceptors.rs +0 -46
@@ -1,18 +1,18 @@
1
1
  //! Worker-specific client needs
2
2
 
3
3
  pub(crate) mod mocks;
4
- use crate::abstractions::dbg_panic;
5
- use crate::protosext::legacy_query_failure;
6
- use crate::worker::heartbeat::HeartbeatFn;
7
- use parking_lot::RwLock;
8
- use std::sync::OnceLock;
9
- use std::{sync::Arc, time::Duration};
4
+ use crate::{
5
+ abstractions::dbg_panic, protosext::legacy_query_failure, worker::heartbeat::HeartbeatFn,
6
+ };
7
+ use std::{
8
+ sync::{Arc, OnceLock},
9
+ time::Duration,
10
+ };
10
11
  use temporal_client::{
11
12
  Client, IsWorkerTaskLongPoll, Namespace, NamespacedClient, NoRetryOnMatching, RetryClient,
12
- SlotManager, WorkflowService,
13
+ SharedReplaceableClient, SlotManager, WorkflowService,
13
14
  };
14
15
  use temporal_sdk_core_api::worker::WorkerVersioningStrategy;
15
- use temporal_sdk_core_protos::temporal::api::worker::v1::WorkerHeartbeat;
16
16
  use temporal_sdk_core_protos::{
17
17
  TaskToken,
18
18
  coresdk::{workflow_commands::QueryResult, workflow_completion},
@@ -32,6 +32,7 @@ use temporal_sdk_core_protos::{
32
32
  query::v1::WorkflowQueryResult,
33
33
  sdk::v1::WorkflowTaskCompletedMetadata,
34
34
  taskqueue::v1::{StickyExecutionAttributes, TaskQueue, TaskQueueMetadata},
35
+ worker::v1::WorkerHeartbeat,
35
36
  workflowservice::v1::{get_system_info_response::Capabilities, *},
36
37
  },
37
38
  };
@@ -46,7 +47,7 @@ pub enum LegacyQueryResult {
46
47
 
47
48
  /// Contains everything a worker needs to interact with the server
48
49
  pub(crate) struct WorkerClientBag {
49
- replaceable_client: RwLock<RetryClient<Client>>,
50
+ client: RetryClient<SharedReplaceableClient<Client>>,
50
51
  namespace: String,
51
52
  identity: String,
52
53
  worker_versioning_strategy: WorkerVersioningStrategy,
@@ -55,14 +56,14 @@ pub(crate) struct WorkerClientBag {
55
56
 
56
57
  impl WorkerClientBag {
57
58
  pub(crate) fn new(
58
- client: RetryClient<Client>,
59
+ client: RetryClient<SharedReplaceableClient<Client>>,
59
60
  namespace: String,
60
61
  identity: String,
61
62
  worker_versioning_strategy: WorkerVersioningStrategy,
62
63
  heartbeat_data: Option<Arc<OnceLock<HeartbeatFn>>>,
63
64
  ) -> Self {
64
65
  Self {
65
- replaceable_client: RwLock::new(client),
66
+ client,
66
67
  namespace,
67
68
  identity,
68
69
  worker_versioning_strategy,
@@ -70,10 +71,6 @@ impl WorkerClientBag {
70
71
  }
71
72
  }
72
73
 
73
- fn cloned_client(&self) -> RetryClient<Client> {
74
- self.replaceable_client.read().clone()
75
- }
76
-
77
74
  fn default_capabilities(&self) -> Capabilities {
78
75
  self.capabilities().unwrap_or_default()
79
76
  }
@@ -144,7 +141,7 @@ impl WorkerClientBag {
144
141
 
145
142
  /// This trait contains everything workers need to interact with Temporal, and hence provides a
146
143
  /// minimal mocking surface. Delegates to [WorkflowClientTrait] so see that for details.
147
- #[cfg_attr(test, mockall::automock)]
144
+ #[cfg_attr(any(feature = "test-utilities", test), mockall::automock)]
148
145
  #[async_trait::async_trait]
149
146
  pub trait WorkerClient: Sync + Send {
150
147
  /// Poll workflow tasks
@@ -236,7 +233,7 @@ pub trait WorkerClient: Sync + Send {
236
233
  ) -> Result<RecordWorkerHeartbeatResponse>;
237
234
 
238
235
  /// Replace the underlying client
239
- fn replace_client(&self, new_client: RetryClient<Client>);
236
+ fn replace_client(&self, new_client: Client);
240
237
  /// Return server capabilities
241
238
  fn capabilities(&self) -> Option<Capabilities>;
242
239
  /// Return workers using this client
@@ -312,7 +309,8 @@ impl WorkerClient for WorkerClientBag {
312
309
  }
313
310
 
314
311
  Ok(self
315
- .cloned_client()
312
+ .client
313
+ .clone()
316
314
  .poll_workflow_task_queue(request)
317
315
  .await?
318
316
  .into_inner())
@@ -349,7 +347,8 @@ impl WorkerClient for WorkerClientBag {
349
347
  }
350
348
 
351
349
  Ok(self
352
- .cloned_client()
350
+ .client
351
+ .clone()
353
352
  .poll_activity_task_queue(request)
354
353
  .await?
355
354
  .into_inner())
@@ -382,7 +381,8 @@ impl WorkerClient for WorkerClientBag {
382
381
  }
383
382
 
384
383
  Ok(self
385
- .cloned_client()
384
+ .client
385
+ .clone()
386
386
  .poll_nexus_task_queue(request)
387
387
  .await?
388
388
  .into_inner())
@@ -432,8 +432,9 @@ impl WorkerClient for WorkerClientBag {
432
432
  deployment_options: self.deployment_options(),
433
433
  };
434
434
  Ok(self
435
- .cloned_client()
436
- .respond_workflow_task_completed(request)
435
+ .client
436
+ .clone()
437
+ .respond_workflow_task_completed(request.into_request())
437
438
  .await?
438
439
  .into_inner())
439
440
  }
@@ -444,7 +445,8 @@ impl WorkerClient for WorkerClientBag {
444
445
  result: Option<Payloads>,
445
446
  ) -> Result<RespondActivityTaskCompletedResponse> {
446
447
  Ok(self
447
- .cloned_client()
448
+ .client
449
+ .clone()
448
450
  .respond_activity_task_completed(
449
451
  #[allow(deprecated)] // want to list all fields explicitly
450
452
  RespondActivityTaskCompletedRequest {
@@ -456,7 +458,8 @@ impl WorkerClient for WorkerClientBag {
456
458
  // Will never be set, deprecated.
457
459
  deployment: None,
458
460
  deployment_options: self.deployment_options(),
459
- },
461
+ }
462
+ .into_request(),
460
463
  )
461
464
  .await?
462
465
  .into_inner())
@@ -468,13 +471,17 @@ impl WorkerClient for WorkerClientBag {
468
471
  response: nexus::v1::Response,
469
472
  ) -> Result<RespondNexusTaskCompletedResponse> {
470
473
  Ok(self
471
- .cloned_client()
472
- .respond_nexus_task_completed(RespondNexusTaskCompletedRequest {
473
- namespace: self.namespace.clone(),
474
- identity: self.identity.clone(),
475
- task_token: task_token.0,
476
- response: Some(response),
477
- })
474
+ .client
475
+ .clone()
476
+ .respond_nexus_task_completed(
477
+ RespondNexusTaskCompletedRequest {
478
+ namespace: self.namespace.clone(),
479
+ identity: self.identity.clone(),
480
+ task_token: task_token.0,
481
+ response: Some(response),
482
+ }
483
+ .into_request(),
484
+ )
478
485
  .await?
479
486
  .into_inner())
480
487
  }
@@ -485,13 +492,17 @@ impl WorkerClient for WorkerClientBag {
485
492
  details: Option<Payloads>,
486
493
  ) -> Result<RecordActivityTaskHeartbeatResponse> {
487
494
  Ok(self
488
- .cloned_client()
489
- .record_activity_task_heartbeat(RecordActivityTaskHeartbeatRequest {
490
- task_token: task_token.0,
491
- details,
492
- identity: self.identity.clone(),
493
- namespace: self.namespace.clone(),
494
- })
495
+ .client
496
+ .clone()
497
+ .record_activity_task_heartbeat(
498
+ RecordActivityTaskHeartbeatRequest {
499
+ task_token: task_token.0,
500
+ details,
501
+ identity: self.identity.clone(),
502
+ namespace: self.namespace.clone(),
503
+ }
504
+ .into_request(),
505
+ )
495
506
  .await?
496
507
  .into_inner())
497
508
  }
@@ -502,7 +513,8 @@ impl WorkerClient for WorkerClientBag {
502
513
  details: Option<Payloads>,
503
514
  ) -> Result<RespondActivityTaskCanceledResponse> {
504
515
  Ok(self
505
- .cloned_client()
516
+ .client
517
+ .clone()
506
518
  .respond_activity_task_canceled(
507
519
  #[allow(deprecated)] // want to list all fields explicitly
508
520
  RespondActivityTaskCanceledRequest {
@@ -514,7 +526,8 @@ impl WorkerClient for WorkerClientBag {
514
526
  // Will never be set, deprecated.
515
527
  deployment: None,
516
528
  deployment_options: self.deployment_options(),
517
- },
529
+ }
530
+ .into_request(),
518
531
  )
519
532
  .await?
520
533
  .into_inner())
@@ -526,7 +539,8 @@ impl WorkerClient for WorkerClientBag {
526
539
  failure: Option<Failure>,
527
540
  ) -> Result<RespondActivityTaskFailedResponse> {
528
541
  Ok(self
529
- .cloned_client()
542
+ .client
543
+ .clone()
530
544
  .respond_activity_task_failed(
531
545
  #[allow(deprecated)] // want to list all fields explicitly
532
546
  RespondActivityTaskFailedRequest {
@@ -540,7 +554,8 @@ impl WorkerClient for WorkerClientBag {
540
554
  // Will never be set, deprecated.
541
555
  deployment: None,
542
556
  deployment_options: self.deployment_options(),
543
- },
557
+ }
558
+ .into_request(),
544
559
  )
545
560
  .await?
546
561
  .into_inner())
@@ -567,8 +582,9 @@ impl WorkerClient for WorkerClientBag {
567
582
  deployment_options: self.deployment_options(),
568
583
  };
569
584
  Ok(self
570
- .cloned_client()
571
- .respond_workflow_task_failed(request)
585
+ .client
586
+ .clone()
587
+ .respond_workflow_task_failed(request.into_request())
572
588
  .await?
573
589
  .into_inner())
574
590
  }
@@ -579,13 +595,17 @@ impl WorkerClient for WorkerClientBag {
579
595
  error: nexus::v1::HandlerError,
580
596
  ) -> Result<RespondNexusTaskFailedResponse> {
581
597
  Ok(self
582
- .cloned_client()
583
- .respond_nexus_task_failed(RespondNexusTaskFailedRequest {
584
- namespace: self.namespace.clone(),
585
- identity: self.identity.clone(),
586
- task_token: task_token.0,
587
- error: Some(error),
588
- })
598
+ .client
599
+ .clone()
600
+ .respond_nexus_task_failed(
601
+ RespondNexusTaskFailedRequest {
602
+ namespace: self.namespace.clone(),
603
+ identity: self.identity.clone(),
604
+ task_token: task_token.0,
605
+ error: Some(error),
606
+ }
607
+ .into_request(),
608
+ )
589
609
  .await?
590
610
  .into_inner())
591
611
  }
@@ -597,16 +617,20 @@ impl WorkerClient for WorkerClientBag {
597
617
  page_token: Vec<u8>,
598
618
  ) -> Result<GetWorkflowExecutionHistoryResponse> {
599
619
  Ok(self
600
- .cloned_client()
601
- .get_workflow_execution_history(GetWorkflowExecutionHistoryRequest {
602
- namespace: self.namespace.clone(),
603
- execution: Some(WorkflowExecution {
604
- workflow_id,
605
- run_id: run_id.unwrap_or_default(),
606
- }),
607
- next_page_token: page_token,
608
- ..Default::default()
609
- })
620
+ .client
621
+ .clone()
622
+ .get_workflow_execution_history(
623
+ GetWorkflowExecutionHistoryRequest {
624
+ namespace: self.namespace.clone(),
625
+ execution: Some(WorkflowExecution {
626
+ workflow_id,
627
+ run_id: run_id.unwrap_or_default(),
628
+ }),
629
+ next_page_token: page_token,
630
+ ..Default::default()
631
+ }
632
+ .into_request(),
633
+ )
610
634
  .await?
611
635
  .into_inner())
612
636
  }
@@ -629,25 +653,32 @@ impl WorkerClient for WorkerClientBag {
629
653
  let (_, completed_type, query_result, error_message) = query_result.into_components();
630
654
 
631
655
  Ok(self
632
- .cloned_client()
633
- .respond_query_task_completed(RespondQueryTaskCompletedRequest {
634
- task_token: task_token.into(),
635
- completed_type: completed_type as i32,
636
- query_result,
637
- error_message,
638
- namespace: self.namespace.clone(),
639
- failure,
640
- cause: cause.into(),
641
- })
656
+ .client
657
+ .clone()
658
+ .respond_query_task_completed(
659
+ RespondQueryTaskCompletedRequest {
660
+ task_token: task_token.into(),
661
+ completed_type: completed_type as i32,
662
+ query_result,
663
+ error_message,
664
+ namespace: self.namespace.clone(),
665
+ failure,
666
+ cause: cause.into(),
667
+ }
668
+ .into_request(),
669
+ )
642
670
  .await?
643
671
  .into_inner())
644
672
  }
645
673
 
646
674
  async fn describe_namespace(&self) -> Result<DescribeNamespaceResponse> {
647
675
  Ok(self
648
- .cloned_client()
676
+ .client
677
+ .clone()
649
678
  .describe_namespace(
650
- Namespace::Name(self.namespace.clone()).into_describe_namespace_request(),
679
+ Namespace::Name(self.namespace.clone())
680
+ .into_describe_namespace_request()
681
+ .into_request(),
651
682
  )
652
683
  .await?
653
684
  .into_inner())
@@ -663,15 +694,14 @@ impl WorkerClient for WorkerClientBag {
663
694
  };
664
695
 
665
696
  Ok(
666
- WorkflowService::shutdown_worker(&mut self.cloned_client(), request)
697
+ WorkflowService::shutdown_worker(&mut self.client.clone(), request.into_request())
667
698
  .await?
668
699
  .into_inner(),
669
700
  )
670
701
  }
671
702
 
672
- fn replace_client(&self, new_client: RetryClient<Client>) {
673
- let mut replaceable_client = self.replaceable_client.write();
674
- *replaceable_client = new_client;
703
+ fn replace_client(&self, new_client: Client) {
704
+ self.client.get_client().replace_client(new_client);
675
705
  }
676
706
 
677
707
  async fn record_worker_heartbeat(
@@ -679,24 +709,31 @@ impl WorkerClient for WorkerClientBag {
679
709
  heartbeat: WorkerHeartbeat,
680
710
  ) -> Result<RecordWorkerHeartbeatResponse> {
681
711
  Ok(self
682
- .cloned_client()
683
- .record_worker_heartbeat(RecordWorkerHeartbeatRequest {
684
- namespace: self.namespace.clone(),
685
- identity: self.identity.clone(),
686
- worker_heartbeat: vec![heartbeat],
687
- })
712
+ .client
713
+ .clone()
714
+ .record_worker_heartbeat(
715
+ RecordWorkerHeartbeatRequest {
716
+ namespace: self.namespace.clone(),
717
+ identity: self.identity.clone(),
718
+ worker_heartbeat: vec![heartbeat],
719
+ }
720
+ .into_request(),
721
+ )
688
722
  .await?
689
723
  .into_inner())
690
724
  }
691
725
 
692
726
  fn capabilities(&self) -> Option<Capabilities> {
693
- let client = self.replaceable_client.read();
694
- client.get_client().inner().capabilities().cloned()
727
+ self.client
728
+ .get_client()
729
+ .inner_cow()
730
+ .inner()
731
+ .capabilities()
732
+ .cloned()
695
733
  }
696
734
 
697
735
  fn workers(&self) -> Arc<SlotManager> {
698
- let client = self.replaceable_client.read();
699
- client.get_client().inner().workers()
736
+ self.client.get_client().inner_cow().inner().workers()
700
737
  }
701
738
 
702
739
  fn is_mock(&self) -> bool {
@@ -704,8 +741,8 @@ impl WorkerClient for WorkerClientBag {
704
741
  }
705
742
 
706
743
  fn sdk_name_and_version(&self) -> (String, String) {
707
- let lock = self.replaceable_client.read();
708
- let opts = lock.get_client().inner().options();
744
+ let inner = self.client.get_client().inner_cow();
745
+ let opts = inner.options();
709
746
  (opts.client_name.clone(), opts.client_version.clone())
710
747
  }
711
748
 
@@ -715,12 +752,12 @@ impl WorkerClient for WorkerClientBag {
715
752
  }
716
753
 
717
754
  impl NamespacedClient for WorkerClientBag {
718
- fn namespace(&self) -> &str {
719
- &self.namespace
755
+ fn namespace(&self) -> String {
756
+ self.namespace.clone()
720
757
  }
721
758
 
722
- fn get_identity(&self) -> &str {
723
- &self.identity
759
+ fn identity(&self) -> String {
760
+ self.identity.clone()
724
761
  }
725
762
  }
726
763
 
@@ -1,15 +1,14 @@
1
- use crate::WorkerClient;
2
- use crate::abstractions::dbg_panic;
1
+ use crate::{WorkerClient, abstractions::dbg_panic};
3
2
  use gethostname::gethostname;
4
3
  use parking_lot::Mutex;
5
4
  use prost_types::Duration as PbDuration;
6
- use std::sync::{Arc, OnceLock};
7
- use std::time::{Duration, SystemTime};
5
+ use std::{
6
+ sync::{Arc, OnceLock},
7
+ time::{Duration, SystemTime},
8
+ };
8
9
  use temporal_sdk_core_api::worker::WorkerConfig;
9
10
  use temporal_sdk_core_protos::temporal::api::worker::v1::{WorkerHeartbeat, WorkerHostInfo};
10
- use tokio::sync::Notify;
11
- use tokio::task::JoinHandle;
12
- use tokio::time::MissedTickBehavior;
11
+ use tokio::{sync::Notify, task::JoinHandle, time::MissedTickBehavior};
13
12
  use uuid::Uuid;
14
13
 
15
14
  pub(crate) type HeartbeatFn = Box<dyn Fn() -> Option<WorkerHeartbeat> + Send + Sync>;
@@ -169,12 +168,12 @@ impl WorkerHeartbeatData {
169
168
  #[cfg(test)]
170
169
  mod tests {
171
170
  use super::*;
172
- use crate::test_help::WorkerExt;
173
- use crate::test_help::test_worker_cfg;
174
- use crate::worker;
175
- use crate::worker::client::mocks::mock_worker_client;
176
- use std::sync::Arc;
177
- use std::time::Duration;
171
+ use crate::{
172
+ test_help::{WorkerExt, test_worker_cfg},
173
+ worker,
174
+ worker::client::mocks::mock_worker_client,
175
+ };
176
+ use std::{sync::Arc, time::Duration};
178
177
  use temporal_sdk_core_api::worker::PollerBehavior;
179
178
  use temporal_sdk_core_protos::temporal::api::workflowservice::v1::RecordWorkerHeartbeatResponse;
180
179
 
@@ -18,15 +18,17 @@ pub(crate) use activities::{
18
18
  NewLocalAct,
19
19
  };
20
20
  pub(crate) use wft_poller::WFTPollerShared;
21
- pub(crate) use workflow::LEGACY_QUERY_ID;
22
21
 
23
- use crate::worker::heartbeat::{HeartbeatFn, WorkerHeartbeatManager};
22
+ #[allow(unreachable_pub)] // re-exported in test_help::integ_helpers
23
+ pub use workflow::LEGACY_QUERY_ID;
24
+
24
25
  use crate::{
25
26
  ActivityHeartbeat, CompleteActivityError, PollError, WorkerTrait,
26
27
  abstractions::{MeteredPermitDealer, PermitDealerContextData, dbg_panic},
27
28
  errors::CompleteWfError,
28
- pollers::{BoxedActPoller, BoxedNexusPoller},
29
+ pollers::{ActivityTaskOptions, BoxedActPoller, BoxedNexusPoller, LongPollBuffer},
29
30
  protosext::validate_activity_completion,
31
+ sealed::AnyClient,
30
32
  telemetry::{
31
33
  TelemetryInstance,
32
34
  metrics::{
@@ -37,31 +39,28 @@ use crate::{
37
39
  worker::{
38
40
  activities::{LACompleteAction, LocalActivityManager, NextPendingLAAction},
39
41
  client::WorkerClient,
42
+ heartbeat::{HeartbeatFn, WorkerHeartbeatManager},
40
43
  nexus::NexusManager,
41
44
  workflow::{
42
- LAReqSink, LocalResolution, WorkflowBasics, Workflows, wft_poller::make_wft_poller,
45
+ LAReqSink, LocalResolution, WorkflowBasics, Workflows, wft_poller,
46
+ wft_poller::make_wft_poller,
43
47
  },
44
48
  },
45
49
  };
46
- use crate::{
47
- pollers::{ActivityTaskOptions, LongPollBuffer},
48
- worker::workflow::wft_poller,
49
- };
50
50
  use activities::WorkerActivityTasks;
51
51
  use futures_util::{StreamExt, stream};
52
52
  use parking_lot::Mutex;
53
53
  use slot_provider::SlotProvider;
54
- use std::sync::OnceLock;
55
54
  use std::{
56
55
  convert::TryInto,
57
56
  future,
58
57
  sync::{
59
- Arc,
58
+ Arc, OnceLock,
60
59
  atomic::{AtomicBool, Ordering},
61
60
  },
62
61
  time::Duration,
63
62
  };
64
- use temporal_client::{ConfiguredClient, TemporalServiceClientWithMetrics, WorkerKey};
63
+ use temporal_client::WorkerKey;
65
64
  use temporal_sdk_core_api::{
66
65
  errors::{CompleteNexusError, WorkerValidationError},
67
66
  worker::PollerBehavior,
@@ -84,7 +83,8 @@ use temporal_sdk_core_protos::{
84
83
  use tokio::sync::{mpsc::unbounded_channel, watch};
85
84
  use tokio_stream::wrappers::UnboundedReceiverStream;
86
85
  use tokio_util::sync::CancellationToken;
87
- #[cfg(test)]
86
+
87
+ #[cfg(any(feature = "test-utilities", test))]
88
88
  use {
89
89
  crate::{
90
90
  pollers::{BoxedPoller, MockPermittedPollBuffer},
@@ -114,7 +114,7 @@ pub struct Worker {
114
114
  shutdown_token: CancellationToken,
115
115
  /// Will be called at the end of each activation completion
116
116
  #[allow(clippy::type_complexity)] // Sorry clippy, there's no simple way to re-use here.
117
- post_activate_hook: Option<Box<dyn Fn(&Self, PostActivateHookData) + Send + Sync>>,
117
+ post_activate_hook: Option<Box<dyn Fn(&Self, PostActivateHookData<'_>) + Send + Sync>>,
118
118
  /// Set when non-local activities are complete and should stop being polled
119
119
  non_local_activities_complete: Arc<AtomicBool>,
120
120
  /// Set when local activities are complete and should stop being polled
@@ -289,9 +289,12 @@ impl Worker {
289
289
  )
290
290
  }
291
291
 
292
- /// Replace client and return a new client. For eager workflow purposes, this new client will
293
- /// now apply to future eager start requests and the older client will not.
294
- pub fn replace_client(&self, new_client: ConfiguredClient<TemporalServiceClientWithMetrics>) {
292
+ /// Replace client. For eager workflow purposes, this new client will now apply to future
293
+ /// eager start requests and the older client will not.
294
+ pub fn replace_client<CT>(&self, new_client: CT)
295
+ where
296
+ CT: Into<AnyClient>,
297
+ {
295
298
  // Unregister worker from current client, register in new client at the end
296
299
  let mut worker_key = self.worker_key.lock();
297
300
  let slot_provider = (*worker_key).and_then(|k| self.client.workers().unregister(k));
@@ -396,7 +399,7 @@ impl Worker {
396
399
  shutdown_token.child_token(),
397
400
  Some(move |np| act_metrics.record_num_pollers(np)),
398
401
  ActivityTaskOptions {
399
- max_worker_acts_per_second: config.max_task_queue_activities_per_second,
402
+ max_worker_acts_per_second: config.max_worker_activities_per_second,
400
403
  max_tps: config.max_task_queue_activities_per_second,
401
404
  },
402
405
  );
@@ -413,11 +416,11 @@ impl Worker {
413
416
  Some(move |np| np_metrics.record_num_pollers(np)),
414
417
  )) as BoxedNexusPoller;
415
418
 
416
- #[cfg(test)]
419
+ #[cfg(any(feature = "test-utilities", test))]
417
420
  let wft_stream = wft_stream.left_stream();
418
421
  (wft_stream, act_poll_buffer, nexus_poll_buffer)
419
422
  }
420
- #[cfg(test)]
423
+ #[cfg(any(feature = "test-utilities", test))]
421
424
  TaskPollers::Mocked {
422
425
  wft_stream,
423
426
  act_poller,
@@ -483,11 +486,18 @@ impl Worker {
483
486
  shutdown_token.child_token(),
484
487
  );
485
488
 
489
+ let deployment_options = match &config.versioning_strategy {
490
+ temporal_sdk_core_api::worker::WorkerVersioningStrategy::WorkerDeploymentBased(
491
+ opts,
492
+ ) => Some(opts.clone()),
493
+ _ => None,
494
+ };
486
495
  let provider = SlotProvider::new(
487
496
  config.namespace.clone(),
488
497
  config.task_queue.clone(),
489
498
  wft_slots.clone(),
490
499
  external_wft_tx,
500
+ deployment_options,
491
501
  );
492
502
  let worker_key = Mutex::new(client.workers().register(Box::new(provider)));
493
503
  let sdk_name_and_ver = client.sdk_name_and_version();
@@ -813,7 +823,7 @@ impl Worker {
813
823
  /// Sets a function to be called at the end of each activation completion
814
824
  pub(crate) fn set_post_activate_hook(
815
825
  &mut self,
816
- callback: impl Fn(&Self, PostActivateHookData) + Send + Sync + 'static,
826
+ callback: impl Fn(&Self, PostActivateHookData<'_>) + Send + Sync + 'static,
817
827
  ) {
818
828
  self.post_activate_hook = Some(Box::new(callback))
819
829
  }
@@ -868,7 +878,7 @@ pub(crate) struct PostActivateHookData<'a> {
868
878
 
869
879
  pub(crate) enum TaskPollers {
870
880
  Real,
871
- #[cfg(test)]
881
+ #[cfg(any(feature = "test-utilities", test))]
872
882
  Mocked {
873
883
  wft_stream: BoxStream<'static, Result<ValidPollWFTQResponse, tonic::Status>>,
874
884
  act_poller: Option<BoxedPoller<PollActivityTaskQueueResponse>>,
@@ -32,7 +32,11 @@ use temporal_sdk_core_protos::{
32
32
  CancelNexusTask, NexusTask, NexusTaskCancelReason, nexus_task, nexus_task_completion,
33
33
  },
34
34
  },
35
- temporal::api::nexus::v1::{request::Variant, response, start_operation_response},
35
+ temporal::api::nexus::{
36
+ self,
37
+ v1::{request::Variant, response, start_operation_response},
38
+ },
39
+ utilities::normalize_http_headers,
36
40
  };
37
41
  use tokio::{
38
42
  join,
@@ -42,7 +46,7 @@ use tokio::{
42
46
  use tokio_stream::wrappers::UnboundedReceiverStream;
43
47
  use tokio_util::sync::CancellationToken;
44
48
 
45
- static REQUEST_TIMEOUT_HEADER: &str = "Request-Timeout";
49
+ static REQUEST_TIMEOUT_HEADER: &str = "request-timeout";
46
50
 
47
51
  /// Centralizes all state related to received nexus tasks
48
52
  pub(super) struct NexusManager {
@@ -245,11 +249,18 @@ where
245
249
  .filter_map(move |t| {
246
250
  let res = match t {
247
251
  TaskStreamInput::Poll(t) => match *t {
248
- Ok(t) => {
252
+ Ok(mut t) => {
249
253
  if let Some(dur) = t.resp.sched_to_start() {
250
254
  self.metrics.nexus_task_sched_to_start_latency(dur);
251
255
  };
252
256
 
257
+ if let Some(ref mut req) = t.resp.request {
258
+ req.header = normalize_http_headers(std::mem::take(&mut req.header));
259
+ if let Some(nexus::v1::request::Variant::StartOperation(ref mut sor)) = req.variant {
260
+ sor.callback_header = normalize_http_headers(std::mem::take(&mut sor.callback_header));
261
+ }
262
+ }
263
+
253
264
  let tt = TaskToken(t.resp.task_token.clone());
254
265
  let mut timeout_task = None;
255
266
  if let Some(timeout_str) = t