@temporalio/core-bridge 0.19.2 → 0.20.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 (125) hide show
  1. package/Cargo.lock +90 -157
  2. package/Cargo.toml +1 -0
  3. package/index.d.ts +11 -27
  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/.buildkite/docker/Dockerfile +1 -1
  11. package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
  12. package/sdk-core/.cargo/config.toml +1 -0
  13. package/sdk-core/CODEOWNERS +1 -1
  14. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +119 -86
  15. package/sdk-core/bridge-ffi/src/lib.rs +311 -315
  16. package/sdk-core/bridge-ffi/src/wrappers.rs +108 -113
  17. package/sdk-core/client/Cargo.toml +13 -9
  18. package/sdk-core/client/LICENSE.txt +23 -0
  19. package/sdk-core/client/src/lib.rs +286 -174
  20. package/sdk-core/client/src/metrics.rs +86 -12
  21. package/sdk-core/client/src/raw.rs +566 -0
  22. package/sdk-core/client/src/retry.rs +137 -99
  23. package/sdk-core/core/Cargo.toml +15 -10
  24. package/sdk-core/core/LICENSE.txt +23 -0
  25. package/sdk-core/core/benches/workflow_replay.rs +79 -0
  26. package/sdk-core/core/src/abstractions.rs +38 -0
  27. package/sdk-core/core/src/core_tests/activity_tasks.rs +108 -182
  28. package/sdk-core/core/src/core_tests/child_workflows.rs +16 -11
  29. package/sdk-core/core/src/core_tests/determinism.rs +24 -12
  30. package/sdk-core/core/src/core_tests/local_activities.rs +53 -27
  31. package/sdk-core/core/src/core_tests/mod.rs +30 -43
  32. package/sdk-core/core/src/core_tests/queries.rs +82 -81
  33. package/sdk-core/core/src/core_tests/workers.rs +111 -296
  34. package/sdk-core/core/src/core_tests/workflow_cancels.rs +4 -4
  35. package/sdk-core/core/src/core_tests/workflow_tasks.rs +257 -242
  36. package/sdk-core/core/src/lib.rs +73 -318
  37. package/sdk-core/core/src/pollers/mod.rs +4 -6
  38. package/sdk-core/core/src/pollers/poll_buffer.rs +20 -14
  39. package/sdk-core/core/src/protosext/mod.rs +7 -10
  40. package/sdk-core/core/src/replay/mod.rs +11 -150
  41. package/sdk-core/core/src/telemetry/metrics.rs +35 -2
  42. package/sdk-core/core/src/telemetry/mod.rs +49 -16
  43. package/sdk-core/core/src/telemetry/prometheus_server.rs +14 -35
  44. package/sdk-core/core/src/test_help/mod.rs +104 -170
  45. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +57 -34
  46. package/sdk-core/core/src/worker/activities/local_activities.rs +95 -23
  47. package/sdk-core/core/src/worker/activities.rs +23 -16
  48. package/sdk-core/core/src/worker/client/mocks.rs +86 -0
  49. package/sdk-core/core/src/worker/client.rs +209 -0
  50. package/sdk-core/core/src/worker/mod.rs +207 -108
  51. package/sdk-core/core/src/workflow/driven_workflow.rs +21 -6
  52. package/sdk-core/core/src/workflow/history_update.rs +107 -24
  53. package/sdk-core/core/src/workflow/machines/activity_state_machine.rs +2 -3
  54. package/sdk-core/core/src/workflow/machines/child_workflow_state_machine.rs +2 -3
  55. package/sdk-core/core/src/workflow/machines/mod.rs +20 -17
  56. package/sdk-core/core/src/workflow/machines/signal_external_state_machine.rs +56 -19
  57. package/sdk-core/core/src/workflow/machines/transition_coverage.rs +5 -0
  58. package/sdk-core/core/src/workflow/machines/upsert_search_attributes_state_machine.rs +230 -22
  59. package/sdk-core/core/src/workflow/machines/workflow_machines.rs +81 -115
  60. package/sdk-core/core/src/workflow/machines/workflow_task_state_machine.rs +4 -4
  61. package/sdk-core/core/src/workflow/mod.rs +13 -1
  62. package/sdk-core/core/src/workflow/workflow_tasks/concurrency_manager.rs +70 -11
  63. package/sdk-core/core/src/workflow/workflow_tasks/mod.rs +65 -41
  64. package/sdk-core/core-api/Cargo.toml +9 -1
  65. package/sdk-core/core-api/LICENSE.txt +23 -0
  66. package/sdk-core/core-api/src/errors.rs +7 -38
  67. package/sdk-core/core-api/src/lib.rs +44 -52
  68. package/sdk-core/core-api/src/worker.rs +10 -2
  69. package/sdk-core/etc/deps.svg +127 -96
  70. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +11 -7
  71. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +10 -0
  72. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +6 -1
  73. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +6 -0
  74. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +6 -0
  75. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +2 -1
  76. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +3 -0
  77. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +12 -0
  78. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +25 -0
  79. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -0
  80. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +19 -35
  81. package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +2 -6
  82. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +53 -11
  83. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +14 -7
  84. package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +3 -5
  85. package/sdk-core/sdk/Cargo.toml +16 -2
  86. package/sdk-core/sdk/LICENSE.txt +23 -0
  87. package/sdk-core/sdk/src/interceptors.rs +11 -0
  88. package/sdk-core/sdk/src/lib.rs +139 -151
  89. package/sdk-core/sdk/src/workflow_context/options.rs +86 -1
  90. package/sdk-core/sdk/src/workflow_context.rs +36 -17
  91. package/sdk-core/sdk/src/workflow_future.rs +19 -25
  92. package/sdk-core/sdk-core-protos/Cargo.toml +1 -1
  93. package/sdk-core/sdk-core-protos/build.rs +1 -0
  94. package/sdk-core/sdk-core-protos/src/history_info.rs +17 -4
  95. package/sdk-core/sdk-core-protos/src/lib.rs +251 -47
  96. package/sdk-core/test-utils/Cargo.toml +3 -1
  97. package/sdk-core/test-utils/src/canned_histories.rs +27 -0
  98. package/sdk-core/test-utils/src/histfetch.rs +3 -3
  99. package/sdk-core/test-utils/src/lib.rs +223 -68
  100. package/sdk-core/tests/integ_tests/client_tests.rs +27 -4
  101. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +93 -14
  102. package/sdk-core/tests/integ_tests/polling_tests.rs +18 -12
  103. package/sdk-core/tests/integ_tests/queries_tests.rs +50 -53
  104. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +117 -103
  105. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +8 -1
  106. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +10 -5
  107. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +7 -1
  108. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +32 -9
  109. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +7 -1
  110. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +76 -15
  111. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +19 -3
  112. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +39 -42
  113. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +84 -0
  114. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +30 -8
  115. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +21 -6
  116. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +26 -16
  117. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +66 -0
  118. package/sdk-core/tests/integ_tests/workflow_tests.rs +78 -74
  119. package/sdk-core/tests/load_tests.rs +9 -6
  120. package/sdk-core/tests/main.rs +43 -10
  121. package/src/conversions.rs +7 -12
  122. package/src/lib.rs +322 -357
  123. package/sdk-core/client/src/mocks.rs +0 -167
  124. package/sdk-core/core/src/worker/dispatcher.rs +0 -171
  125. package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +0 -61
@@ -10,6 +10,7 @@ pub extern crate assert_matches;
10
10
  #[macro_use]
11
11
  extern crate tracing;
12
12
 
13
+ mod abstractions;
13
14
  mod log_export;
14
15
  mod pending_activations;
15
16
  mod pollers;
@@ -29,50 +30,30 @@ mod test_help;
29
30
  pub(crate) use temporal_sdk_core_api::errors;
30
31
 
31
32
  pub use pollers::{
32
- ClientTlsConfig, RetryConfig, RetryGateway, ServerGateway, ServerGatewayApis,
33
- ServerGatewayOptions, ServerGatewayOptionsBuilder, TlsConfig,
33
+ Client, ClientOptions, ClientOptionsBuilder, ClientTlsConfig, RetryClient, RetryConfig,
34
+ TlsConfig, WorkflowClientTrait,
35
+ };
36
+ pub use telemetry::{
37
+ fetch_global_buffered_logs, telemetry_init, TelemetryOptions, TelemetryOptionsBuilder,
34
38
  };
35
- pub use telemetry::{TelemetryOptions, TelemetryOptionsBuilder};
36
39
  pub use temporal_sdk_core_api as api;
37
40
  pub use temporal_sdk_core_protos as protos;
38
41
  pub use temporal_sdk_core_protos::TaskToken;
39
42
  pub use url::Url;
40
- pub use worker::{WorkerConfig, WorkerConfigBuilder};
43
+ pub use worker::{Worker, WorkerConfig, WorkerConfigBuilder};
41
44
 
42
45
  use crate::{
43
- telemetry::{
44
- fetch_global_buffered_logs,
45
- metrics::{MetricsContext, METRIC_METER},
46
- telemetry_init,
47
- },
48
- worker::{Worker, WorkerDispatcher},
49
- };
50
- use std::{
51
- ops::Deref,
52
- sync::{
53
- atomic::{AtomicBool, Ordering},
54
- Arc,
55
- },
46
+ replay::mock_client_from_history,
47
+ telemetry::metrics::{MetricsContext, METRIC_METER},
48
+ worker::client::WorkerClientBag,
56
49
  };
50
+ use std::sync::Arc;
51
+ use temporal_client::AnyClient;
57
52
  use temporal_sdk_core_api::{
58
- errors::{
59
- CompleteActivityError, CompleteWfError, CoreInitError, PollActivityError, PollWfError,
60
- WorkerRegistrationError,
61
- },
62
- Core, CoreLog,
63
- };
64
- use temporal_sdk_core_protos::{
65
- coresdk::{
66
- activity_task::ActivityTask,
67
- workflow_activation::{remove_from_cache::EvictionReason, WorkflowActivation},
68
- workflow_completion::WorkflowActivationCompletion,
69
- ActivityHeartbeat, ActivityTaskCompletion,
70
- },
71
- temporal::api::history::v1::History,
53
+ errors::{CompleteActivityError, PollActivityError, PollWfError},
54
+ CoreLog, Worker as WorkerTrait,
72
55
  };
73
-
74
- #[cfg(test)]
75
- use crate::test_help::MockWorker;
56
+ use temporal_sdk_core_protos::{coresdk::ActivityHeartbeat, temporal::api::history::v1::History};
76
57
 
77
58
  lazy_static::lazy_static! {
78
59
  /// A process-wide unique string, which will be different on every startup
@@ -81,294 +62,68 @@ lazy_static::lazy_static! {
81
62
  };
82
63
  }
83
64
 
84
- /// Holds various configuration information required to call [init]
85
- #[derive(Debug, Clone, derive_builder::Builder)]
86
- #[builder(setter(into))]
87
- #[non_exhaustive]
88
- pub struct CoreInitOptions {
89
- /// Options for the connection to the temporal server
90
- pub gateway_opts: ServerGatewayOptions,
91
- /// Options for telemetry (traces and metrics)
92
- #[builder(default)]
93
- pub telemetry_opts: TelemetryOptions,
94
- }
95
-
96
- /// Initializes an instance of the core sdk and establishes a connection to the temporal server.
97
- /// Expects that a tokio runtime exists.
98
- pub async fn init(opts: CoreInitOptions) -> Result<CoreSDK, CoreInitError> {
99
- telemetry_init(&opts.telemetry_opts).map_err(CoreInitError::TelemetryInitError)?;
100
- // Initialize server client
101
- let server_gateway = opts.gateway_opts.connect(Some(&METRIC_METER)).await?;
102
-
103
- Ok(CoreSDK::new(server_gateway, opts))
104
- }
105
-
106
- /// Initialize core using a provided gateway instance, which is typically a mock
107
- pub fn init_mock_gateway<SG: ServerGatewayApis + Send + Sync + 'static>(
108
- opts: CoreInitOptions,
109
- server_gateway: SG,
110
- ) -> Result<CoreSDK, CoreInitError> {
111
- telemetry_init(&opts.telemetry_opts).map_err(CoreInitError::TelemetryInitError)?;
112
- Ok(CoreSDK::new(server_gateway, opts))
113
- }
114
-
115
- /// Implements the [Core] trait
116
- pub struct CoreSDK {
117
- /// Options provided at initialization time
118
- init_options: CoreInitOptions,
119
- /// A client for interacting with the Temporal service.
120
- server_gateway: Arc<dyn ServerGatewayApis + Send + Sync>,
121
- /// Controls access to workers
122
- workers: WorkerDispatcher,
123
- /// Has shutdown been called and all workers drained of tasks?
124
- whole_core_shutdown: AtomicBool,
125
- /// Top-level metrics context
126
- metrics: MetricsContext,
127
- }
128
-
129
- #[async_trait::async_trait]
130
- impl Core for CoreSDK {
131
- fn register_worker(&self, config: WorkerConfig) -> Result<(), WorkerRegistrationError> {
132
- info!(
133
- task_queue = config.task_queue.as_str(),
134
- "Registering worker"
135
- );
136
- let sticky_q = self.get_sticky_q_name_for_worker(&config);
137
- self.workers.new_worker(
138
- config,
139
- sticky_q,
140
- self.server_gateway.clone(),
141
- self.metrics.clone(),
142
- )
143
- }
144
-
145
- #[instrument(level = "debug", skip(self), fields(run_id))]
146
- async fn poll_workflow_activation(
147
- &self,
148
- task_queue: &str,
149
- ) -> Result<WorkflowActivation, PollWfError> {
150
- let worker = self.worker(task_queue)?;
151
- worker.next_workflow_activation().await
152
- }
153
-
154
- #[instrument(level = "debug", skip(self))]
155
- async fn poll_activity_task(
156
- &self,
157
- task_queue: &str,
158
- ) -> Result<ActivityTask, PollActivityError> {
159
- loop {
160
- if self.whole_core_shutdown.load(Ordering::Relaxed) {
161
- return Err(PollActivityError::ShutDown);
162
- }
163
- let worker = self.worker(task_queue)?;
164
- match worker.activity_poll().await.transpose() {
165
- Some(r) => break r,
166
- None => {
167
- tokio::task::yield_now().await;
168
- continue;
169
- }
170
- }
171
- }
172
- }
173
-
174
- #[instrument(level = "debug", skip(self, completion),
175
- fields(completion=%&completion, run_id=%completion.run_id))]
176
- async fn complete_workflow_activation(
177
- &self,
178
- completion: WorkflowActivationCompletion,
179
- ) -> Result<(), CompleteWfError> {
180
- let worker = self.worker(&completion.task_queue)?;
181
- worker.complete_workflow_activation(completion).await
182
- }
183
-
184
- #[instrument(level = "debug", skip(self))]
185
- async fn complete_activity_task(
186
- &self,
187
- completion: ActivityTaskCompletion,
188
- ) -> Result<(), CompleteActivityError> {
189
- let task_token = TaskToken(completion.task_token);
190
- let status = if let Some(s) = completion.result.and_then(|r| r.status) {
191
- s
192
- } else {
193
- return Err(CompleteActivityError::MalformedActivityCompletion {
194
- reason: "Activity completion had empty result/status field".to_owned(),
195
- completion: None,
196
- });
197
- };
198
-
199
- let worker = self.worker(&completion.task_queue)?;
200
- worker.complete_activity(task_token, status).await
201
- }
202
-
203
- fn record_activity_heartbeat(&self, details: ActivityHeartbeat) {
204
- if let Ok(w) = self.worker(&details.task_queue) {
205
- w.record_heartbeat(details);
206
- }
207
- }
208
-
209
- fn request_workflow_eviction(&self, task_queue: &str, run_id: &str) {
210
- if let Ok(w) = self.worker(task_queue) {
211
- w.request_wf_eviction(
212
- run_id,
213
- "Eviction explicitly requested by lang",
214
- EvictionReason::LangRequested,
215
- );
216
- }
217
- }
218
-
219
- fn server_gateway(&self) -> Arc<dyn ServerGatewayApis + Send + Sync> {
220
- self.server_gateway.clone()
221
- }
222
-
223
- async fn shutdown(&self) {
224
- self.workers.shutdown_all().await;
225
- self.whole_core_shutdown.store(true, Ordering::Relaxed);
226
- }
227
-
228
- async fn shutdown_worker(&self, task_queue: &str) {
229
- self.workers.shutdown_one(task_queue).await;
230
- }
231
-
232
- fn fetch_buffered_logs(&self) -> Vec<CoreLog> {
233
- fetch_global_buffered_logs()
234
- }
235
- }
236
-
237
- impl CoreSDK {
238
- pub(crate) fn new<SG: ServerGatewayApis + Send + Sync + 'static>(
239
- server_gateway: SG,
240
- init_options: CoreInitOptions,
241
- ) -> Self {
242
- let server_gateway = Arc::new(server_gateway);
243
- let workers = WorkerDispatcher::default();
244
- Self {
245
- workers,
246
- init_options,
247
- whole_core_shutdown: AtomicBool::new(false),
248
- metrics: MetricsContext::top_level(server_gateway.get_options().namespace.clone()),
249
- server_gateway,
250
- }
251
- }
252
-
253
- /// Register a worker for replaying a specific history. The worker should use a unique task
254
- /// queue name. It will auto-shutdown as soon as the history has finished being replayed. The
255
- /// provided gateway should be a mock, and this should only be used for workflow testing
256
- /// purposes.
257
- pub fn register_replay_worker(
258
- &self,
259
- config: WorkerConfig,
260
- gateway: Arc<dyn ServerGatewayApis + Send + Sync>,
261
- history: &History,
262
- ) -> Result<(), anyhow::Error> {
263
- info!(
264
- task_queue = config.task_queue.as_str(),
265
- "Registering replay worker"
266
- );
267
- // Could possibly just use mocked pollers here, but they'd need to be un-test-moded
268
- let run_id = history.extract_run_id_from_start()?.to_string();
269
- let last_event = history.last_event_id();
270
- let tq = config.task_queue.clone();
271
- let mut worker = Worker::new(config, None, gateway, self.metrics.clone());
272
- worker.set_post_activate_hook(move |worker| {
273
- if worker
274
- .wft_manager
275
- .most_recently_processed_event(&run_id)
276
- .unwrap_or_default()
277
- >= last_event
278
- {
279
- worker.initiate_shutdown();
280
- }
281
- });
282
-
283
- self.workers.set_worker_for_task_queue(tq, worker)?;
284
- Ok(())
285
- }
286
-
287
- /// Allow construction of workers with mocked poll responses during testing
288
- #[cfg(test)]
289
- pub(crate) fn reg_worker_sync(&self, worker: MockWorker) {
290
- let sticky_q = self.get_sticky_q_name_for_worker(&worker.config);
291
- let tq = worker.config.task_queue.clone();
292
- let worker = Worker::new_with_pollers(
293
- worker.config,
294
- sticky_q,
295
- self.server_gateway.clone(),
296
- worker.wf_poller,
297
- worker.act_poller,
298
- self.metrics.clone(),
299
- );
300
- self.workers.set_worker_for_task_queue(tq, worker).unwrap();
301
- }
302
-
303
- #[cfg(test)]
304
- pub(crate) fn outstanding_wfts(&self, tq: &str) -> usize {
305
- self.worker(tq).unwrap().outstanding_workflow_tasks()
306
- }
307
- #[cfg(test)]
308
- pub(crate) fn available_wft_permits(&self, tq: &str) -> usize {
309
- self.worker(tq).unwrap().available_wft_permits()
310
- }
311
-
312
- fn get_sticky_q_name_for_worker(&self, config: &WorkerConfig) -> Option<String> {
313
- if config.max_cached_workflows > 0 {
314
- Some(format!(
315
- "{}-{}-{}",
316
- &self.init_options.gateway_opts.identity, &config.task_queue, *PROCCESS_UNIQ_ID
317
- ))
318
- } else {
319
- None
65
+ /// Initialize a worker bound to a task queue
66
+ pub fn init_worker<CT>(worker_config: WorkerConfig, client: CT) -> Worker
67
+ where
68
+ CT: Into<AnyClient>,
69
+ {
70
+ let as_enum = client.into();
71
+ // TODO: Assert namespaces match
72
+ let client = match as_enum {
73
+ AnyClient::HighLevel(ac) => ac,
74
+ AnyClient::LowLevel(ll) => {
75
+ let client = Client::new(*ll, worker_config.namespace.clone());
76
+ let retry_client = RetryClient::new(client, RetryConfig::default());
77
+ Arc::new(retry_client)
320
78
  }
321
- }
322
-
323
- fn worker(&self, tq: &str) -> Result<impl Deref<Target = Worker>, WorkerLookupErr> {
324
- let worker = self.workers.get(tq);
325
- if worker.is_err() && self.whole_core_shutdown.load(Ordering::Relaxed) {
326
- return Err(WorkerLookupErr::Shutdown(tq.to_owned()));
327
- }
328
- worker
329
- }
330
- }
331
-
332
- #[derive(Debug)]
333
- enum WorkerLookupErr {
334
- Shutdown(String),
335
- NoWorker(String),
336
- }
337
-
338
- impl From<WorkerLookupErr> for PollWfError {
339
- fn from(e: WorkerLookupErr) -> Self {
340
- match e {
341
- WorkerLookupErr::Shutdown(_) => Self::ShutDown,
342
- WorkerLookupErr::NoWorker(s) => Self::NoWorkerForQueue(s),
343
- }
344
- }
345
- }
346
-
347
- impl From<WorkerLookupErr> for PollActivityError {
348
- fn from(e: WorkerLookupErr) -> Self {
349
- match e {
350
- WorkerLookupErr::Shutdown(_) => Self::ShutDown,
351
- WorkerLookupErr::NoWorker(s) => Self::NoWorkerForQueue(s),
352
- }
353
- }
79
+ };
80
+ let c_opts = client.get_options().clone();
81
+ if client.namespace() != worker_config.namespace {
82
+ panic!("Passed in client is not bound to the same namespace as the worker");
83
+ }
84
+ let client_bag = Arc::new(WorkerClientBag::new(
85
+ Box::new(client),
86
+ worker_config.namespace.clone(),
87
+ ));
88
+ let sticky_q = sticky_q_name_for_worker(&c_opts.identity, &worker_config);
89
+ let metrics = MetricsContext::top_level(worker_config.namespace.clone())
90
+ .with_task_q(worker_config.task_queue.clone());
91
+ Worker::new(worker_config, sticky_q, client_bag, metrics)
354
92
  }
355
93
 
356
- impl From<WorkerLookupErr> for CompleteWfError {
357
- fn from(e: WorkerLookupErr) -> Self {
358
- match e {
359
- WorkerLookupErr::Shutdown(s) | WorkerLookupErr::NoWorker(s) => {
360
- Self::NoWorkerForQueue(s)
361
- }
362
- }
363
- }
94
+ /// Create a worker for replaying a specific history. It will auto-shutdown as soon as the history
95
+ /// has finished being replayed. The provided client should be a mock, and this should only be used
96
+ /// for workflow testing purposes.
97
+ pub fn init_replay_worker(
98
+ mut config: WorkerConfig,
99
+ history: &History,
100
+ ) -> Result<Worker, anyhow::Error> {
101
+ info!(
102
+ task_queue = config.task_queue.as_str(),
103
+ "Registering replay worker"
104
+ );
105
+ config.max_cached_workflows = 1;
106
+ config.max_concurrent_wft_polls = 1;
107
+ config.no_remote_activities = true;
108
+ // Could possibly just use mocked pollers here?
109
+ let client = mock_client_from_history(history, &config.task_queue);
110
+ let run_id = history.extract_run_id_from_start()?.to_string();
111
+ let last_event = history.last_event_id();
112
+ let mut worker = Worker::new(config, None, Arc::new(client), MetricsContext::default());
113
+ worker.set_shutdown_on_run_reaches_event(run_id, last_event);
114
+ Ok(worker)
364
115
  }
365
116
 
366
- impl From<WorkerLookupErr> for CompleteActivityError {
367
- fn from(e: WorkerLookupErr) -> Self {
368
- match e {
369
- WorkerLookupErr::Shutdown(s) | WorkerLookupErr::NoWorker(s) => {
370
- Self::NoWorkerForQueue(s)
371
- }
372
- }
117
+ pub(crate) fn sticky_q_name_for_worker(
118
+ process_identity: &str,
119
+ config: &WorkerConfig,
120
+ ) -> Option<String> {
121
+ if config.max_cached_workflows > 0 {
122
+ Some(format!(
123
+ "{}-{}-{}",
124
+ &process_identity, &config.task_queue, *PROCCESS_UNIQ_ID
125
+ ))
126
+ } else {
127
+ None
373
128
  }
374
129
  }
@@ -1,14 +1,12 @@
1
1
  mod poll_buffer;
2
2
 
3
- pub use poll_buffer::{
4
- new_activity_task_buffer, new_workflow_task_buffer, PollActivityTaskBuffer,
5
- PollWorkflowTaskBuffer, WorkflowTaskPoller,
3
+ pub(crate) use poll_buffer::{
4
+ new_activity_task_buffer, new_workflow_task_buffer, WorkflowTaskPoller,
6
5
  };
7
6
  pub use temporal_client::{
8
- ClientTlsConfig, RetryConfig, RetryGateway, ServerGateway, ServerGatewayApis,
9
- ServerGatewayOptions, ServerGatewayOptionsBuilder, TlsConfig,
7
+ Client, ClientOptions, ClientOptionsBuilder, ClientTlsConfig, RetryClient, RetryConfig,
8
+ TlsConfig, WorkflowClientTrait,
10
9
  };
11
-
12
10
  use temporal_sdk_core_protos::temporal::api::workflowservice::v1::{
13
11
  PollActivityTaskQueueResponse, PollWorkflowTaskQueueResponse,
14
12
  };
@@ -1,6 +1,6 @@
1
1
  use crate::{
2
2
  pollers::{self, Poller},
3
- ServerGatewayApis,
3
+ worker::client::WorkerClientBag,
4
4
  };
5
5
  use futures::{prelude::stream::FuturesUnordered, StreamExt};
6
6
  use std::{
@@ -197,8 +197,8 @@ impl Poller<PollWorkflowTaskQueueResponse> for WorkflowTaskPoller {
197
197
  }
198
198
 
199
199
  pub type PollWorkflowTaskBuffer = LongPollBuffer<PollWorkflowTaskQueueResponse>;
200
- pub fn new_workflow_task_buffer(
201
- sg: Arc<impl ServerGatewayApis + Send + Sync + 'static + ?Sized>,
200
+ pub(crate) fn new_workflow_task_buffer(
201
+ client: Arc<WorkerClientBag>,
202
202
  task_queue: String,
203
203
  is_sticky: bool,
204
204
  concurrent_pollers: usize,
@@ -206,9 +206,9 @@ pub fn new_workflow_task_buffer(
206
206
  ) -> PollWorkflowTaskBuffer {
207
207
  LongPollBuffer::new(
208
208
  move || {
209
- let sg = sg.clone();
209
+ let client = client.clone();
210
210
  let task_queue = task_queue.clone();
211
- async move { sg.poll_workflow_task(task_queue, is_sticky).await }
211
+ async move { client.poll_workflow_task(task_queue, is_sticky).await }
212
212
  },
213
213
  concurrent_pollers,
214
214
  buffer_size,
@@ -216,17 +216,18 @@ pub fn new_workflow_task_buffer(
216
216
  }
217
217
 
218
218
  pub type PollActivityTaskBuffer = LongPollBuffer<PollActivityTaskQueueResponse>;
219
- pub fn new_activity_task_buffer(
220
- sg: Arc<impl ServerGatewayApis + Send + Sync + 'static + ?Sized>,
219
+ pub(crate) fn new_activity_task_buffer(
220
+ client: Arc<WorkerClientBag>,
221
221
  task_queue: String,
222
222
  concurrent_pollers: usize,
223
223
  buffer_size: usize,
224
+ max_tps: Option<f64>,
224
225
  ) -> PollActivityTaskBuffer {
225
226
  LongPollBuffer::new(
226
227
  move || {
227
- let sg = sg.clone();
228
+ let client = client.clone();
228
229
  let task_queue = task_queue.clone();
229
- async move { sg.poll_activity_task(task_queue).await }
230
+ async move { client.poll_activity_task(task_queue, max_tps).await }
230
231
  },
231
232
  concurrent_pollers,
232
233
  buffer_size,
@@ -236,15 +237,15 @@ pub fn new_activity_task_buffer(
236
237
  #[cfg(test)]
237
238
  mod tests {
238
239
  use super::*;
240
+ use crate::worker::client::mocks::mock_manual_workflow_client;
239
241
  use futures::FutureExt;
240
242
  use std::time::Duration;
241
- use temporal_client::MockManualGateway;
242
243
  use tokio::{select, sync::mpsc::channel};
243
244
 
244
245
  #[tokio::test]
245
246
  async fn only_polls_once_with_1_poller() {
246
- let mut mock_gateway = MockManualGateway::new();
247
- mock_gateway
247
+ let mut mock_client = mock_manual_workflow_client();
248
+ mock_client
248
249
  .expect_poll_workflow_task()
249
250
  .times(2)
250
251
  .returning(move |_, _| {
@@ -254,9 +255,14 @@ mod tests {
254
255
  }
255
256
  .boxed()
256
257
  });
257
- let mock_gateway = Arc::new(mock_gateway);
258
258
 
259
- let pb = new_workflow_task_buffer(mock_gateway, "someq".to_string(), false, 1, 1);
259
+ let pb = new_workflow_task_buffer(
260
+ Arc::new(mock_client.into()),
261
+ "someq".to_string(),
262
+ false,
263
+ 1,
264
+ 1,
265
+ );
260
266
 
261
267
  // Poll a bunch of times, "interrupting" it each time, we should only actually have polled
262
268
  // once since the poll takes a while
@@ -19,12 +19,13 @@ use temporal_sdk_core_protos::{
19
19
  },
20
20
  external_data::LocalActivityMarkerData,
21
21
  workflow_activation::{
22
- workflow_activation_job, QueryWorkflow, WorkflowActivation, WorkflowActivationJob,
22
+ query_to_job, workflow_activation_job, QueryWorkflow, WorkflowActivation,
23
+ WorkflowActivationJob,
23
24
  },
24
25
  workflow_commands::{
25
26
  query_result, ActivityCancellationType, QueryResult, ScheduleLocalActivity,
26
27
  },
27
- workflow_completion, FromPayloadsExt,
28
+ workflow_completion,
28
29
  },
29
30
  temporal::api::{
30
31
  common::v1::{Payload, WorkflowExecution},
@@ -82,11 +83,7 @@ impl TryFrom<PollWorkflowTaskQueueResponse> for ValidPollWFTQResponse {
82
83
  } => {
83
84
  let query_requests = queries
84
85
  .into_iter()
85
- .map(|(id, q)| QueryWorkflow {
86
- query_id: id,
87
- query_type: q.query_type,
88
- arguments: Vec::from_payloads(q.query_args),
89
- })
86
+ .map(|(id, q)| query_to_job(id, q))
90
87
  .collect();
91
88
 
92
89
  Ok(Self {
@@ -267,7 +264,7 @@ pub struct ValidScheduleLA {
267
264
  pub activity_type: String,
268
265
  pub attempt: u32,
269
266
  pub original_schedule_time: Option<SystemTime>,
270
- pub header_fields: HashMap<String, SDKPayload>,
267
+ pub headers: HashMap<String, SDKPayload>,
271
268
  pub arguments: Vec<SDKPayload>,
272
269
  pub schedule_to_start_timeout: Option<Duration>,
273
270
  pub close_timeouts: LACloseTimeouts,
@@ -364,7 +361,7 @@ impl ValidScheduleLA {
364
361
  };
365
362
  let retry_policy = v
366
363
  .retry_policy
367
- .ok_or(anyhow!("Retry policy must be defined!"))?;
364
+ .ok_or_else(|| anyhow!("Retry policy must be defined!"))?;
368
365
  let local_retry_threshold = v
369
366
  .local_retry_threshold
370
367
  .clone()
@@ -378,7 +375,7 @@ impl ValidScheduleLA {
378
375
  activity_type: v.activity_type,
379
376
  attempt: v.attempt,
380
377
  original_schedule_time,
381
- header_fields: v.header_fields,
378
+ headers: v.headers,
382
379
  arguments: v.arguments,
383
380
  schedule_to_start_timeout,
384
381
  close_timeouts,