@temporalio/core-bridge 1.15.0 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/Cargo.lock +172 -70
  2. package/lib/native.d.ts +1 -1
  3. package/package.json +2 -2
  4. package/releases/aarch64-apple-darwin/index.node +0 -0
  5. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  6. package/releases/x86_64-apple-darwin/index.node +0 -0
  7. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  8. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  9. package/sdk-core/.github/workflows/per-pr.yml +6 -6
  10. package/sdk-core/AGENTS.md +41 -30
  11. package/sdk-core/Cargo.toml +3 -0
  12. package/sdk-core/README.md +15 -9
  13. package/sdk-core/crates/client/Cargo.toml +4 -0
  14. package/sdk-core/crates/client/README.md +139 -0
  15. package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
  16. package/sdk-core/crates/client/src/callback_based.rs +7 -0
  17. package/sdk-core/crates/client/src/errors.rs +294 -0
  18. package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +280 -159
  19. package/sdk-core/crates/client/src/lib.rs +920 -1326
  20. package/sdk-core/crates/client/src/metrics.rs +24 -33
  21. package/sdk-core/crates/client/src/options_structs.rs +457 -0
  22. package/sdk-core/crates/client/src/replaceable.rs +5 -4
  23. package/sdk-core/crates/client/src/request_extensions.rs +8 -9
  24. package/sdk-core/crates/client/src/retry.rs +99 -54
  25. package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +1 -1
  26. package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
  27. package/sdk-core/crates/common/Cargo.toml +61 -2
  28. package/sdk-core/crates/common/build.rs +742 -12
  29. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
  30. package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
  31. package/sdk-core/crates/common/protos/api_upstream/buf.yaml +0 -3
  32. package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
  33. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +1166 -770
  34. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +1243 -750
  35. package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +2 -2
  36. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +4 -3
  37. package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
  38. package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +4 -0
  39. package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
  40. package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +16 -1
  41. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -6
  42. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +88 -33
  43. package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +4 -2
  44. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +4 -0
  45. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +5 -5
  46. package/sdk-core/crates/common/src/activity_definition.rs +20 -0
  47. package/sdk-core/crates/common/src/data_converters.rs +770 -0
  48. package/sdk-core/crates/common/src/envconfig.rs +5 -0
  49. package/sdk-core/crates/common/src/lib.rs +15 -211
  50. package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
  51. package/sdk-core/crates/common/src/priority.rs +110 -0
  52. package/sdk-core/crates/common/src/protos/canned_histories.rs +3 -0
  53. package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
  54. package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
  55. package/sdk-core/crates/common/src/protos/mod.rs +122 -27
  56. package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
  57. package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
  58. package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +5 -7
  59. package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
  60. package/sdk-core/crates/common/src/telemetry/metrics.rs +268 -223
  61. package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
  62. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
  63. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
  64. package/sdk-core/crates/common/src/telemetry.rs +264 -4
  65. package/sdk-core/crates/common/src/worker.rs +68 -603
  66. package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
  67. package/sdk-core/crates/macros/Cargo.toml +5 -1
  68. package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
  69. package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
  70. package/sdk-core/crates/macros/src/lib.rs +138 -512
  71. package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
  72. package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
  73. package/sdk-core/crates/sdk/Cargo.toml +19 -6
  74. package/sdk-core/crates/sdk/README.md +415 -0
  75. package/sdk-core/crates/sdk/src/activities.rs +417 -0
  76. package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
  77. package/sdk-core/crates/sdk/src/lib.rs +757 -442
  78. package/sdk-core/crates/sdk/src/workflow_context/options.rs +45 -35
  79. package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
  80. package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
  81. package/sdk-core/crates/sdk/src/workflows.rs +711 -0
  82. package/sdk-core/crates/sdk-core/Cargo.toml +57 -64
  83. package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +41 -35
  84. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
  85. package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
  86. package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
  87. package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +13 -15
  88. package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
  89. package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
  90. package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
  91. package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +493 -26
  92. package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +4 -8
  93. package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +7 -7
  94. package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
  95. package/sdk-core/crates/sdk-core/src/lib.rs +41 -111
  96. package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
  97. package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +118 -19
  98. package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
  99. package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
  100. package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +179 -196
  101. package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -280
  102. package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +6 -9
  103. package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
  104. package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
  105. package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
  106. package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +9 -5
  107. package/sdk-core/crates/sdk-core/src/worker/client.rs +103 -81
  108. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +7 -11
  109. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1124 -229
  110. package/sdk-core/crates/sdk-core/src/worker/nexus.rs +145 -23
  111. package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
  112. package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
  113. package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +13 -13
  114. package/sdk-core/crates/sdk-core/src/worker/tuner.rs +28 -8
  115. package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
  116. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
  117. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +19 -4
  118. package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +14 -18
  119. package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +4 -6
  120. package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
  121. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
  122. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
  123. package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
  124. package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
  125. package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
  126. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
  127. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
  128. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
  129. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
  130. package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
  131. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
  132. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
  133. package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
  134. package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
  135. package/sdk-core/crates/sdk-core/tests/common/mod.rs +241 -196
  136. package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
  137. package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +3 -5
  138. package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -64
  139. package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +298 -252
  140. package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
  141. package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
  142. package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
  143. package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +16 -12
  144. package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +48 -40
  145. package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +327 -255
  146. package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
  147. package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +147 -126
  148. package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
  149. package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -453
  150. package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
  151. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +360 -231
  152. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +248 -185
  153. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -43
  154. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
  155. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +428 -315
  156. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -56
  157. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -28
  158. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -243
  159. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
  160. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +101 -42
  161. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -147
  162. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -28
  163. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1036
  164. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -41
  165. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +397 -238
  166. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +414 -189
  167. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
  168. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
  169. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +154 -137
  170. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -105
  171. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -38
  172. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -40
  173. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -54
  174. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +363 -226
  175. package/sdk-core/crates/sdk-core/tests/main.rs +17 -15
  176. package/sdk-core/crates/sdk-core/tests/manual_tests.rs +207 -152
  177. package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +65 -34
  178. package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
  179. package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
  180. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
  181. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
  182. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
  183. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
  184. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
  185. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
  186. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
  187. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
  188. package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +7 -1
  189. package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +14 -14
  190. package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +83 -74
  191. package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +9 -14
  192. package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +1 -2
  193. package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +13 -13
  194. package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +6 -6
  195. package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +3 -4
  196. package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +62 -75
  197. package/sdk-core/rustfmt.toml +2 -1
  198. package/src/client.rs +205 -318
  199. package/src/metrics.rs +22 -30
  200. package/src/runtime.rs +4 -5
  201. package/src/worker.rs +16 -19
  202. package/ts/native.ts +1 -1
  203. package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
  204. package/sdk-core/crates/common/src/errors.rs +0 -85
  205. package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
  206. package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
  207. package/sdk-core/crates/sdk/src/app_data.rs +0 -37
  208. package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
  209. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
@@ -1,11 +1,14 @@
1
- //! We need a way to trait-ify the raw grpc client because there is no other way to get the
2
- //! information we need via interceptors. This module contains the necessary stuff to make that
3
- //! happen.
1
+ //! gRPC service traits for direct access to Temporal services.
2
+ //!
3
+ //! Most users should use the higher-level methods on [`Client`] or [`Connection`] instead.
4
+ //! These traits are useful for advanced scenarios like custom interceptors, testing with mocks,
5
+ //! or making raw gRPC calls not covered by the higher-level API.
4
6
 
5
7
  use crate::{
6
- Client, ConfiguredClient, LONG_POLL_TIMEOUT, RequestExt, RetryClient, SharedReplaceableClient,
8
+ Client, Connection, LONG_POLL_TIMEOUT, RequestExt, SharedReplaceableClient,
7
9
  TEMPORAL_NAMESPACE_HEADER_KEY, TemporalServiceClient,
8
10
  metrics::namespace_kv,
11
+ retry::make_future_retry,
9
12
  worker::{ClientWorkerSet, Slot},
10
13
  };
11
14
  use dyn_clone::DynClone;
@@ -32,7 +35,7 @@ use tonic::{
32
35
  };
33
36
 
34
37
  /// Something that has access to the raw grpc services
35
- trait RawClientProducer {
38
+ pub(crate) trait RawClientProducer {
36
39
  /// Returns information about workers associated with this client. Implementers outside of
37
40
  /// core can safely return `None`.
38
41
  fn get_workers_info(&self) -> Option<Arc<ClientWorkerSet>>;
@@ -54,10 +57,10 @@ trait RawClientProducer {
54
57
  }
55
58
 
56
59
  /// Any client that can make gRPC calls. The default implementation simply invokes the passed-in
57
- /// function. Implementers may override this to provide things like retry behavior, ex:
58
- /// [RetryClient].
60
+ /// function. Implementers may override this to provide things like retry behavior.
59
61
  #[async_trait::async_trait]
60
- trait RawGrpcCaller: Send + Sync + 'static {
62
+ pub(crate) trait RawGrpcCaller: Send + Sync + 'static {
63
+ /// Make a gRPC call. The default implementation simply invokes the provided function.
61
64
  async fn call<F, Req, Resp>(
62
65
  &mut self,
63
66
  _call_name: &'static str,
@@ -67,11 +70,10 @@ trait RawGrpcCaller: Send + Sync + 'static {
67
70
  where
68
71
  Req: Clone + Unpin + Send + Sync + 'static,
69
72
  Resp: Send + 'static,
73
+ F: FnMut(Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
70
74
  F: Send + Sync + Unpin + 'static,
71
- for<'a> F:
72
- FnMut(&'a mut Self, Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
73
75
  {
74
- callfn(self, req).await
76
+ callfn(req).await
75
77
  }
76
78
  }
77
79
 
@@ -110,19 +112,15 @@ impl<F, Req, Resp> ErasedCallOp for CallShim<F, Req, Resp>
110
112
  where
111
113
  Req: Clone + Unpin + Send + Sync + 'static,
112
114
  Resp: Send + 'static,
115
+ F: FnMut(Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
113
116
  F: Send + Sync + Unpin + 'static,
114
- for<'a> F: FnMut(
115
- &'a mut dyn ErasedRawClient,
116
- Request<Req>,
117
- ) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
118
117
  {
119
118
  fn invoke(
120
119
  &mut self,
121
- raw: &mut dyn ErasedRawClient,
120
+ _raw: &mut dyn ErasedRawClient,
122
121
  _call_name: &'static str,
123
122
  ) -> BoxFuture<'static, Result<Response<Box<dyn Any + Send>>, Status>> {
124
123
  (self.callfn)(
125
- raw,
126
124
  self.seed_req
127
125
  .take()
128
126
  .expect("CallShim must have request populated"),
@@ -133,80 +131,7 @@ where
133
131
  }
134
132
 
135
133
  #[async_trait::async_trait]
136
- impl RawGrpcCaller for dyn ErasedRawClient {
137
- async fn call<F, Req, Resp>(
138
- &mut self,
139
- call_name: &'static str,
140
- callfn: F,
141
- req: Request<Req>,
142
- ) -> Result<Response<Resp>, Status>
143
- where
144
- Req: Clone + Unpin + Send + Sync + 'static,
145
- Resp: Send + 'static,
146
- F: Send + Sync + Unpin + 'static,
147
- for<'a> F: FnMut(
148
- &'a mut dyn ErasedRawClient,
149
- Request<Req>,
150
- ) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
151
- {
152
- let mut shim = CallShim::new(callfn, req);
153
- let erased_resp = ErasedRawClient::erased_call(self, call_name, &mut shim).await?;
154
- Ok(erased_resp.map(|boxed| {
155
- *boxed
156
- .downcast()
157
- .expect("RawGrpcCaller erased response type mismatch")
158
- }))
159
- }
160
- }
161
-
162
- impl<T> ErasedRawClient for T
163
- where
164
- T: RawGrpcCaller + 'static,
165
- {
166
- fn erased_call(
167
- &mut self,
168
- call_name: &'static str,
169
- op: &mut dyn ErasedCallOp,
170
- ) -> BoxFuture<'static, Result<Response<Box<dyn Any + Send>>, Status>> {
171
- let raw: &mut dyn ErasedRawClient = self;
172
- op.invoke(raw, call_name)
173
- }
174
- }
175
-
176
- impl<RC> RawClientProducer for RetryClient<RC>
177
- where
178
- RC: RawClientProducer + 'static,
179
- {
180
- fn get_workers_info(&self) -> Option<Arc<ClientWorkerSet>> {
181
- self.get_client().get_workers_info()
182
- }
183
-
184
- fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
185
- self.get_client_mut().workflow_client()
186
- }
187
-
188
- fn operator_client(&mut self) -> Box<dyn OperatorService> {
189
- self.get_client_mut().operator_client()
190
- }
191
-
192
- fn cloud_client(&mut self) -> Box<dyn CloudService> {
193
- self.get_client_mut().cloud_client()
194
- }
195
-
196
- fn test_client(&mut self) -> Box<dyn TestService> {
197
- self.get_client_mut().test_client()
198
- }
199
-
200
- fn health_client(&mut self) -> Box<dyn HealthService> {
201
- self.get_client_mut().health_client()
202
- }
203
- }
204
-
205
- #[async_trait::async_trait]
206
- impl<RC> RawGrpcCaller for RetryClient<RC>
207
- where
208
- RC: RawGrpcCaller + 'static,
209
- {
134
+ impl RawGrpcCaller for Connection {
210
135
  async fn call<F, Req, Resp>(
211
136
  &mut self,
212
137
  call_name: &'static str,
@@ -215,19 +140,25 @@ where
215
140
  ) -> Result<Response<Resp>, Status>
216
141
  where
217
142
  Req: Clone + Unpin + Send + Sync + 'static,
218
- F: FnMut(&mut Self, Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
143
+ Resp: Send + 'static,
144
+ F: FnMut(Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
219
145
  F: Send + Sync + Unpin + 'static,
220
146
  {
221
- let info = self.get_call_info(call_name, Some(&req));
147
+ let info = self
148
+ .inner
149
+ .retry_options
150
+ .get_call_info(call_name, Some(&req));
222
151
  req.extensions_mut().insert(info.call_type);
223
152
  if info.call_type.is_long() {
224
153
  req.set_default_timeout(LONG_POLL_TIMEOUT);
225
154
  }
155
+
226
156
  let fact = || {
227
157
  let req_clone = req_cloner(&req);
228
- callfn(self, req_clone)
158
+ callfn(req_clone)
229
159
  };
230
- let res = Self::make_future_retry(info, fact);
160
+
161
+ let res = make_future_retry(info, fact);
231
162
  res.map_err(|(e, _attempt)| e).map_ok(|x| x.0).await
232
163
  }
233
164
  }
@@ -251,123 +182,192 @@ fn req_cloner<T: Clone>(cloneme: &Request<T>) -> Request<T> {
251
182
  new_req
252
183
  }
253
184
 
254
- impl<RC> RawClientProducer for SharedReplaceableClient<RC>
185
+ #[async_trait::async_trait]
186
+ impl RawGrpcCaller for dyn ErasedRawClient {
187
+ async fn call<F, Req, Resp>(
188
+ &mut self,
189
+ call_name: &'static str,
190
+ callfn: F,
191
+ req: Request<Req>,
192
+ ) -> Result<Response<Resp>, Status>
193
+ where
194
+ Req: Clone + Unpin + Send + Sync + 'static,
195
+ Resp: Send + 'static,
196
+ F: FnMut(Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
197
+ F: Send + Sync + Unpin + 'static,
198
+ {
199
+ let mut shim = CallShim::new(callfn, req);
200
+ let erased_resp = ErasedRawClient::erased_call(self, call_name, &mut shim).await?;
201
+ Ok(erased_resp.map(|boxed| {
202
+ *boxed
203
+ .downcast()
204
+ .expect("RawGrpcCaller erased response type mismatch")
205
+ }))
206
+ }
207
+ }
208
+
209
+ impl<T> ErasedRawClient for T
255
210
  where
256
- RC: RawClientProducer + Clone + Send + Sync + 'static,
211
+ T: RawGrpcCaller + 'static,
257
212
  {
213
+ fn erased_call(
214
+ &mut self,
215
+ call_name: &'static str,
216
+ op: &mut dyn ErasedCallOp,
217
+ ) -> BoxFuture<'static, Result<Response<Box<dyn Any + Send>>, Status>> {
218
+ let raw: &mut dyn ErasedRawClient = self;
219
+ op.invoke(raw, call_name)
220
+ }
221
+ }
222
+
223
+ impl RawClientProducer for Connection {
258
224
  fn get_workers_info(&self) -> Option<Arc<ClientWorkerSet>> {
259
- self.inner_cow().get_workers_info()
225
+ Some(self.workers())
260
226
  }
227
+
261
228
  fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
262
- self.inner_mut_refreshed().workflow_client()
229
+ self.inner.service.workflow_service()
263
230
  }
264
231
 
265
232
  fn operator_client(&mut self) -> Box<dyn OperatorService> {
266
- self.inner_mut_refreshed().operator_client()
233
+ self.inner.service.operator_service()
267
234
  }
268
235
 
269
236
  fn cloud_client(&mut self) -> Box<dyn CloudService> {
270
- self.inner_mut_refreshed().cloud_client()
237
+ self.inner.service.cloud_service()
271
238
  }
272
239
 
273
240
  fn test_client(&mut self) -> Box<dyn TestService> {
274
- self.inner_mut_refreshed().test_client()
241
+ self.inner.service.test_service()
275
242
  }
276
243
 
277
244
  fn health_client(&mut self) -> Box<dyn HealthService> {
278
- self.inner_mut_refreshed().health_client()
245
+ self.inner.service.health_service()
279
246
  }
280
247
  }
281
248
 
282
- #[async_trait::async_trait]
283
- impl<RC> RawGrpcCaller for SharedReplaceableClient<RC> where
284
- RC: RawGrpcCaller + Clone + Sync + 'static
285
- {
286
- }
287
-
288
249
  impl RawClientProducer for TemporalServiceClient {
289
250
  fn get_workers_info(&self) -> Option<Arc<ClientWorkerSet>> {
290
251
  None
291
252
  }
292
253
 
293
254
  fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
294
- self.workflow_svc()
255
+ self.workflow_service()
295
256
  }
296
257
 
297
258
  fn operator_client(&mut self) -> Box<dyn OperatorService> {
298
- self.operator_svc()
259
+ self.operator_service()
299
260
  }
300
261
 
301
262
  fn cloud_client(&mut self) -> Box<dyn CloudService> {
302
- self.cloud_svc()
263
+ self.cloud_service()
303
264
  }
304
265
 
305
266
  fn test_client(&mut self) -> Box<dyn TestService> {
306
- self.test_svc()
267
+ self.test_service()
307
268
  }
308
269
 
309
270
  fn health_client(&mut self) -> Box<dyn HealthService> {
310
- self.health_svc()
271
+ self.health_service()
311
272
  }
312
273
  }
313
274
 
314
275
  impl RawGrpcCaller for TemporalServiceClient {}
315
276
 
316
- impl RawClientProducer for ConfiguredClient<TemporalServiceClient> {
277
+ impl RawClientProducer for Client {
317
278
  fn get_workers_info(&self) -> Option<Arc<ClientWorkerSet>> {
318
- Some(self.workers())
279
+ Some(self.connection.workers())
319
280
  }
320
281
 
321
282
  fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
322
- self.client.workflow_client()
283
+ self.connection.workflow_client()
323
284
  }
324
285
 
325
286
  fn operator_client(&mut self) -> Box<dyn OperatorService> {
326
- self.client.operator_client()
287
+ self.connection.operator_client()
327
288
  }
328
289
 
329
290
  fn cloud_client(&mut self) -> Box<dyn CloudService> {
330
- self.client.cloud_client()
291
+ self.connection.cloud_client()
331
292
  }
332
293
 
333
294
  fn test_client(&mut self) -> Box<dyn TestService> {
334
- self.client.test_client()
295
+ self.connection.test_client()
335
296
  }
336
297
 
337
298
  fn health_client(&mut self) -> Box<dyn HealthService> {
338
- self.client.health_client()
299
+ self.connection.health_client()
339
300
  }
340
301
  }
341
302
 
342
- impl RawGrpcCaller for ConfiguredClient<TemporalServiceClient> {}
303
+ #[async_trait::async_trait]
304
+ impl RawGrpcCaller for Client {
305
+ async fn call<F, Req, Resp>(
306
+ &mut self,
307
+ call_name: &'static str,
308
+ callfn: F,
309
+ req: Request<Req>,
310
+ ) -> Result<Response<Resp>, Status>
311
+ where
312
+ Req: Clone + Unpin + Send + Sync + 'static,
313
+ Resp: Send + 'static,
314
+ F: FnMut(Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
315
+ F: Send + Sync + Unpin + 'static,
316
+ {
317
+ self.connection.call(call_name, callfn, req).await
318
+ }
319
+ }
343
320
 
344
- impl RawClientProducer for Client {
321
+ impl<RC> RawClientProducer for SharedReplaceableClient<RC>
322
+ where
323
+ RC: RawClientProducer + Clone + Send + Sync + 'static,
324
+ {
345
325
  fn get_workers_info(&self) -> Option<Arc<ClientWorkerSet>> {
346
- self.inner.get_workers_info()
326
+ self.inner_cow().get_workers_info()
347
327
  }
348
-
349
328
  fn workflow_client(&mut self) -> Box<dyn WorkflowService> {
350
- self.inner.workflow_client()
329
+ self.inner_mut_refreshed().workflow_client()
351
330
  }
352
331
 
353
332
  fn operator_client(&mut self) -> Box<dyn OperatorService> {
354
- self.inner.operator_client()
333
+ self.inner_mut_refreshed().operator_client()
355
334
  }
356
335
 
357
336
  fn cloud_client(&mut self) -> Box<dyn CloudService> {
358
- self.inner.cloud_client()
337
+ self.inner_mut_refreshed().cloud_client()
359
338
  }
360
339
 
361
340
  fn test_client(&mut self) -> Box<dyn TestService> {
362
- self.inner.test_client()
341
+ self.inner_mut_refreshed().test_client()
363
342
  }
364
343
 
365
344
  fn health_client(&mut self) -> Box<dyn HealthService> {
366
- self.inner.health_client()
345
+ self.inner_mut_refreshed().health_client()
367
346
  }
368
347
  }
369
348
 
370
- impl RawGrpcCaller for Client {}
349
+ #[async_trait::async_trait]
350
+ impl<RC> RawGrpcCaller for SharedReplaceableClient<RC>
351
+ where
352
+ RC: RawGrpcCaller + Clone + Sync + 'static,
353
+ {
354
+ async fn call<F, Req, Resp>(
355
+ &mut self,
356
+ call_name: &'static str,
357
+ callfn: F,
358
+ req: Request<Req>,
359
+ ) -> Result<Response<Resp>, Status>
360
+ where
361
+ Req: Clone + Unpin + Send + Sync + 'static,
362
+ Resp: Send + 'static,
363
+ F: FnMut(Request<Req>) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
364
+ F: Send + Sync + Unpin + 'static,
365
+ {
366
+ self.inner_mut_refreshed()
367
+ .call(call_name, callfn, req)
368
+ .await
369
+ }
370
+ }
371
371
 
372
372
  #[derive(Clone, Debug)]
373
373
  pub(super) struct AttachMetricLabels {
@@ -426,6 +426,7 @@ macro_rules! proxy_def {
426
426
  ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>>;
427
427
  };
428
428
  }
429
+
429
430
  /// Helps re-declare gRPC client methods
430
431
  ///
431
432
  /// There are four forms:
@@ -447,9 +448,10 @@ macro_rules! proxy_impl {
447
448
  mut request: tonic::Request<$req>,
448
449
  ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>> {
449
450
  $( type_closure_arg(&mut request, $closure); )*
451
+ let mut self_clone = self.clone();
450
452
  #[allow(unused_mut)]
451
- let fact = |c: &mut Self, mut req: tonic::Request<$req>| {
452
- let mut c = c.$client_meth();
453
+ let fact = move |mut req: tonic::Request<$req>| {
454
+ let mut c = self_clone.$client_meth();
453
455
  async move { c.$method(req).await }.boxed()
454
456
  };
455
457
  self.call(stringify!($method), fact, request)
@@ -463,10 +465,12 @@ macro_rules! proxy_impl {
463
465
  mut request: tonic::Request<$req>,
464
466
  ) -> BoxFuture<'_, Result<tonic::Response<$resp>, tonic::Status>> {
465
467
  type_closure_arg(&mut request, $closure_request);
468
+ let workers_info = self.get_workers_info();
469
+ let mut self_clone = self.clone();
466
470
  #[allow(unused_mut)]
467
- let fact = |c: &mut Self, mut req: tonic::Request<$req>| {
468
- let data = type_closure_two_arg(&mut req, c.get_workers_info(), $closure_before);
469
- let mut c = c.$client_meth();
471
+ let fact = move |mut req: tonic::Request<$req>| {
472
+ let data = type_closure_two_arg(&mut req, workers_info.clone(), $closure_before);
473
+ let mut c = self_clone.$client_meth();
470
474
  async move {
471
475
  type_closure_two_arg(c.$method(req).await, data, $closure_after)
472
476
  }.boxed()
@@ -519,7 +523,7 @@ macro_rules! proxier_impl {
519
523
 
520
524
  impl<RC> $trait_name for RC
521
525
  where
522
- RC: RawGrpcCaller + RawClientProducer + Clone,
526
+ RC: RawGrpcCaller + RawClientProducer + Clone + Unpin,
523
527
  {
524
528
  $(
525
529
  proxy_impl!($client_type, $client_meth, $method, $req, $resp
@@ -1102,6 +1106,15 @@ proxier! {
1102
1106
  r.extensions_mut().insert(labels);
1103
1107
  }
1104
1108
  );
1109
+ (
1110
+ count_schedules,
1111
+ CountSchedulesRequest,
1112
+ CountSchedulesResponse,
1113
+ |r| {
1114
+ let labels = namespaced_request!(r);
1115
+ r.extensions_mut().insert(labels);
1116
+ }
1117
+ );
1105
1118
  (
1106
1119
  update_worker_build_id_compatibility,
1107
1120
  UpdateWorkerBuildIdCompatibilityRequest,
@@ -1688,7 +1701,7 @@ proxier! {
1688
1701
  #[cfg(test)]
1689
1702
  mod tests {
1690
1703
  use super::*;
1691
- use crate::{ClientOptions, RetryClient};
1704
+ use crate::{ClientOptions, ConnectionOptions};
1692
1705
  use std::collections::HashSet;
1693
1706
  use temporalio_common::{
1694
1707
  protos::temporal::api::{
@@ -1703,63 +1716,62 @@ mod tests {
1703
1716
  // Just to help make sure some stuff compiles. Not run.
1704
1717
  #[allow(dead_code)]
1705
1718
  async fn raw_client_retry_compiles() {
1706
- let opts = ClientOptions::builder()
1707
- .target_url(Url::parse("http://localhost:7233").unwrap())
1719
+ let opts = ConnectionOptions::new(Url::parse("http://localhost:7233").unwrap())
1708
1720
  .client_name("test")
1709
1721
  .client_version("0.0.0")
1710
1722
  .build();
1711
- let raw_client = opts.connect_no_namespace(None).await.unwrap();
1712
- let mut retry_client = RetryClient::new(raw_client, opts.retry_options);
1723
+ let connection = Connection::connect(opts).await.unwrap();
1724
+ let mut client = Client::new(connection, ClientOptions::new("default").build()).unwrap();
1713
1725
 
1714
1726
  let list_ns_req = ListNamespacesRequest::default();
1715
- let fact = |c: &mut RetryClient<_>, req| {
1716
- let mut c = c.workflow_client();
1727
+ let wf_client = client.workflow_client();
1728
+ let fact = move |req| {
1729
+ let mut c = wf_client.clone();
1717
1730
  async move { c.list_namespaces(req).await }.boxed()
1718
1731
  };
1719
- retry_client
1732
+ client
1720
1733
  .call("whatever", fact, Request::new(list_ns_req.clone()))
1721
1734
  .await
1722
1735
  .unwrap();
1723
1736
 
1724
1737
  // Operator svc method
1725
1738
  let op_del_ns_req = DeleteNamespaceRequest::default();
1726
- let fact = |c: &mut RetryClient<_>, req| {
1727
- let mut c = c.operator_client();
1739
+ let op_client = client.operator_client();
1740
+ let fact = move |req| {
1741
+ let mut c = op_client.clone();
1728
1742
  async move { c.delete_namespace(req).await }.boxed()
1729
1743
  };
1730
- retry_client
1744
+ client
1731
1745
  .call("whatever", fact, Request::new(op_del_ns_req.clone()))
1732
1746
  .await
1733
1747
  .unwrap();
1734
1748
 
1735
1749
  // Cloud svc method
1736
1750
  let cloud_del_ns_req = cloudreq::DeleteNamespaceRequest::default();
1737
- let fact = |c: &mut RetryClient<_>, req| {
1738
- let mut c = c.cloud_client();
1751
+ let cloud_client = client.cloud_client();
1752
+ let fact = move |req| {
1753
+ let mut c = cloud_client.clone();
1739
1754
  async move { c.delete_namespace(req).await }.boxed()
1740
1755
  };
1741
- retry_client
1756
+ client
1742
1757
  .call("whatever", fact, Request::new(cloud_del_ns_req.clone()))
1743
1758
  .await
1744
1759
  .unwrap();
1745
1760
 
1746
1761
  // Verify calling through traits works
1747
- retry_client
1762
+ client
1748
1763
  .list_namespaces(list_ns_req.into_request())
1749
1764
  .await
1750
1765
  .unwrap();
1751
1766
  // Have to disambiguate operator and cloud service
1752
- OperatorService::delete_namespace(&mut retry_client, op_del_ns_req.into_request())
1753
- .await
1754
- .unwrap();
1755
- CloudService::delete_namespace(&mut retry_client, cloud_del_ns_req.into_request())
1767
+ OperatorService::delete_namespace(&mut client, op_del_ns_req.into_request())
1756
1768
  .await
1757
1769
  .unwrap();
1758
- retry_client
1759
- .get_current_time(().into_request())
1770
+ CloudService::delete_namespace(&mut client, cloud_del_ns_req.into_request())
1760
1771
  .await
1761
1772
  .unwrap();
1762
- retry_client
1773
+ client.get_current_time(().into_request()).await.unwrap();
1774
+ client
1763
1775
  .check(HealthCheckRequest::default().into_request())
1764
1776
  .await
1765
1777
  .unwrap();
@@ -2031,4 +2043,113 @@ mod tests {
2031
2043
  .await
2032
2044
  .unwrap();
2033
2045
  }
2046
+
2047
+ /// Tests that Connection's RawClientProducer impl correctly provides worker info
2048
+ /// so that eager workflow start can reserve a slot and dispatch the WFT.
2049
+ #[tokio::test]
2050
+ async fn connection_eager_start_dispatches_wft() {
2051
+ use crate::{
2052
+ ConnectionOptions,
2053
+ callback_based::{CallbackBasedGrpcService, GrpcSuccessResponse},
2054
+ worker::{MockClientWorker, MockSlot},
2055
+ };
2056
+ use prost::Message;
2057
+ use std::sync::atomic::{AtomicBool, Ordering};
2058
+ use temporalio_common::protos::temporal::api::workflowservice::v1::PollWorkflowTaskQueueResponse;
2059
+
2060
+ let dispatched = Arc::new(AtomicBool::new(false));
2061
+ let dispatched_clone = dispatched.clone();
2062
+
2063
+ // Create a callback-based service that returns an eager_workflow_task in the response
2064
+ let service_override = CallbackBasedGrpcService {
2065
+ callback: Arc::new(|_req| {
2066
+ Box::pin(async {
2067
+ let resp = StartWorkflowExecutionResponse {
2068
+ run_id: "test-run-id".to_string(),
2069
+ eager_workflow_task: Some(PollWorkflowTaskQueueResponse {
2070
+ task_token: vec![1, 2, 3],
2071
+ ..Default::default()
2072
+ }),
2073
+ ..Default::default()
2074
+ };
2075
+ let proto = resp.encode_to_vec();
2076
+ Ok(GrpcSuccessResponse {
2077
+ headers: Default::default(),
2078
+ proto,
2079
+ })
2080
+ })
2081
+ }),
2082
+ };
2083
+
2084
+ let opts = ConnectionOptions::new(url::Url::parse("http://localhost:7233").unwrap())
2085
+ .skip_get_system_info(true)
2086
+ .service_override(service_override)
2087
+ .build();
2088
+ let mut connection = crate::Connection::connect(opts).await.unwrap();
2089
+
2090
+ // Register a mock worker on the connection's worker set
2091
+ let mut mock_worker = MockClientWorker::new();
2092
+ mock_worker
2093
+ .expect_namespace()
2094
+ .return_const("default".to_string());
2095
+ mock_worker
2096
+ .expect_task_queue()
2097
+ .return_const("test-tq".to_string());
2098
+ mock_worker
2099
+ .expect_deployment_options()
2100
+ .return_const(None::<temporalio_common::worker::WorkerDeploymentOptions>);
2101
+ mock_worker.expect_heartbeat_enabled().return_const(false);
2102
+ let uuid = Uuid::new_v4();
2103
+ mock_worker.expect_worker_instance_key().return_const(uuid);
2104
+ mock_worker
2105
+ .expect_worker_task_types()
2106
+ .return_const(WorkerTaskTypes {
2107
+ enable_workflows: true,
2108
+ enable_local_activities: false,
2109
+ enable_remote_activities: false,
2110
+ enable_nexus: false,
2111
+ });
2112
+
2113
+ let mut mock_slot = MockSlot::new();
2114
+ mock_slot.expect_schedule_wft().returning(move |_| {
2115
+ dispatched_clone.store(true, Ordering::SeqCst);
2116
+ Ok(())
2117
+ });
2118
+ mock_worker
2119
+ .expect_try_reserve_wft_slot()
2120
+ .return_once(|| Some(Box::new(mock_slot)));
2121
+
2122
+ connection
2123
+ .workers()
2124
+ .register_worker(Arc::new(mock_worker), true)
2125
+ .unwrap();
2126
+
2127
+ // Make an eager start_workflow_execution call through Connection
2128
+ let req = StartWorkflowExecutionRequest {
2129
+ namespace: "default".to_string(),
2130
+ workflow_id: "test-wf".to_string(),
2131
+ workflow_type: Some(
2132
+ temporalio_common::protos::temporal::api::common::v1::WorkflowType {
2133
+ name: "test-workflow".to_string(),
2134
+ },
2135
+ ),
2136
+ task_queue: Some(TaskQueue {
2137
+ name: "test-tq".to_string(),
2138
+ kind: 0,
2139
+ normal_name: String::new(),
2140
+ }),
2141
+ request_eager_execution: true,
2142
+ ..Default::default()
2143
+ };
2144
+
2145
+ connection
2146
+ .start_workflow_execution(req.into_request())
2147
+ .await
2148
+ .unwrap();
2149
+
2150
+ assert!(
2151
+ dispatched.load(Ordering::SeqCst),
2152
+ "Eager workflow task should have been dispatched to the worker"
2153
+ );
2154
+ }
2034
2155
  }