@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
@@ -7,9 +7,11 @@ mod determinism;
7
7
  mod local_activities;
8
8
  mod patches;
9
9
  mod replay;
10
+ mod resets;
10
11
  mod signals;
11
12
  mod stickyness;
12
13
  mod timers;
14
+ mod upsert_search_attrs;
13
15
 
14
16
  use assert_matches::assert_matches;
15
17
  use futures::{channel::mpsc::UnboundedReceiver, future, SinkExt, StreamExt};
@@ -21,8 +23,9 @@ use std::{
21
23
  },
22
24
  time::Duration,
23
25
  };
26
+ use temporal_client::{WorkflowClientTrait, WorkflowOptions};
24
27
  use temporal_sdk::{WfContext, WorkflowResult};
25
- use temporal_sdk_core_api::{errors::PollWfError, Core};
28
+ use temporal_sdk_core_api::{errors::PollWfError, Worker};
26
29
  use temporal_sdk_core_protos::{
27
30
  coresdk::{
28
31
  activity_result::ActivityExecutionResult,
@@ -35,7 +38,7 @@ use temporal_sdk_core_protos::{
35
38
  };
36
39
  use temporal_sdk_core_test_utils::{
37
40
  history_from_proto_binary, init_core_and_create_wf, init_core_replay_preloaded,
38
- schedule_activity_cmd, CoreTestHelpers, CoreWfStarter,
41
+ schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
39
42
  };
40
43
  use tokio::time::sleep;
41
44
  use uuid::Uuid;
@@ -46,19 +49,18 @@ use uuid::Uuid;
46
49
  #[tokio::test]
47
50
  async fn parallel_workflows_same_queue() {
48
51
  let mut starter = CoreWfStarter::new("parallel_workflows_same_queue");
49
- let core = starter.get_core().await;
50
- let task_q = starter.get_task_queue().to_string();
52
+ let core = starter.get_worker().await;
51
53
  let num_workflows = 25usize;
52
54
 
53
55
  let run_ids: Vec<_> = future::join_all(
54
- (0..num_workflows).map(|i| starter.start_wf_with_id(format!("wf-id-{}", i))),
56
+ (0..num_workflows)
57
+ .map(|i| starter.start_wf_with_id(format!("wf-id-{}", i), WorkflowOptions::default())),
55
58
  )
56
59
  .await;
57
60
 
58
61
  let mut send_chans = HashMap::new();
59
62
  async fn wf_task(
60
- core: Arc<dyn Core>,
61
- task_q: String,
63
+ worker: Arc<dyn Worker>,
62
64
  mut task_chan: UnboundedReceiver<WorkflowActivation>,
63
65
  ) {
64
66
  let task = task_chan.next().await.unwrap();
@@ -68,10 +70,11 @@ async fn parallel_workflows_same_queue() {
68
70
  variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
69
71
  }]
70
72
  );
71
- core.complete_timer(&task_q, &task.run_id, 1, Duration::from_secs(1))
73
+ worker
74
+ .complete_timer(&task.run_id, 1, Duration::from_secs(1))
72
75
  .await;
73
76
  let task = task_chan.next().await.unwrap();
74
- core.complete_execution(&task_q, &task.run_id).await;
77
+ worker.complete_execution(&task.run_id).await;
75
78
  }
76
79
 
77
80
  let handles: Vec<_> = run_ids
@@ -79,12 +82,12 @@ async fn parallel_workflows_same_queue() {
79
82
  .map(|run_id| {
80
83
  let (tx, rx) = futures::channel::mpsc::unbounded();
81
84
  send_chans.insert(run_id.clone(), tx);
82
- tokio::spawn(wf_task(core.clone(), task_q.clone(), rx))
85
+ tokio::spawn(wf_task(core.clone(), rx))
83
86
  })
84
87
  .collect();
85
88
 
86
89
  for _ in 0..num_workflows * 2 {
87
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
90
+ let task = core.poll_workflow_activation().await.unwrap();
88
91
  send_chans
89
92
  .get(&task.run_id)
90
93
  .unwrap()
@@ -120,6 +123,7 @@ async fn workflow_lru_cache_evictions() {
120
123
  format!("wce-{}", Uuid::new_v4()),
121
124
  wf_type.to_string(),
122
125
  vec![],
126
+ WorkflowOptions::default(),
123
127
  )
124
128
  .await
125
129
  .unwrap();
@@ -136,8 +140,7 @@ async fn workflow_lru_cache_evictions() {
136
140
  #[tokio::test]
137
141
  async fn shutdown_aborts_actively_blocked_poll() {
138
142
  let mut starter = CoreWfStarter::new("shutdown_aborts_actively_blocked_poll");
139
- let core = starter.get_core().await;
140
- let task_q = starter.get_task_queue();
143
+ let core = starter.get_worker().await;
141
144
  // Begin the poll, and request shutdown from another thread after a small period of time.
142
145
  let tcore = core.clone();
143
146
  let handle = tokio::spawn(async move {
@@ -145,14 +148,14 @@ async fn shutdown_aborts_actively_blocked_poll() {
145
148
  tcore.shutdown().await;
146
149
  });
147
150
  assert_matches!(
148
- core.poll_workflow_activation(task_q).await.unwrap_err(),
151
+ core.poll_workflow_activation().await.unwrap_err(),
149
152
  PollWfError::ShutDown
150
153
  );
151
154
  handle.await.unwrap();
152
155
  // Ensure double-shutdown doesn't explode
153
156
  core.shutdown().await;
154
157
  assert_matches!(
155
- core.poll_workflow_activation(task_q).await.unwrap_err(),
158
+ core.poll_workflow_activation().await.unwrap_err(),
156
159
  PollWfError::ShutDown
157
160
  );
158
161
  }
@@ -160,25 +163,26 @@ async fn shutdown_aborts_actively_blocked_poll() {
160
163
  #[rstest::rstest]
161
164
  #[tokio::test]
162
165
  async fn fail_wf_task(#[values(true, false)] replay: bool) {
163
- let (core, task_q) = if replay {
164
- init_core_replay_preloaded(
166
+ let core = if replay {
167
+ let (core, _) = init_core_replay_preloaded(
165
168
  "fail_wf_task",
166
169
  &history_from_proto_binary("histories/fail_wf_task.bin")
167
170
  .await
168
171
  .unwrap(),
169
- )
172
+ );
173
+ core
170
174
  } else {
171
- init_core_and_create_wf("fail_wf_task").await
175
+ let mut starter = init_core_and_create_wf("fail_wf_task").await;
176
+ starter.get_worker().await
172
177
  };
173
178
  // Start with a timer
174
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
175
- core.complete_timer(&task_q, &task.run_id, 0, Duration::from_millis(200))
179
+ let task = core.poll_workflow_activation().await.unwrap();
180
+ core.complete_timer(&task.run_id, 0, Duration::from_millis(200))
176
181
  .await;
177
182
 
178
183
  // Then break for whatever reason
179
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
184
+ let task = core.poll_workflow_activation().await.unwrap();
180
185
  core.complete_workflow_activation(WorkflowActivationCompletion::fail(
181
- &task_q,
182
186
  task.run_id,
183
187
  Failure::application_failure("I did an oopsie".to_string(), false),
184
188
  ))
@@ -187,7 +191,7 @@ async fn fail_wf_task(#[values(true, false)] replay: bool) {
187
191
 
188
192
  // The server will want to retry the task. This time we finish the workflow -- but we need
189
193
  // to poll a couple of times as there will be more than one required workflow activation.
190
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
194
+ let task = core.poll_workflow_activation().await.unwrap();
191
195
  // The first poll response will tell us to evict
192
196
  assert_matches!(
193
197
  task.jobs.as_slice(),
@@ -195,13 +199,12 @@ async fn fail_wf_task(#[values(true, false)] replay: bool) {
195
199
  variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
196
200
  }]
197
201
  );
198
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(&task_q, task.run_id))
202
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
199
203
  .await
200
204
  .unwrap();
201
205
 
202
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
206
+ let task = core.poll_workflow_activation().await.unwrap();
203
207
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
204
- &task_q,
205
208
  task.run_id,
206
209
  vec![StartTimer {
207
210
  seq: 0,
@@ -211,19 +214,21 @@ async fn fail_wf_task(#[values(true, false)] replay: bool) {
211
214
  ))
212
215
  .await
213
216
  .unwrap();
214
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
215
- core.complete_execution(&task_q, &task.run_id).await;
217
+ let task = core.poll_workflow_activation().await.unwrap();
218
+ core.complete_execution(&task.run_id).await;
216
219
  }
217
220
 
218
221
  #[tokio::test]
219
222
  async fn fail_workflow_execution() {
220
- let (core, task_q) = init_core_and_create_wf("fail_workflow_execution").await;
221
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
222
- core.complete_timer(&task_q, &task.run_id, 0, Duration::from_secs(1))
223
+ let core = init_core_and_create_wf("fail_workflow_execution")
224
+ .await
225
+ .get_worker()
226
+ .await;
227
+ let task = core.poll_workflow_activation().await.unwrap();
228
+ core.complete_timer(&task.run_id, 0, Duration::from_secs(1))
223
229
  .await;
224
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
230
+ let task = core.poll_workflow_activation().await.unwrap();
225
231
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
226
- &task_q,
227
232
  task.run_id,
228
233
  vec![FailWorkflowExecution {
229
234
  failure: Some(Failure::application_failure("I'm ded".to_string(), false)),
@@ -236,15 +241,16 @@ async fn fail_workflow_execution() {
236
241
 
237
242
  #[tokio::test]
238
243
  async fn signal_workflow() {
239
- let (core, task_q) = init_core_and_create_wf("signal_workflow").await;
240
- let workflow_id = task_q.clone();
244
+ let mut starter = init_core_and_create_wf("signal_workflow").await;
245
+ let core = starter.get_worker().await;
246
+ let client = starter.get_client().await;
247
+ let workflow_id = starter.get_task_queue().to_string();
241
248
 
242
249
  let signal_id_1 = "signal1";
243
250
  let signal_id_2 = "signal2";
244
- let res = core.poll_workflow_activation(&task_q).await.unwrap();
251
+ let res = core.poll_workflow_activation().await.unwrap();
245
252
  // Task is completed with no commands
246
253
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
247
- &task_q,
248
254
  res.run_id.clone(),
249
255
  vec![],
250
256
  ))
@@ -252,7 +258,7 @@ async fn signal_workflow() {
252
258
  .unwrap();
253
259
 
254
260
  // Send the signals to the server
255
- core.server_gateway()
261
+ client
256
262
  .signal_workflow_execution(
257
263
  workflow_id.to_string(),
258
264
  res.run_id.to_string(),
@@ -261,7 +267,7 @@ async fn signal_workflow() {
261
267
  )
262
268
  .await
263
269
  .unwrap();
264
- core.server_gateway()
270
+ client
265
271
  .signal_workflow_execution(
266
272
  workflow_id.to_string(),
267
273
  res.run_id.to_string(),
@@ -271,7 +277,7 @@ async fn signal_workflow() {
271
277
  .await
272
278
  .unwrap();
273
279
 
274
- let mut res = core.poll_workflow_activation(&task_q).await.unwrap();
280
+ let mut res = core.poll_workflow_activation().await.unwrap();
275
281
  // Sometimes both signals are complete at once, sometimes only one, depending on server
276
282
  // Converting test to wf function type would make this shorter
277
283
  if res.jobs.len() == 2 {
@@ -294,13 +300,12 @@ async fn signal_workflow() {
294
300
  },]
295
301
  );
296
302
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
297
- &task_q,
298
303
  res.run_id,
299
304
  vec![],
300
305
  ))
301
306
  .await
302
307
  .unwrap();
303
- res = core.poll_workflow_activation(&task_q).await.unwrap();
308
+ res = core.poll_workflow_activation().await.unwrap();
304
309
  assert_matches!(
305
310
  res.jobs.as_slice(),
306
311
  [WorkflowActivationJob {
@@ -308,20 +313,20 @@ async fn signal_workflow() {
308
313
  },]
309
314
  );
310
315
  }
311
- core.complete_execution(&task_q, &res.run_id).await;
316
+ core.complete_execution(&res.run_id).await;
312
317
  }
313
318
 
314
319
  #[tokio::test]
315
320
  async fn signal_workflow_signal_not_handled_on_workflow_completion() {
316
- let (core, task_q) =
321
+ let mut starter =
317
322
  init_core_and_create_wf("signal_workflow_signal_not_handled_on_workflow_completion").await;
318
- let workflow_id = task_q.as_str();
323
+ let core = starter.get_worker().await;
324
+ let workflow_id = starter.get_task_queue().to_string();
319
325
  let signal_id_1 = "signal1";
320
326
  for i in 1..=2 {
321
- let res = core.poll_workflow_activation(&task_q).await.unwrap();
327
+ let res = core.poll_workflow_activation().await.unwrap();
322
328
  // Task is completed with a timer
323
329
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
324
- &task_q,
325
330
  res.run_id,
326
331
  vec![StartTimer {
327
332
  seq: 0,
@@ -332,7 +337,7 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
332
337
  .await
333
338
  .unwrap();
334
339
 
335
- let res = core.poll_workflow_activation(&task_q).await.unwrap();
340
+ let res = core.poll_workflow_activation().await.unwrap();
336
341
 
337
342
  if i == 1 {
338
343
  // First attempt we should only see the timer being fired
@@ -346,9 +351,11 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
346
351
  let run_id = res.run_id.clone();
347
352
 
348
353
  // Send the signal to the server
349
- core.server_gateway()
354
+ starter
355
+ .get_client()
356
+ .await
350
357
  .signal_workflow_execution(
351
- workflow_id.to_string(),
358
+ workflow_id.clone(),
352
359
  res.run_id.to_string(),
353
360
  signal_id_1.to_string(),
354
361
  None,
@@ -358,22 +365,19 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
358
365
 
359
366
  // Send completion - not having seen a poll response with a signal in it yet (unhandled
360
367
  // command error will be logged as a warning and an eviction will be issued)
361
- core.complete_execution(&task_q, &run_id).await;
368
+ core.complete_execution(&run_id).await;
362
369
 
363
370
  // We should be told to evict
364
- let res = core.poll_workflow_activation(&task_q).await.unwrap();
371
+ let res = core.poll_workflow_activation().await.unwrap();
365
372
  assert_matches!(
366
373
  res.jobs.as_slice(),
367
374
  [WorkflowActivationJob {
368
375
  variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
369
376
  }]
370
377
  );
371
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(
372
- task_q.clone(),
373
- res.run_id,
374
- ))
375
- .await
376
- .unwrap();
378
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(res.run_id))
379
+ .await
380
+ .unwrap();
377
381
  // Loop to the top to handle wf from the beginning
378
382
  continue;
379
383
  }
@@ -390,7 +394,7 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
390
394
  }
391
395
  ]
392
396
  );
393
- core.complete_execution(&task_q, &res.run_id).await;
397
+ core.complete_execution(&res.run_id).await;
394
398
  }
395
399
  }
396
400
 
@@ -404,13 +408,14 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
404
408
  // Test needs eviction on and a short timeout
405
409
  .max_cached_workflows(0usize)
406
410
  .wft_timeout(Duration::from_secs(1));
407
- let core = wf_starter.get_core().await;
411
+ let core = wf_starter.get_worker().await;
412
+ let client = wf_starter.get_client().await;
408
413
  let task_q = wf_starter.get_task_queue();
409
414
  let wf_id = &wf_starter.get_wf_id().to_owned();
410
415
 
411
416
  // Set up some helpers for polling and completing
412
417
  let poll_sched_act = || async {
413
- let wf_task = core.poll_workflow_activation(task_q).await.unwrap();
418
+ let wf_task = core.poll_workflow_activation().await.unwrap();
414
419
  core.complete_workflow_activation(
415
420
  schedule_activity_cmd(
416
421
  0,
@@ -420,7 +425,7 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
420
425
  Duration::from_secs(60),
421
426
  Duration::from_secs(60),
422
427
  )
423
- .into_completion(task_q.to_string(), wf_task.run_id.clone()),
428
+ .into_completion(wf_task.run_id.clone()),
424
429
  )
425
430
  .await
426
431
  .unwrap();
@@ -428,7 +433,7 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
428
433
  };
429
434
  let poll_sched_act_poll = || async {
430
435
  poll_sched_act().await;
431
- let wf_task = core.poll_workflow_activation(task_q).await.unwrap();
436
+ let wf_task = core.poll_workflow_activation().await.unwrap();
432
437
  assert_matches!(
433
438
  wf_task.jobs.as_slice(),
434
439
  [
@@ -452,36 +457,35 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
452
457
  let wf_task = poll_sched_act().await;
453
458
  // Before polling for a task again, we start and complete the activity and send the
454
459
  // corresponding signals.
455
- let ac_task = core.poll_activity_task(task_q).await.unwrap();
460
+ let ac_task = core.poll_activity_task().await.unwrap();
456
461
  let rid = wf_task.run_id.clone();
457
462
  // Send the signals to the server & resolve activity -- sometimes this happens too fast
458
463
  sleep(Duration::from_millis(200)).await;
459
- core.server_gateway()
464
+ client
460
465
  .signal_workflow_execution(wf_id.to_string(), rid, signal_at_start.to_string(), None)
461
466
  .await
462
467
  .unwrap();
463
468
  // Complete activity successfully.
464
469
  core.complete_activity_task(ActivityTaskCompletion {
465
470
  task_token: ac_task.task_token,
466
- task_queue: task_q.to_string(),
467
471
  result: Some(ActivityExecutionResult::ok(Default::default())),
468
472
  })
469
473
  .await
470
474
  .unwrap();
471
475
  let rid = wf_task.run_id.clone();
472
- core.server_gateway()
476
+ client
473
477
  .signal_workflow_execution(wf_id.to_string(), rid, signal_at_complete.to_string(), None)
474
478
  .await
475
479
  .unwrap();
476
480
  // Now poll again, it will be an eviction b/c non-sticky mode.
477
- let wf_task = core.poll_workflow_activation(task_q).await.unwrap();
481
+ let wf_task = core.poll_workflow_activation().await.unwrap();
478
482
  assert_matches!(
479
483
  wf_task.jobs.as_slice(),
480
484
  [WorkflowActivationJob {
481
485
  variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
482
486
  }]
483
487
  );
484
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(task_q, wf_task.run_id))
488
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
485
489
  .await
486
490
  .unwrap();
487
491
  // Start from the beginning
@@ -491,11 +495,11 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
491
495
  // Poll again, which should not have any work to do and spin, until the complete goes through.
492
496
  // Which will be rejected with not found, producing an eviction.
493
497
  let (wf_task, _) = tokio::join!(
494
- async { core.poll_workflow_activation(task_q).await.unwrap() },
498
+ async { core.poll_workflow_activation().await.unwrap() },
495
499
  async {
496
500
  sleep(Duration::from_millis(500)).await;
497
501
  // Reply to the first one, finally
498
- core.complete_execution(task_q, &wf_task.run_id).await;
502
+ core.complete_execution(&wf_task.run_id).await;
499
503
  }
500
504
  );
501
505
  assert_matches!(
@@ -504,10 +508,10 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
504
508
  variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
505
509
  }]
506
510
  );
507
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(task_q, wf_task.run_id))
511
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
508
512
  .await
509
513
  .unwrap();
510
514
  // Do it all over again, without timing out this time
511
515
  let wf_task = poll_sched_act_poll().await;
512
- core.complete_execution(task_q, &wf_task.run_id).await;
516
+ core.complete_execution(&wf_task.run_id).await;
513
517
  }
@@ -1,6 +1,7 @@
1
1
  use assert_matches::assert_matches;
2
2
  use futures::future::join_all;
3
3
  use std::time::{Duration, Instant};
4
+ use temporal_client::WorkflowOptions;
4
5
  use temporal_sdk::{ActivityOptions, WfContext};
5
6
  use temporal_sdk_core_protos::coresdk::{
6
7
  activity_result::ActivityExecutionResult, activity_task::activity_task as act_task,
@@ -19,7 +20,6 @@ async fn activity_load() {
19
20
  .max_at_polls(10)
20
21
  .max_at(CONCURRENCY);
21
22
  let mut worker = starter.worker().await;
22
- let task_q = starter.get_task_queue().to_owned();
23
23
 
24
24
  let activity_id = "act-1";
25
25
  let activity_timeout = Duration::from_secs(8);
@@ -57,7 +57,12 @@ async fn activity_load() {
57
57
  let wf_id = format!("activity_load_{}", i);
58
58
  async move {
59
59
  worker
60
- .submit_wf(wf_id, wf_type.to_owned(), vec![])
60
+ .submit_wf(
61
+ wf_id,
62
+ wf_type.to_owned(),
63
+ vec![],
64
+ WorkflowOptions::default(),
65
+ )
61
66
  .await
62
67
  .unwrap();
63
68
  }
@@ -66,15 +71,14 @@ async fn activity_load() {
66
71
  dbg!(starting.elapsed());
67
72
 
68
73
  let running = Instant::now();
69
- let core = starter.get_core().await;
74
+ let core = starter.get_worker().await;
70
75
 
71
76
  // Poll for and complete all activities
72
77
  let c2 = core.clone();
73
78
  let all_acts = async move {
74
79
  let mut act_complete_futs = vec![];
75
80
  for _ in 0..CONCURRENCY {
76
- let task_q = task_q.clone();
77
- let task = c2.poll_activity_task(&task_q).await.unwrap();
81
+ let task = c2.poll_activity_task().await.unwrap();
78
82
  assert_matches!(
79
83
  task.variant,
80
84
  Some(act_task::Variant::Start(ref start_activity)) => {
@@ -86,7 +90,6 @@ async fn activity_load() {
86
90
  act_complete_futs.push(tokio::spawn(async move {
87
91
  core.complete_activity_task(ActivityTaskCompletion {
88
92
  task_token: task.task_token,
89
- task_queue: task_q,
90
93
  result: Some(ActivityExecutionResult::ok(pd.into())),
91
94
  })
92
95
  .await
@@ -2,19 +2,53 @@
2
2
 
3
3
  #[cfg(test)]
4
4
  mod integ_tests {
5
- use std::str::FromStr;
6
- use temporal_sdk_core::{
7
- ClientTlsConfig, ServerGatewayApis, ServerGatewayOptionsBuilder, TlsConfig,
8
- };
9
- use temporal_sdk_core_test_utils::NAMESPACE;
10
- use url::Url;
11
-
12
5
  mod client_tests;
13
6
  mod heartbeat_tests;
14
7
  mod polling_tests;
15
8
  mod queries_tests;
16
9
  mod workflow_tests;
17
10
 
11
+ use std::str::FromStr;
12
+ use temporal_client::WorkflowService;
13
+ use temporal_sdk_core::{
14
+ init_worker, telemetry_init, ClientOptionsBuilder, ClientTlsConfig, TlsConfig,
15
+ WorkflowClientTrait,
16
+ };
17
+ use temporal_sdk_core_api::{worker::WorkerConfigBuilder, CoreTelemetry};
18
+ use temporal_sdk_core_protos::temporal::api::workflowservice::v1::ListNamespacesRequest;
19
+ use temporal_sdk_core_test_utils::{
20
+ get_integ_server_options, get_integ_telem_options, NAMESPACE,
21
+ };
22
+ use url::Url;
23
+
24
+ // Create a worker like a bridge would (unwraps aside)
25
+ #[tokio::test]
26
+ #[ignore] // Really a compile time check more than anything
27
+ async fn lang_bridge_example() {
28
+ let opts = get_integ_server_options();
29
+ let telem_d = telemetry_init(&get_integ_telem_options()).unwrap();
30
+ let mut retrying_client = opts
31
+ .connect_no_namespace(telem_d.get_metric_meter())
32
+ .await
33
+ .unwrap();
34
+
35
+ let _worker = init_worker(
36
+ WorkerConfigBuilder::default()
37
+ .namespace("default")
38
+ .task_queue("Wheee!")
39
+ .build()
40
+ .unwrap(),
41
+ // clone the client if you intend to use it later. Strip off the retry wrapper since
42
+ // worker will assert its own
43
+ retrying_client.clone(),
44
+ );
45
+
46
+ // Do things with worker or client
47
+ let _ = retrying_client
48
+ .list_namespaces(ListNamespacesRequest::default())
49
+ .await;
50
+ }
51
+
18
52
  // TODO: Currently ignored because starting up the docker image with TLS requires some hoop
19
53
  // jumping. We should upgrade CI to be able to do that but this was manually run against
20
54
  // https://github.com/temporalio/customization-samples/tree/master/tls/tls-simple
@@ -37,9 +71,8 @@ mod integ_tests {
37
71
  )
38
72
  .await
39
73
  .unwrap();
40
- let sgo = ServerGatewayOptionsBuilder::default()
74
+ let sgo = ClientOptionsBuilder::default()
41
75
  .target_url(Url::from_str("https://localhost:7233").unwrap())
42
- .namespace(NAMESPACE.to_string())
43
76
  .worker_binary_id("binident".to_string())
44
77
  .tls_cfg(TlsConfig {
45
78
  server_root_ca_cert: Some(root),
@@ -51,7 +84,7 @@ mod integ_tests {
51
84
  })
52
85
  .build()
53
86
  .unwrap();
54
- let con = sgo.connect(None).await.unwrap();
87
+ let con = sgo.connect(NAMESPACE.to_string(), None).await.unwrap();
55
88
  con.list_namespaces().await.unwrap();
56
89
  }
57
90
  }
@@ -9,8 +9,8 @@ use opentelemetry::trace::{SpanContext, SpanId, TraceFlags, TraceId, TraceState}
9
9
  use std::{fmt::Display, net::SocketAddr, str::FromStr, time::Duration};
10
10
  use temporal_sdk_core::{
11
11
  api::worker::{WorkerConfig, WorkerConfigBuilder},
12
- ClientTlsConfig, RetryConfig, ServerGatewayOptions, ServerGatewayOptionsBuilder,
13
- TelemetryOptions, TelemetryOptionsBuilder, TlsConfig, Url,
12
+ ClientOptions, ClientOptionsBuilder, ClientTlsConfig, RetryConfig, TelemetryOptions,
13
+ TelemetryOptionsBuilder, TlsConfig, Url,
14
14
  };
15
15
 
16
16
  macro_rules! js_value_getter {
@@ -105,10 +105,7 @@ where
105
105
 
106
106
  pub(crate) trait ObjectHandleConversionsExt {
107
107
  fn as_otel_span_context(&self, ctx: &mut FunctionContext) -> NeonResult<SpanContext>;
108
- fn as_server_gateway_options(
109
- &self,
110
- ctx: &mut FunctionContext,
111
- ) -> NeonResult<ServerGatewayOptions>;
108
+ fn as_client_options(&self, ctx: &mut FunctionContext) -> NeonResult<ClientOptions>;
112
109
  fn as_telemetry_options(&self, cx: &mut FunctionContext) -> NeonResult<TelemetryOptions>;
113
110
  fn as_worker_config(&self, cx: &mut FunctionContext) -> NeonResult<WorkerConfig>;
114
111
  }
@@ -127,10 +124,7 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
127
124
  ))
128
125
  }
129
126
 
130
- fn as_server_gateway_options(
131
- &self,
132
- cx: &mut FunctionContext,
133
- ) -> NeonResult<ServerGatewayOptions> {
127
+ fn as_client_options(&self, cx: &mut FunctionContext) -> NeonResult<ClientOptions> {
134
128
  let url = match Url::parse(&js_value_getter!(cx, self, "url", JsString)) {
135
129
  Ok(url) => url,
136
130
  // Note that address is what's used in the Node side.
@@ -204,7 +198,7 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
204
198
  },
205
199
  };
206
200
 
207
- let mut gateway_opts = ServerGatewayOptionsBuilder::default();
201
+ let mut gateway_opts = ClientOptionsBuilder::default();
208
202
  if let Some(tls_cfg) = tls_cfg {
209
203
  gateway_opts.tls_cfg(tls_cfg);
210
204
  }
@@ -212,7 +206,6 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
212
206
  .client_name("temporal-typescript".to_string())
213
207
  .client_version(js_value_getter!(cx, self, "sdkVersion", JsString))
214
208
  .target_url(url)
215
- .namespace(js_value_getter!(cx, self, "namespace", JsString))
216
209
  .identity(js_value_getter!(cx, self, "identity", JsString))
217
210
  .worker_binary_id(js_value_getter!(cx, self, "workerBinaryId", JsString))
218
211
  .retry_config(retry_config)
@@ -255,6 +248,7 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
255
248
  }
256
249
 
257
250
  fn as_worker_config(&self, cx: &mut FunctionContext) -> NeonResult<WorkerConfig> {
251
+ let namespace = js_value_getter!(cx, self, "namespace", JsString);
258
252
  let task_queue = js_value_getter!(cx, self, "taskQueue", JsString);
259
253
  let max_outstanding_activities =
260
254
  js_value_getter!(cx, self, "maxConcurrentActivityTaskExecutions", JsNumber) as usize;
@@ -298,6 +292,7 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
298
292
  .max_cached_workflows(max_cached_workflows)
299
293
  .nonsticky_to_sticky_poll_ratio(nonsticky_to_sticky_poll_ratio)
300
294
  .sticky_queue_schedule_to_start_timeout(sticky_queue_schedule_to_start_timeout)
295
+ .namespace(namespace)
301
296
  .task_queue(task_queue)
302
297
  .max_heartbeat_throttle_interval(max_heartbeat_throttle_interval)
303
298
  .default_heartbeat_throttle_interval(default_heartbeat_throttle_interval)