@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
@@ -3,14 +3,14 @@
3
3
  //! happen.
4
4
 
5
5
  use crate::{
6
- Client, ConfiguredClient, InterceptedMetricsSvc, LONG_POLL_TIMEOUT, RequestExt, RetryClient,
6
+ Client, ConfiguredClient, LONG_POLL_TIMEOUT, RequestExt, RetryClient, SharedReplaceableClient,
7
7
  TEMPORAL_NAMESPACE_HEADER_KEY, TemporalServiceClient,
8
- metrics::{namespace_kv, task_queue_kv},
9
- raw::sealed::RawClientLike,
8
+ metrics::namespace_kv,
10
9
  worker_registry::{Slot, SlotManager},
11
10
  };
11
+ use dyn_clone::DynClone;
12
12
  use futures_util::{FutureExt, TryFutureExt, future::BoxFuture};
13
- use std::sync::Arc;
13
+ use std::{any::Any, marker::PhantomData, sync::Arc};
14
14
  use temporal_sdk_core_api::telemetry::metrics::MetricKeyValue;
15
15
  use temporal_sdk_core_protos::{
16
16
  grpc::health::v1::{health_client::HealthClient, *},
@@ -29,115 +29,182 @@ use tonic::{
29
29
  metadata::{AsciiMetadataValue, KeyAndValueRef},
30
30
  };
31
31
 
32
- pub(super) mod sealed {
33
- use super::*;
34
-
35
- /// Something that has access to the raw grpc services
36
- #[async_trait::async_trait]
37
- pub trait RawClientLike: Send {
38
- type SvcType: Send + Sync + Clone + 'static;
39
-
40
- /// Return a ref to the workflow service client instance
41
- fn workflow_client(&self) -> &WorkflowServiceClient<Self::SvcType>;
32
+ /// Something that has access to the raw grpc services
33
+ trait RawClientProducer {
34
+ /// Returns information about workers associated with this client. Implementers outside of
35
+ /// core can safely return `None`.
36
+ fn get_workers_info(&self) -> Option<Arc<SlotManager>>;
42
37
 
43
- /// Return a mutable ref to the workflow service client instance
44
- fn workflow_client_mut(&mut self) -> &mut WorkflowServiceClient<Self::SvcType>;
38
+ /// Return a workflow service client instance
39
+ fn workflow_client(&mut self) -> Box<dyn WorkflowService>;
45
40
 
46
- /// Return a ref to the operator service client instance
47
- fn operator_client(&self) -> &OperatorServiceClient<Self::SvcType>;
41
+ /// Return a mutable ref to the operator service client instance
42
+ fn operator_client(&mut self) -> Box<dyn OperatorService>;
48
43
 
49
- /// Return a mutable ref to the operator service client instance
50
- fn operator_client_mut(&mut self) -> &mut OperatorServiceClient<Self::SvcType>;
44
+ /// Return a mutable ref to the cloud service client instance
45
+ fn cloud_client(&mut self) -> Box<dyn CloudService>;
51
46
 
52
- /// Return a ref to the cloud service client instance
53
- fn cloud_client(&self) -> &CloudServiceClient<Self::SvcType>;
47
+ /// Return a mutable ref to the test service client instance
48
+ fn test_client(&mut self) -> Box<dyn TestService>;
54
49
 
55
- /// Return a mutable ref to the cloud service client instance
56
- fn cloud_client_mut(&mut self) -> &mut CloudServiceClient<Self::SvcType>;
57
-
58
- /// Return a ref to the test service client instance
59
- fn test_client(&self) -> &TestServiceClient<Self::SvcType>;
50
+ /// Return a mutable ref to the health service client instance
51
+ fn health_client(&mut self) -> Box<dyn HealthService>;
52
+ }
60
53
 
61
- /// Return a mutable ref to the test service client instance
62
- fn test_client_mut(&mut self) -> &mut TestServiceClient<Self::SvcType>;
54
+ /// Any client that can make gRPC calls. The default implementation simply invokes the passed-in
55
+ /// function. Implementers may override this to provide things like retry behavior, ex:
56
+ /// [RetryClient].
57
+ #[async_trait::async_trait]
58
+ trait RawGrpcCaller: Send + Sync + 'static {
59
+ async fn call<F, Req, Resp>(
60
+ &mut self,
61
+ _call_name: &'static str,
62
+ mut callfn: F,
63
+ req: Request<Req>,
64
+ ) -> Result<Response<Resp>, Status>
65
+ where
66
+ Req: Clone + Unpin + Send + Sync + 'static,
67
+ Resp: Send + 'static,
68
+ F: Send + Sync + Unpin + 'static,
69
+ for<'a> F:
70
+ FnMut(&'a mut Self, Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
71
+ {
72
+ callfn(self, req).await
73
+ }
74
+ }
63
75
 
64
- /// Return a ref to the health service client instance
65
- fn health_client(&self) -> &HealthClient<Self::SvcType>;
76
+ trait ErasedRawClient: Send + Sync + 'static {
77
+ fn erased_call(
78
+ &mut self,
79
+ call_name: &'static str,
80
+ op: &mut dyn ErasedCallOp,
81
+ ) -> BoxFuture<'static, Result<Response<Box<dyn Any + Send>>, Status>>;
82
+ }
66
83
 
67
- /// Return a mutable ref to the health service client instance
68
- fn health_client_mut(&mut self) -> &mut HealthClient<Self::SvcType>;
84
+ trait ErasedCallOp: Send {
85
+ fn invoke(
86
+ &mut self,
87
+ raw: &mut dyn ErasedRawClient,
88
+ call_name: &'static str,
89
+ ) -> BoxFuture<'static, Result<Response<Box<dyn Any + Send>>, Status>>;
90
+ }
69
91
 
70
- /// Return a registry with workers using this client instance
71
- fn get_workers_info(&self) -> Option<Arc<SlotManager>>;
92
+ struct CallShim<F, Req, Resp> {
93
+ callfn: F,
94
+ seed_req: Option<Request<Req>>,
95
+ _resp: PhantomData<Resp>,
96
+ }
72
97
 
73
- async fn call<F, Req, Resp>(
74
- &mut self,
75
- _call_name: &'static str,
76
- mut callfn: F,
77
- req: Request<Req>,
78
- ) -> Result<Response<Resp>, Status>
79
- where
80
- Req: Clone + Unpin + Send + Sync + 'static,
81
- F: FnMut(&mut Self, Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
82
- F: Send + Sync + Unpin + 'static,
83
- {
84
- callfn(self, req).await
98
+ impl<F, Req, Resp> CallShim<F, Req, Resp> {
99
+ fn new(callfn: F, seed_req: Request<Req>) -> Self {
100
+ Self {
101
+ callfn,
102
+ seed_req: Some(seed_req),
103
+ _resp: PhantomData,
85
104
  }
86
105
  }
87
106
  }
88
-
89
- #[async_trait::async_trait]
90
- impl<RC, T> RawClientLike for RetryClient<RC>
107
+ impl<F, Req, Resp> ErasedCallOp for CallShim<F, Req, Resp>
91
108
  where
92
- RC: RawClientLike<SvcType = T> + 'static,
93
- T: Send + Sync + Clone + 'static,
109
+ Req: Clone + Unpin + Send + Sync + 'static,
110
+ Resp: Send + 'static,
111
+ F: Send + Sync + Unpin + 'static,
112
+ for<'a> F: FnMut(
113
+ &'a mut dyn ErasedRawClient,
114
+ Request<Req>,
115
+ ) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
94
116
  {
95
- type SvcType = T;
96
-
97
- fn workflow_client(&self) -> &WorkflowServiceClient<Self::SvcType> {
98
- self.get_client().workflow_client()
99
- }
100
-
101
- fn workflow_client_mut(&mut self) -> &mut WorkflowServiceClient<Self::SvcType> {
102
- self.get_client_mut().workflow_client_mut()
103
- }
104
-
105
- fn operator_client(&self) -> &OperatorServiceClient<Self::SvcType> {
106
- self.get_client().operator_client()
117
+ fn invoke(
118
+ &mut self,
119
+ raw: &mut dyn ErasedRawClient,
120
+ _call_name: &'static str,
121
+ ) -> BoxFuture<'static, Result<Response<Box<dyn Any + Send>>, Status>> {
122
+ (self.callfn)(
123
+ raw,
124
+ self.seed_req
125
+ .take()
126
+ .expect("CallShim must have request populated"),
127
+ )
128
+ .map(|res| res.map(|payload| payload.map(|t| Box::new(t) as Box<dyn Any + Send>)))
129
+ .boxed()
107
130
  }
131
+ }
108
132
 
109
- fn operator_client_mut(&mut self) -> &mut OperatorServiceClient<Self::SvcType> {
110
- self.get_client_mut().operator_client_mut()
133
+ #[async_trait::async_trait]
134
+ impl RawGrpcCaller for dyn ErasedRawClient {
135
+ async fn call<F, Req, Resp>(
136
+ &mut self,
137
+ call_name: &'static str,
138
+ callfn: F,
139
+ req: Request<Req>,
140
+ ) -> Result<Response<Resp>, Status>
141
+ where
142
+ Req: Clone + Unpin + Send + Sync + 'static,
143
+ Resp: Send + 'static,
144
+ F: Send + Sync + Unpin + 'static,
145
+ for<'a> F: FnMut(
146
+ &'a mut dyn ErasedRawClient,
147
+ Request<Req>,
148
+ ) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
149
+ {
150
+ let mut shim = CallShim::new(callfn, req);
151
+ let erased_resp = ErasedRawClient::erased_call(self, call_name, &mut shim).await?;
152
+ Ok(erased_resp.map(|boxed| {
153
+ *boxed
154
+ .downcast()
155
+ .expect("RawGrpcCaller erased response type mismatch")
156
+ }))
111
157
  }
158
+ }
112
159
 
113
- fn cloud_client(&self) -> &CloudServiceClient<Self::SvcType> {
114
- self.get_client().cloud_client()
160
+ impl<T> ErasedRawClient for T
161
+ where
162
+ T: RawGrpcCaller + 'static,
163
+ {
164
+ fn erased_call(
165
+ &mut self,
166
+ call_name: &'static str,
167
+ op: &mut dyn ErasedCallOp,
168
+ ) -> BoxFuture<'static, Result<Response<Box<dyn Any + Send>>, Status>> {
169
+ let raw: &mut dyn ErasedRawClient = self;
170
+ op.invoke(raw, call_name)
115
171
  }
172
+ }
116
173
 
117
- fn cloud_client_mut(&mut self) -> &mut CloudServiceClient<Self::SvcType> {
118
- self.get_client_mut().cloud_client_mut()
174
+ impl<RC> RawClientProducer for RetryClient<RC>
175
+ where
176
+ RC: RawClientProducer + 'static,
177
+ {
178
+ fn get_workers_info(&self) -> Option<Arc<SlotManager>> {
179
+ self.get_client().get_workers_info()
119
180
  }
120
181
 
121
- fn test_client(&self) -> &TestServiceClient<Self::SvcType> {
122
- self.get_client().test_client()
182
+ fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
183
+ self.get_client_mut().workflow_client()
123
184
  }
124
185
 
125
- fn test_client_mut(&mut self) -> &mut TestServiceClient<Self::SvcType> {
126
- self.get_client_mut().test_client_mut()
186
+ fn operator_client(&mut self) -> Box<dyn OperatorService> {
187
+ self.get_client_mut().operator_client()
127
188
  }
128
189
 
129
- fn health_client(&self) -> &HealthClient<Self::SvcType> {
130
- self.get_client().health_client()
190
+ fn cloud_client(&mut self) -> Box<dyn CloudService> {
191
+ self.get_client_mut().cloud_client()
131
192
  }
132
193
 
133
- fn health_client_mut(&mut self) -> &mut HealthClient<Self::SvcType> {
134
- self.get_client_mut().health_client_mut()
194
+ fn test_client(&mut self) -> Box<dyn TestService> {
195
+ self.get_client_mut().test_client()
135
196
  }
136
197
 
137
- fn get_workers_info(&self) -> Option<Arc<SlotManager>> {
138
- self.get_client().get_workers_info()
198
+ fn health_client(&mut self) -> Box<dyn HealthService> {
199
+ self.get_client_mut().health_client()
139
200
  }
201
+ }
140
202
 
203
+ #[async_trait::async_trait]
204
+ impl<RC> RawGrpcCaller for RetryClient<RC>
205
+ where
206
+ RC: RawGrpcCaller + 'static,
207
+ {
141
208
  async fn call<F, Req, Resp>(
142
209
  &mut self,
143
210
  call_name: &'static str,
@@ -163,202 +230,173 @@ where
163
230
  }
164
231
  }
165
232
 
166
- impl<T> RawClientLike for TemporalServiceClient<T>
233
+ /// Helper for cloning a tonic request as long as the inner message may be cloned.
234
+ fn req_cloner<T: Clone>(cloneme: &Request<T>) -> Request<T> {
235
+ let msg = cloneme.get_ref().clone();
236
+ let mut new_req = Request::new(msg);
237
+ let new_met = new_req.metadata_mut();
238
+ for kv in cloneme.metadata().iter() {
239
+ match kv {
240
+ KeyAndValueRef::Ascii(k, v) => {
241
+ new_met.insert(k, v.clone());
242
+ }
243
+ KeyAndValueRef::Binary(k, v) => {
244
+ new_met.insert_bin(k, v.clone());
245
+ }
246
+ }
247
+ }
248
+ *new_req.extensions_mut() = cloneme.extensions().clone();
249
+ new_req
250
+ }
251
+
252
+ impl<RC> RawClientProducer for SharedReplaceableClient<RC>
167
253
  where
168
- T: Send + Sync + Clone + 'static,
169
- T: GrpcService<Body> + Send + Clone + 'static,
170
- T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
171
- T::Error: Into<tonic::codegen::StdError>,
172
- <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
254
+ RC: RawClientProducer + Clone + Send + Sync + 'static,
173
255
  {
174
- type SvcType = T;
175
-
176
- fn workflow_client(&self) -> &WorkflowServiceClient<Self::SvcType> {
177
- self.workflow_svc()
256
+ fn get_workers_info(&self) -> Option<Arc<SlotManager>> {
257
+ self.inner_cow().get_workers_info()
258
+ }
259
+ fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
260
+ self.inner_mut_refreshed().workflow_client()
178
261
  }
179
262
 
180
- fn workflow_client_mut(&mut self) -> &mut WorkflowServiceClient<Self::SvcType> {
181
- self.workflow_svc_mut()
263
+ fn operator_client(&mut self) -> Box<dyn OperatorService> {
264
+ self.inner_mut_refreshed().operator_client()
182
265
  }
183
266
 
184
- fn operator_client(&self) -> &OperatorServiceClient<Self::SvcType> {
185
- self.operator_svc()
267
+ fn cloud_client(&mut self) -> Box<dyn CloudService> {
268
+ self.inner_mut_refreshed().cloud_client()
186
269
  }
187
270
 
188
- fn operator_client_mut(&mut self) -> &mut OperatorServiceClient<Self::SvcType> {
189
- self.operator_svc_mut()
271
+ fn test_client(&mut self) -> Box<dyn TestService> {
272
+ self.inner_mut_refreshed().test_client()
190
273
  }
191
274
 
192
- fn cloud_client(&self) -> &CloudServiceClient<Self::SvcType> {
193
- self.cloud_svc()
275
+ fn health_client(&mut self) -> Box<dyn HealthService> {
276
+ self.inner_mut_refreshed().health_client()
194
277
  }
278
+ }
195
279
 
196
- fn cloud_client_mut(&mut self) -> &mut CloudServiceClient<Self::SvcType> {
197
- self.cloud_svc_mut()
280
+ #[async_trait::async_trait]
281
+ impl<RC> RawGrpcCaller for SharedReplaceableClient<RC> where
282
+ RC: RawGrpcCaller + Clone + Sync + 'static
283
+ {
284
+ }
285
+
286
+ impl RawClientProducer for TemporalServiceClient {
287
+ fn get_workers_info(&self) -> Option<Arc<SlotManager>> {
288
+ None
198
289
  }
199
290
 
200
- fn test_client(&self) -> &TestServiceClient<Self::SvcType> {
201
- self.test_svc()
291
+ fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
292
+ self.workflow_svc()
202
293
  }
203
294
 
204
- fn test_client_mut(&mut self) -> &mut TestServiceClient<Self::SvcType> {
205
- self.test_svc_mut()
295
+ fn operator_client(&mut self) -> Box<dyn OperatorService> {
296
+ self.operator_svc()
206
297
  }
207
298
 
208
- fn health_client(&self) -> &HealthClient<Self::SvcType> {
209
- self.health_svc()
299
+ fn cloud_client(&mut self) -> Box<dyn CloudService> {
300
+ self.cloud_svc()
210
301
  }
211
302
 
212
- fn health_client_mut(&mut self) -> &mut HealthClient<Self::SvcType> {
213
- self.health_svc_mut()
303
+ fn test_client(&mut self) -> Box<dyn TestService> {
304
+ self.test_svc()
214
305
  }
215
306
 
216
- fn get_workers_info(&self) -> Option<Arc<SlotManager>> {
217
- None
307
+ fn health_client(&mut self) -> Box<dyn HealthService> {
308
+ self.health_svc()
218
309
  }
219
310
  }
220
311
 
221
- impl<T> RawClientLike for ConfiguredClient<TemporalServiceClient<T>>
222
- where
223
- T: Send + Sync + Clone + 'static,
224
- T: GrpcService<Body> + Send + Clone + 'static,
225
- T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
226
- T::Error: Into<tonic::codegen::StdError>,
227
- <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
228
- {
229
- type SvcType = T;
312
+ impl RawGrpcCaller for TemporalServiceClient {}
230
313
 
231
- fn workflow_client(&self) -> &WorkflowServiceClient<Self::SvcType> {
232
- self.client.workflow_client()
314
+ impl RawClientProducer for ConfiguredClient<TemporalServiceClient> {
315
+ fn get_workers_info(&self) -> Option<Arc<SlotManager>> {
316
+ Some(self.workers())
233
317
  }
234
318
 
235
- fn workflow_client_mut(&mut self) -> &mut WorkflowServiceClient<Self::SvcType> {
236
- self.client.workflow_client_mut()
319
+ fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
320
+ self.client.workflow_client()
237
321
  }
238
322
 
239
- fn operator_client(&self) -> &OperatorServiceClient<Self::SvcType> {
323
+ fn operator_client(&mut self) -> Box<dyn OperatorService> {
240
324
  self.client.operator_client()
241
325
  }
242
326
 
243
- fn operator_client_mut(&mut self) -> &mut OperatorServiceClient<Self::SvcType> {
244
- self.client.operator_client_mut()
245
- }
246
-
247
- fn cloud_client(&self) -> &CloudServiceClient<Self::SvcType> {
327
+ fn cloud_client(&mut self) -> Box<dyn CloudService> {
248
328
  self.client.cloud_client()
249
329
  }
250
330
 
251
- fn cloud_client_mut(&mut self) -> &mut CloudServiceClient<Self::SvcType> {
252
- self.client.cloud_client_mut()
253
- }
254
-
255
- fn test_client(&self) -> &TestServiceClient<Self::SvcType> {
331
+ fn test_client(&mut self) -> Box<dyn TestService> {
256
332
  self.client.test_client()
257
333
  }
258
334
 
259
- fn test_client_mut(&mut self) -> &mut TestServiceClient<Self::SvcType> {
260
- self.client.test_client_mut()
261
- }
262
-
263
- fn health_client(&self) -> &HealthClient<Self::SvcType> {
335
+ fn health_client(&mut self) -> Box<dyn HealthService> {
264
336
  self.client.health_client()
265
337
  }
338
+ }
266
339
 
267
- fn health_client_mut(&mut self) -> &mut HealthClient<Self::SvcType> {
268
- self.client.health_client_mut()
269
- }
340
+ impl RawGrpcCaller for ConfiguredClient<TemporalServiceClient> {}
270
341
 
342
+ impl RawClientProducer for Client {
271
343
  fn get_workers_info(&self) -> Option<Arc<SlotManager>> {
272
- Some(self.workers())
344
+ self.inner.get_workers_info()
273
345
  }
274
- }
275
-
276
- impl RawClientLike for Client {
277
- type SvcType = InterceptedMetricsSvc;
278
346
 
279
- fn workflow_client(&self) -> &WorkflowServiceClient<Self::SvcType> {
347
+ fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
280
348
  self.inner.workflow_client()
281
349
  }
282
350
 
283
- fn workflow_client_mut(&mut self) -> &mut WorkflowServiceClient<Self::SvcType> {
284
- self.inner.workflow_client_mut()
285
- }
286
-
287
- fn operator_client(&self) -> &OperatorServiceClient<Self::SvcType> {
351
+ fn operator_client(&mut self) -> Box<dyn OperatorService> {
288
352
  self.inner.operator_client()
289
353
  }
290
354
 
291
- fn operator_client_mut(&mut self) -> &mut OperatorServiceClient<Self::SvcType> {
292
- self.inner.operator_client_mut()
293
- }
294
-
295
- fn cloud_client(&self) -> &CloudServiceClient<Self::SvcType> {
355
+ fn cloud_client(&mut self) -> Box<dyn CloudService> {
296
356
  self.inner.cloud_client()
297
357
  }
298
358
 
299
- fn cloud_client_mut(&mut self) -> &mut CloudServiceClient<Self::SvcType> {
300
- self.inner.cloud_client_mut()
301
- }
302
-
303
- fn test_client(&self) -> &TestServiceClient<Self::SvcType> {
359
+ fn test_client(&mut self) -> Box<dyn TestService> {
304
360
  self.inner.test_client()
305
361
  }
306
362
 
307
- fn test_client_mut(&mut self) -> &mut TestServiceClient<Self::SvcType> {
308
- self.inner.test_client_mut()
309
- }
310
-
311
- fn health_client(&self) -> &HealthClient<Self::SvcType> {
363
+ fn health_client(&mut self) -> Box<dyn HealthService> {
312
364
  self.inner.health_client()
313
365
  }
314
-
315
- fn health_client_mut(&mut self) -> &mut HealthClient<Self::SvcType> {
316
- self.inner.health_client_mut()
317
- }
318
-
319
- fn get_workers_info(&self) -> Option<Arc<SlotManager>> {
320
- self.inner.get_workers_info()
321
- }
322
366
  }
323
367
 
324
- /// Helper for cloning a tonic request as long as the inner message may be cloned.
325
- fn req_cloner<T: Clone>(cloneme: &Request<T>) -> Request<T> {
326
- let msg = cloneme.get_ref().clone();
327
- let mut new_req = Request::new(msg);
328
- let new_met = new_req.metadata_mut();
329
- for kv in cloneme.metadata().iter() {
330
- match kv {
331
- KeyAndValueRef::Ascii(k, v) => {
332
- new_met.insert(k, v.clone());
333
- }
334
- KeyAndValueRef::Binary(k, v) => {
335
- new_met.insert_bin(k, v.clone());
336
- }
337
- }
338
- }
339
- *new_req.extensions_mut() = cloneme.extensions().clone();
340
- new_req
341
- }
368
+ impl RawGrpcCaller for Client {}
342
369
 
343
370
  #[derive(Clone, Debug)]
344
371
  pub(super) struct AttachMetricLabels {
345
372
  pub(super) labels: Vec<MetricKeyValue>,
373
+ pub(super) normal_task_queue: Option<String>,
374
+ pub(super) sticky_task_queue: Option<String>,
346
375
  }
347
376
  impl AttachMetricLabels {
348
377
  pub(super) fn new(kvs: impl Into<Vec<MetricKeyValue>>) -> Self {
349
- Self { labels: kvs.into() }
378
+ Self {
379
+ labels: kvs.into(),
380
+ normal_task_queue: None,
381
+ sticky_task_queue: None,
382
+ }
350
383
  }
351
384
  pub(super) fn namespace(ns: impl Into<String>) -> Self {
352
385
  AttachMetricLabels::new(vec![namespace_kv(ns.into())])
353
386
  }
354
387
  pub(super) fn task_q(&mut self, tq: Option<TaskQueue>) -> &mut Self {
355
388
  if let Some(tq) = tq {
356
- self.task_q_str(tq.name);
389
+ if !tq.normal_name.is_empty() {
390
+ self.sticky_task_queue = Some(tq.name);
391
+ self.normal_task_queue = Some(tq.normal_name);
392
+ } else {
393
+ self.normal_task_queue = Some(tq.name);
394
+ }
357
395
  }
358
396
  self
359
397
  }
360
398
  pub(super) fn task_q_str(&mut self, tq: impl Into<String>) -> &mut Self {
361
- self.labels.push(task_queue_kv(tq.into()));
399
+ self.normal_task_queue = Some(tq.into());
362
400
  self
363
401
  }
364
402
  }
@@ -368,62 +406,27 @@ impl AttachMetricLabels {
368
406
  #[derive(Copy, Clone, Debug)]
369
407
  pub(super) struct IsUserLongPoll;
370
408
 
371
- // Blanket impl the trait for all raw-client-like things. Since the trait default-implements
372
- // everything, there's nothing to actually implement.
373
- impl<RC, T> WorkflowService for RC
374
- where
375
- RC: RawClientLike<SvcType = T>,
376
- T: GrpcService<Body> + Send + Clone + 'static,
377
- T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
378
- T::Error: Into<tonic::codegen::StdError>,
379
- T::Future: Send,
380
- <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
381
- {
382
- }
383
- impl<RC, T> OperatorService for RC
384
- where
385
- RC: RawClientLike<SvcType = T>,
386
- T: GrpcService<Body> + Send + Clone + 'static,
387
- T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
388
- T::Error: Into<tonic::codegen::StdError>,
389
- T::Future: Send,
390
- <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
391
- {
392
- }
393
- impl<RC, T> CloudService for RC
394
- where
395
- RC: RawClientLike<SvcType = T>,
396
- T: GrpcService<Body> + Send + Clone + 'static,
397
- T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
398
- T::Error: Into<tonic::codegen::StdError>,
399
- T::Future: Send,
400
- <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
401
- {
402
- }
403
- impl<RC, T> TestService for RC
404
- where
405
- RC: RawClientLike<SvcType = T>,
406
- T: GrpcService<Body> + Send + Clone + 'static,
407
- T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
408
- T::Error: Into<tonic::codegen::StdError>,
409
- T::Future: Send,
410
- <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
411
- {
412
- }
413
- impl<RC, T> HealthService for RC
414
- where
415
- RC: RawClientLike<SvcType = T>,
416
- T: GrpcService<Body> + Send + Clone + 'static,
417
- T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
418
- T::Error: Into<tonic::codegen::StdError>,
419
- T::Future: Send,
420
- <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
421
- {
409
+ macro_rules! proxy_def {
410
+ ($client_type:tt, $client_meth:ident, $method:ident, $req:ty, $resp:ty, defaults) => {
411
+ #[doc = concat!("See [", stringify!($client_type), "::", stringify!($method), "]")]
412
+ fn $method(
413
+ &mut self,
414
+ _request: tonic::Request<$req>,
415
+ ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>> {
416
+ async { Ok(tonic::Response::new(<$resp>::default())) }.boxed()
417
+ }
418
+ };
419
+ ($client_type:tt, $client_meth:ident, $method:ident, $req:ty, $resp:ty) => {
420
+ #[doc = concat!("See [", stringify!($client_type), "::", stringify!($method), "]")]
421
+ fn $method(
422
+ &mut self,
423
+ _request: tonic::Request<$req>,
424
+ ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>>;
425
+ };
422
426
  }
423
-
424
427
  /// Helps re-declare gRPC client methods
425
428
  ///
426
- /// There are two forms:
429
+ /// There are four forms:
427
430
  ///
428
431
  /// * The first takes a closure that can modify the request. This is only called once, before the
429
432
  /// actual rpc call is made, and before determinations are made about the kind of call (long poll
@@ -431,22 +434,23 @@ where
431
434
  /// * The second takes three closures. The first can modify the request like in the first form.
432
435
  /// The second can modify the request and return a value, and is called right before every call
433
436
  /// (including on retries). The third is called with the response to the call after it resolves.
434
- macro_rules! proxy {
437
+ /// * The third and fourth are equivalents of the above that skip calling through the `call` method
438
+ /// and are implemented directly on the generated gRPC clients (IE: the bottom of the stack).
439
+ macro_rules! proxy_impl {
435
440
  ($client_type:tt, $client_meth:ident, $method:ident, $req:ty, $resp:ty $(, $closure:expr)?) => {
436
441
  #[doc = concat!("See [", stringify!($client_type), "::", stringify!($method), "]")]
437
442
  fn $method(
438
443
  &mut self,
439
- request: impl tonic::IntoRequest<$req>,
440
- ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>> {
441
444
  #[allow(unused_mut)]
442
- let mut as_req = request.into_request();
443
- $( type_closure_arg(&mut as_req, $closure); )*
445
+ mut request: tonic::Request<$req>,
446
+ ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>> {
447
+ $( type_closure_arg(&mut request, $closure); )*
444
448
  #[allow(unused_mut)]
445
449
  let fact = |c: &mut Self, mut req: tonic::Request<$req>| {
446
- let mut c = c.$client_meth().clone();
450
+ let mut c = c.$client_meth();
447
451
  async move { c.$method(req).await }.boxed()
448
452
  };
449
- self.call(stringify!($method), fact, as_req)
453
+ self.call(stringify!($method), fact, request)
450
454
  }
451
455
  };
452
456
  ($client_type:tt, $client_meth:ident, $method:ident, $req:ty, $resp:ty,
@@ -454,52 +458,108 @@ macro_rules! proxy {
454
458
  #[doc = concat!("See [", stringify!($client_type), "::", stringify!($method), "]")]
455
459
  fn $method(
456
460
  &mut self,
457
- request: impl tonic::IntoRequest<$req>,
461
+ mut request: tonic::Request<$req>,
458
462
  ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>> {
459
- #[allow(unused_mut)]
460
- let mut as_req = request.into_request();
461
- type_closure_arg(&mut as_req, $closure_request);
463
+ type_closure_arg(&mut request, $closure_request);
462
464
  #[allow(unused_mut)]
463
465
  let fact = |c: &mut Self, mut req: tonic::Request<$req>| {
464
- let data = type_closure_two_arg(&mut req, c.get_workers_info().unwrap(),
465
- $closure_before);
466
- let mut c = c.$client_meth().clone();
466
+ let data = type_closure_two_arg(&mut req, c.get_workers_info(), $closure_before);
467
+ let mut c = c.$client_meth();
467
468
  async move {
468
469
  type_closure_two_arg(c.$method(req).await, data, $closure_after)
469
470
  }.boxed()
470
471
  };
471
- self.call(stringify!($method), fact, as_req)
472
+ self.call(stringify!($method), fact, request)
473
+ }
474
+ };
475
+ ($client_type:tt, $method:ident, $req:ty, $resp:ty $(, $closure:expr)?) => {
476
+ #[doc = concat!("See [", stringify!($client_type), "::", stringify!($method), "]")]
477
+ fn $method(
478
+ &mut self,
479
+ #[allow(unused_mut)]
480
+ mut request: tonic::Request<$req>,
481
+ ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>> {
482
+ $( type_closure_arg(&mut request, $closure); )*
483
+ async move { <$client_type<_>>::$method(self, request).await }.boxed()
484
+ }
485
+ };
486
+ ($client_type:tt, $method:ident, $req:ty, $resp:ty,
487
+ $closure_request:expr, $closure_before:expr, $closure_after:expr) => {
488
+ #[doc = concat!("See [", stringify!($client_type), "::", stringify!($method), "]")]
489
+ fn $method(
490
+ &mut self,
491
+ mut request: tonic::Request<$req>,
492
+ ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>> {
493
+ type_closure_arg(&mut request, $closure_request);
494
+ let data = type_closure_two_arg(&mut request, Option::<Arc<SlotManager>>::None,
495
+ $closure_before);
496
+ async move {
497
+ type_closure_two_arg(<$client_type<_>>::$method(self, request).await,
498
+ data, $closure_after)
499
+ }.boxed()
472
500
  }
473
501
  };
474
502
  }
475
- macro_rules! proxier {
476
- ( $trait_name:ident; $impl_list_name:ident; $client_type:tt; $client_meth:ident;
477
- $(($method:ident, $req:ty, $resp:ty
478
- $(, $closure:expr $(, $closure_before:expr, $closure_after:expr)?)? );)* ) => {
503
+ macro_rules! proxier_impl {
504
+ ($trait_name:ident; $impl_list_name:ident; $client_type:tt; $client_meth:ident;
505
+ [$( proxy_def!($($def_args:tt)*); )*];
506
+ $(($method:ident, $req:ty, $resp:ty
507
+ $(, $closure:expr $(, $closure_before:expr, $closure_after:expr)?)? );)* ) => {
479
508
  #[cfg(test)]
480
509
  const $impl_list_name: &'static [&'static str] = &[$(stringify!($method)),*];
481
- /// Trait version of the generated client with modifications to attach appropriate metric
482
- /// labels or whatever else to requests
483
- pub trait $trait_name: RawClientLike
510
+
511
+ #[doc = concat!("Trait version of [", stringify!($client_type), "]")]
512
+ pub trait $trait_name: Send + Sync + DynClone
513
+ {
514
+ $( proxy_def!($($def_args)*); )*
515
+ }
516
+ dyn_clone::clone_trait_object!($trait_name);
517
+
518
+ impl<RC> $trait_name for RC
484
519
  where
485
- // Yo this is wild
486
- <Self as RawClientLike>::SvcType: GrpcService<Body> + Send + Clone + 'static,
487
- <<Self as RawClientLike>::SvcType as GrpcService<Body>>::ResponseBody:
488
- tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
489
- <<Self as RawClientLike>::SvcType as GrpcService<Body>>::Error:
490
- Into<tonic::codegen::StdError>,
491
- <<Self as RawClientLike>::SvcType as GrpcService<Body>>::Future: Send,
492
- <<<Self as RawClientLike>::SvcType as GrpcService<Body>>::ResponseBody
493
- as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
520
+ RC: RawGrpcCaller + RawClientProducer + Clone,
494
521
  {
495
522
  $(
496
- proxy!($client_type, $client_meth, $method, $req, $resp
497
- $(,$closure $(,$closure_before, $closure_after)*)*);
523
+ proxy_impl!($client_type, $client_meth, $method, $req, $resp
524
+ $(,$closure $(,$closure_before, $closure_after)*)*);
525
+ )*
526
+ }
527
+
528
+ impl<T: Send + Sync + 'static> RawGrpcCaller for $client_type<T> {}
529
+
530
+ impl<T> $trait_name for $client_type<T>
531
+ where
532
+ T: GrpcService<Body> + Clone + Send + Sync + 'static,
533
+ T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
534
+ T::Error: Into<tonic::codegen::StdError>,
535
+ <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
536
+ <T as tonic::client::GrpcService<Body>>::Future: Send
537
+ {
538
+ $(
539
+ proxy_impl!($client_type, $method, $req, $resp
540
+ $(,$closure $(,$closure_before, $closure_after)*)*);
498
541
  )*
499
542
  }
500
543
  };
501
544
  }
502
545
 
546
+ macro_rules! proxier {
547
+ ( $trait_name:ident; $impl_list_name:ident; $client_type:tt; $client_meth:ident;
548
+ $(($method:ident, $req:ty, $resp:ty
549
+ $(, $closure:expr $(, $closure_before:expr, $closure_after:expr)?)? );)* ) => {
550
+ proxier_impl!($trait_name; $impl_list_name; $client_type; $client_meth;
551
+ [$(proxy_def!($client_type, $client_meth, $method, $req, $resp);)*];
552
+ $(($method, $req, $resp $(, $closure $(, $closure_before, $closure_after)?)?);)*);
553
+ };
554
+ ( $trait_name:ident; $impl_list_name:ident; $client_type:tt; $client_meth:ident; defaults;
555
+ $(($method:ident, $req:ty, $resp:ty
556
+ $(, $closure:expr $(, $closure_before:expr, $closure_after:expr)?)? );)* ) => {
557
+ proxier_impl!($trait_name; $impl_list_name; $client_type; $client_meth;
558
+ [$(proxy_def!($client_type, $client_meth, $method, $req, $resp, defaults);)*];
559
+ $(($method, $req, $resp $(, $closure $(, $closure_before, $closure_after)?)?);)*);
560
+ };
561
+ }
562
+
503
563
  macro_rules! namespaced_request {
504
564
  ($req:ident) => {{
505
565
  let ns_str = $req.get_ref().namespace.clone();
@@ -526,7 +586,7 @@ fn type_closure_two_arg<T, R, S>(arg1: R, arg2: T, f: impl FnOnce(R, T) -> S) ->
526
586
  }
527
587
 
528
588
  proxier! {
529
- WorkflowService; ALL_IMPLEMENTED_WORKFLOW_SERVICE_RPCS; WorkflowServiceClient; workflow_client_mut;
589
+ WorkflowService; ALL_IMPLEMENTED_WORKFLOW_SERVICE_RPCS; WorkflowServiceClient; workflow_client; defaults;
530
590
  (
531
591
  register_namespace,
532
592
  RegisterNamespaceRequest,
@@ -578,21 +638,39 @@ proxier! {
578
638
  r.extensions_mut().insert(labels);
579
639
  },
580
640
  |r, workers| {
581
- let mut slot: Option<Box<dyn Slot + Send>> = None;
582
- let req_mut = r.get_mut();
583
- if req_mut.request_eager_execution {
584
- let namespace = req_mut.namespace.clone();
585
- let task_queue = req_mut.task_queue.as_ref()
586
- .map(|tq| tq.name.clone()).unwrap_or_default();
587
- match workers.try_reserve_wft_slot(namespace, task_queue) {
588
- Some(s) => slot = Some(s),
589
- None => req_mut.request_eager_execution = false
641
+ if let Some(workers) = workers {
642
+ let mut slot: Option<Box<dyn Slot + Send>> = None;
643
+ let req_mut = r.get_mut();
644
+ if req_mut.request_eager_execution {
645
+ let namespace = req_mut.namespace.clone();
646
+ let task_queue = req_mut.task_queue.as_ref()
647
+ .map(|tq| tq.name.clone()).unwrap_or_default();
648
+ match workers.try_reserve_wft_slot(namespace, task_queue) {
649
+ Some(reservation) => {
650
+ // Populate eager_worker_deployment_options from the slot reservation
651
+ if let Some(opts) = reservation.deployment_options {
652
+ req_mut.eager_worker_deployment_options = Some(temporal_sdk_core_protos::temporal::api::deployment::v1::WorkerDeploymentOptions {
653
+ deployment_name: opts.version.deployment_name,
654
+ build_id: opts.version.build_id,
655
+ worker_versioning_mode: if opts.use_worker_versioning {
656
+ temporal_sdk_core_protos::temporal::api::enums::v1::WorkerVersioningMode::Versioned.into()
657
+ } else {
658
+ temporal_sdk_core_protos::temporal::api::enums::v1::WorkerVersioningMode::Unversioned.into()
659
+ },
660
+ });
661
+ }
662
+ slot = Some(reservation.slot);
663
+ }
664
+ None => req_mut.request_eager_execution = false
665
+ }
590
666
  }
667
+ slot
668
+ } else {
669
+ None
591
670
  }
592
- slot
593
671
  },
594
672
  |resp, slot| {
595
- if let Some(mut s) = slot
673
+ if let Some(s) = slot
596
674
  && let Ok(response) = resp.as_ref()
597
675
  && let Some(task) = response.get_ref().clone().eager_workflow_task
598
676
  && let Err(e) = s.schedule_wft(task) {
@@ -1382,10 +1460,28 @@ proxier! {
1382
1460
  r.extensions_mut().insert(labels);
1383
1461
  }
1384
1462
  );
1463
+ (
1464
+ describe_worker,
1465
+ DescribeWorkerRequest,
1466
+ DescribeWorkerResponse,
1467
+ |r| {
1468
+ let labels = namespaced_request!(r);
1469
+ r.extensions_mut().insert(labels);
1470
+ }
1471
+ );
1472
+ (
1473
+ set_worker_deployment_manager,
1474
+ SetWorkerDeploymentManagerRequest,
1475
+ SetWorkerDeploymentManagerResponse,
1476
+ |r| {
1477
+ let labels = namespaced_request!(r);
1478
+ r.extensions_mut().insert(labels);
1479
+ }
1480
+ );
1385
1481
  }
1386
1482
 
1387
1483
  proxier! {
1388
- OperatorService; ALL_IMPLEMENTED_OPERATOR_SERVICE_RPCS; OperatorServiceClient; operator_client_mut;
1484
+ OperatorService; ALL_IMPLEMENTED_OPERATOR_SERVICE_RPCS; OperatorServiceClient; operator_client; defaults;
1389
1485
  (add_search_attributes, AddSearchAttributesRequest, AddSearchAttributesResponse);
1390
1486
  (remove_search_attributes, RemoveSearchAttributesRequest, RemoveSearchAttributesResponse);
1391
1487
  (list_search_attributes, ListSearchAttributesRequest, ListSearchAttributesResponse);
@@ -1406,7 +1502,7 @@ proxier! {
1406
1502
  }
1407
1503
 
1408
1504
  proxier! {
1409
- CloudService; ALL_IMPLEMENTED_CLOUD_SERVICE_RPCS; CloudServiceClient; cloud_client_mut;
1505
+ CloudService; ALL_IMPLEMENTED_CLOUD_SERVICE_RPCS; CloudServiceClient; cloud_client; defaults;
1410
1506
  (get_users, cloudreq::GetUsersRequest, cloudreq::GetUsersResponse);
1411
1507
  (get_user, cloudreq::GetUserRequest, cloudreq::GetUserResponse);
1412
1508
  (create_user, cloudreq::CreateUserRequest, cloudreq::CreateUserResponse);
@@ -1481,7 +1577,7 @@ proxier! {
1481
1577
  }
1482
1578
 
1483
1579
  proxier! {
1484
- TestService; ALL_IMPLEMENTED_TEST_SERVICE_RPCS; TestServiceClient; test_client_mut;
1580
+ TestService; ALL_IMPLEMENTED_TEST_SERVICE_RPCS; TestServiceClient; test_client; defaults;
1485
1581
  (lock_time_skipping, LockTimeSkippingRequest, LockTimeSkippingResponse);
1486
1582
  (unlock_time_skipping, UnlockTimeSkippingRequest, UnlockTimeSkippingResponse);
1487
1583
  (sleep, SleepRequest, SleepResponse);
@@ -1491,7 +1587,7 @@ proxier! {
1491
1587
  }
1492
1588
 
1493
1589
  proxier! {
1494
- HealthService; ALL_IMPLEMENTED_HEALTH_SERVICE_RPCS; HealthClient; health_client_mut;
1590
+ HealthService; ALL_IMPLEMENTED_HEALTH_SERVICE_RPCS; HealthClient; health_client;
1495
1591
  (check, HealthCheckRequest, HealthCheckResponse);
1496
1592
  (watch, HealthCheckRequest, tonic::codec::Streaming<HealthCheckResponse>);
1497
1593
  }
@@ -1504,6 +1600,7 @@ mod tests {
1504
1600
  use temporal_sdk_core_protos::temporal::api::{
1505
1601
  operatorservice::v1::DeleteNamespaceRequest, workflowservice::v1::ListNamespacesRequest,
1506
1602
  };
1603
+ use tonic::IntoRequest;
1507
1604
 
1508
1605
  // Just to help make sure some stuff compiles. Not run.
1509
1606
  #[allow(dead_code)]
@@ -1514,7 +1611,7 @@ mod tests {
1514
1611
 
1515
1612
  let list_ns_req = ListNamespacesRequest::default();
1516
1613
  let fact = |c: &mut RetryClient<_>, req| {
1517
- let mut c = c.workflow_client_mut().clone();
1614
+ let mut c = c.workflow_client();
1518
1615
  async move { c.list_namespaces(req).await }.boxed()
1519
1616
  };
1520
1617
  retry_client
@@ -1525,7 +1622,7 @@ mod tests {
1525
1622
  // Operator svc method
1526
1623
  let op_del_ns_req = DeleteNamespaceRequest::default();
1527
1624
  let fact = |c: &mut RetryClient<_>, req| {
1528
- let mut c = c.operator_client_mut().clone();
1625
+ let mut c = c.operator_client();
1529
1626
  async move { c.delete_namespace(req).await }.boxed()
1530
1627
  };
1531
1628
  retry_client
@@ -1536,7 +1633,7 @@ mod tests {
1536
1633
  // Cloud svc method
1537
1634
  let cloud_del_ns_req = cloudreq::DeleteNamespaceRequest::default();
1538
1635
  let fact = |c: &mut RetryClient<_>, req| {
1539
- let mut c = c.cloud_client_mut().clone();
1636
+ let mut c = c.cloud_client();
1540
1637
  async move { c.delete_namespace(req).await }.boxed()
1541
1638
  };
1542
1639
  retry_client
@@ -1545,17 +1642,23 @@ mod tests {
1545
1642
  .unwrap();
1546
1643
 
1547
1644
  // Verify calling through traits works
1548
- retry_client.list_namespaces(list_ns_req).await.unwrap();
1645
+ retry_client
1646
+ .list_namespaces(list_ns_req.into_request())
1647
+ .await
1648
+ .unwrap();
1549
1649
  // Have to disambiguate operator and cloud service
1550
- OperatorService::delete_namespace(&mut retry_client, op_del_ns_req)
1650
+ OperatorService::delete_namespace(&mut retry_client, op_del_ns_req.into_request())
1651
+ .await
1652
+ .unwrap();
1653
+ CloudService::delete_namespace(&mut retry_client, cloud_del_ns_req.into_request())
1551
1654
  .await
1552
1655
  .unwrap();
1553
- CloudService::delete_namespace(&mut retry_client, cloud_del_ns_req)
1656
+ retry_client
1657
+ .get_current_time(().into_request())
1554
1658
  .await
1555
1659
  .unwrap();
1556
- retry_client.get_current_time(()).await.unwrap();
1557
1660
  retry_client
1558
- .check(HealthCheckRequest::default())
1661
+ .check(HealthCheckRequest::default().into_request())
1559
1662
  .await
1560
1663
  .unwrap();
1561
1664
  }
@@ -1621,4 +1724,192 @@ mod tests {
1621
1724
  let proto_def = include_str!("../../sdk-core-protos/protos/grpc/health/v1/health.proto");
1622
1725
  verify_methods(proto_def, ALL_IMPLEMENTED_HEALTH_SERVICE_RPCS);
1623
1726
  }
1727
+
1728
+ #[tokio::test]
1729
+ async fn can_mock_services() {
1730
+ #[derive(Clone)]
1731
+ struct MyFakeServices {}
1732
+ impl RawGrpcCaller for MyFakeServices {}
1733
+ impl WorkflowService for MyFakeServices {
1734
+ fn list_namespaces(
1735
+ &mut self,
1736
+ _request: Request<ListNamespacesRequest>,
1737
+ ) -> BoxFuture<'_, Result<Response<ListNamespacesResponse>, Status>> {
1738
+ async {
1739
+ Ok(Response::new(ListNamespacesResponse {
1740
+ namespaces: vec![DescribeNamespaceResponse {
1741
+ failover_version: 12345,
1742
+ ..Default::default()
1743
+ }],
1744
+ ..Default::default()
1745
+ }))
1746
+ }
1747
+ .boxed()
1748
+ }
1749
+ }
1750
+ impl OperatorService for MyFakeServices {}
1751
+ impl CloudService for MyFakeServices {}
1752
+ impl TestService for MyFakeServices {}
1753
+ // Health service isn't possible to create a default impl for.
1754
+ impl HealthService for MyFakeServices {
1755
+ fn check(
1756
+ &mut self,
1757
+ _request: tonic::Request<HealthCheckRequest>,
1758
+ ) -> BoxFuture<'_, Result<tonic::Response<HealthCheckResponse>, tonic::Status>>
1759
+ {
1760
+ todo!()
1761
+ }
1762
+ fn watch(
1763
+ &mut self,
1764
+ _request: tonic::Request<HealthCheckRequest>,
1765
+ ) -> BoxFuture<
1766
+ '_,
1767
+ Result<
1768
+ tonic::Response<tonic::codec::Streaming<HealthCheckResponse>>,
1769
+ tonic::Status,
1770
+ >,
1771
+ > {
1772
+ todo!()
1773
+ }
1774
+ }
1775
+ let mut mocked_client = TemporalServiceClient::from_services(
1776
+ Box::new(MyFakeServices {}),
1777
+ Box::new(MyFakeServices {}),
1778
+ Box::new(MyFakeServices {}),
1779
+ Box::new(MyFakeServices {}),
1780
+ Box::new(MyFakeServices {}),
1781
+ );
1782
+ let r = mocked_client
1783
+ .list_namespaces(ListNamespacesRequest::default().into_request())
1784
+ .await
1785
+ .unwrap();
1786
+ assert_eq!(r.into_inner().namespaces[0].failover_version, 12345);
1787
+ }
1788
+
1789
+ #[rstest::rstest]
1790
+ #[case::with_versioning(true)]
1791
+ #[case::without_versioning(false)]
1792
+ #[tokio::test]
1793
+ async fn eager_reservations_attach_deployment_options(#[case] use_worker_versioning: bool) {
1794
+ use crate::worker_registry::{MockSlot, MockSlotProvider};
1795
+ use temporal_sdk_core_api::worker::{WorkerDeploymentOptions, WorkerDeploymentVersion};
1796
+ use temporal_sdk_core_protos::temporal::api::enums::v1::WorkerVersioningMode;
1797
+
1798
+ let expected_mode = if use_worker_versioning {
1799
+ WorkerVersioningMode::Versioned
1800
+ } else {
1801
+ WorkerVersioningMode::Unversioned
1802
+ };
1803
+
1804
+ #[derive(Clone)]
1805
+ struct MyFakeServices {
1806
+ slot_manager: Arc<SlotManager>,
1807
+ expected_mode: WorkerVersioningMode,
1808
+ }
1809
+ impl RawGrpcCaller for MyFakeServices {}
1810
+ impl RawClientProducer for MyFakeServices {
1811
+ fn get_workers_info(&self) -> Option<Arc<SlotManager>> {
1812
+ Some(self.slot_manager.clone())
1813
+ }
1814
+ fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
1815
+ Box::new(MyFakeWfClient {
1816
+ expected_mode: self.expected_mode,
1817
+ })
1818
+ }
1819
+ fn operator_client(&mut self) -> Box<dyn OperatorService> {
1820
+ unimplemented!()
1821
+ }
1822
+ fn cloud_client(&mut self) -> Box<dyn CloudService> {
1823
+ unimplemented!()
1824
+ }
1825
+ fn test_client(&mut self) -> Box<dyn TestService> {
1826
+ unimplemented!()
1827
+ }
1828
+ fn health_client(&mut self) -> Box<dyn HealthService> {
1829
+ unimplemented!()
1830
+ }
1831
+ }
1832
+
1833
+ let deployment_opts = WorkerDeploymentOptions {
1834
+ version: WorkerDeploymentVersion {
1835
+ deployment_name: "test-deployment".to_string(),
1836
+ build_id: "test-build-123".to_string(),
1837
+ },
1838
+ use_worker_versioning,
1839
+ default_versioning_behavior: None,
1840
+ };
1841
+
1842
+ let mut mock_provider = MockSlotProvider::new();
1843
+ mock_provider
1844
+ .expect_namespace()
1845
+ .return_const("test-namespace".to_string());
1846
+ mock_provider
1847
+ .expect_task_queue()
1848
+ .return_const("test-task-queue".to_string());
1849
+ let mut mock_slot = MockSlot::new();
1850
+ mock_slot.expect_schedule_wft().returning(|_| Ok(()));
1851
+ mock_provider
1852
+ .expect_try_reserve_wft_slot()
1853
+ .return_once(|| Some(Box::new(mock_slot)));
1854
+ mock_provider
1855
+ .expect_deployment_options()
1856
+ .return_const(Some(deployment_opts.clone()));
1857
+
1858
+ let slot_manager = Arc::new(SlotManager::new());
1859
+ slot_manager.register(Box::new(mock_provider));
1860
+
1861
+ #[derive(Clone)]
1862
+ struct MyFakeWfClient {
1863
+ expected_mode: WorkerVersioningMode,
1864
+ }
1865
+ impl WorkflowService for MyFakeWfClient {
1866
+ fn start_workflow_execution(
1867
+ &mut self,
1868
+ request: tonic::Request<StartWorkflowExecutionRequest>,
1869
+ ) -> BoxFuture<'_, Result<tonic::Response<StartWorkflowExecutionResponse>, tonic::Status>>
1870
+ {
1871
+ let req = request.into_inner();
1872
+ let expected_mode = self.expected_mode;
1873
+
1874
+ assert!(
1875
+ req.eager_worker_deployment_options.is_some(),
1876
+ "eager_worker_deployment_options should be populated"
1877
+ );
1878
+
1879
+ let opts = req.eager_worker_deployment_options.as_ref().unwrap();
1880
+ assert_eq!(opts.deployment_name, "test-deployment");
1881
+ assert_eq!(opts.build_id, "test-build-123");
1882
+ assert_eq!(opts.worker_versioning_mode, expected_mode as i32);
1883
+
1884
+ async { Ok(Response::new(StartWorkflowExecutionResponse::default())) }.boxed()
1885
+ }
1886
+ }
1887
+
1888
+ let mut mfs = MyFakeServices {
1889
+ slot_manager,
1890
+ expected_mode,
1891
+ };
1892
+
1893
+ // Create a request with eager execution enabled
1894
+ let req = StartWorkflowExecutionRequest {
1895
+ namespace: "test-namespace".to_string(),
1896
+ workflow_id: "test-wf-id".to_string(),
1897
+ workflow_type: Some(
1898
+ temporal_sdk_core_protos::temporal::api::common::v1::WorkflowType {
1899
+ name: "test-workflow".to_string(),
1900
+ },
1901
+ ),
1902
+ task_queue: Some(TaskQueue {
1903
+ name: "test-task-queue".to_string(),
1904
+ kind: 0,
1905
+ normal_name: String::new(),
1906
+ }),
1907
+ request_eager_execution: true,
1908
+ ..Default::default()
1909
+ };
1910
+
1911
+ mfs.start_workflow_execution(req.into_request())
1912
+ .await
1913
+ .unwrap();
1914
+ }
1624
1915
  }