@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
@@ -1,6 +1,9 @@
1
1
  mod options;
2
2
 
3
- pub use options::{ActivityOptions, ChildWorkflowOptions, LocalActivityOptions};
3
+ pub use options::{
4
+ ActivityOptions, ChildWorkflowOptions, LocalActivityOptions, Signal, SignalData,
5
+ SignalWorkflowOptions,
6
+ };
4
7
 
5
8
  use crate::{
6
9
  workflow_context::options::IntoWorkflowCommand, CancelExternalWfResult, CancellableID,
@@ -31,7 +34,7 @@ use temporal_sdk_core_protos::coresdk::{
31
34
  request_cancel_external_workflow_execution as cancel_we,
32
35
  signal_external_workflow_execution as sig_we, workflow_command,
33
36
  RequestCancelExternalWorkflowExecution, SetPatchMarker, SignalExternalWorkflowExecution,
34
- StartTimer,
37
+ StartTimer, UpsertWorkflowSearchAttributes,
35
38
  },
36
39
  };
37
40
  use tokio::sync::{mpsc, oneshot, watch};
@@ -56,6 +59,7 @@ struct WfCtxProtectedDat {
56
59
  next_child_workflow_sequence_number: u32,
57
60
  next_cancel_external_wf_sequence_number: u32,
58
61
  next_signal_external_wf_sequence_number: u32,
62
+ next_upsert_search_attrs_sequence_number: u32,
59
63
  }
60
64
 
61
65
  impl WfCtxProtectedDat {
@@ -84,6 +88,11 @@ impl WfCtxProtectedDat {
84
88
  self.next_signal_external_wf_sequence_number += 1;
85
89
  seq
86
90
  }
91
+ fn next_upsert_search_attrs_wf_seq(&mut self) -> u32 {
92
+ let seq = self.next_upsert_search_attrs_sequence_number;
93
+ self.next_upsert_search_attrs_sequence_number += 1;
94
+ seq
95
+ }
87
96
  }
88
97
 
89
98
  #[derive(Clone, Debug, Default)]
@@ -121,6 +130,7 @@ impl WfContext {
121
130
  next_child_workflow_sequence_number: 1,
122
131
  next_cancel_external_wf_sequence_number: 1,
123
132
  next_signal_external_wf_sequence_number: 1,
133
+ next_upsert_search_attrs_sequence_number: 1,
124
134
  }),
125
135
  },
126
136
  rx,
@@ -265,24 +275,34 @@ impl WfContext {
265
275
  /// or was cancelled.
266
276
  pub fn signal_workflow(
267
277
  &self,
268
- workflow_id: impl Into<String>,
269
- run_id: impl Into<String>,
270
- signal_name: impl Into<String>,
271
- payload: impl Into<Payload>,
278
+ opts: impl Into<SignalWorkflowOptions>,
272
279
  ) -> impl CancellableFuture<SignalExternalWfResult> {
280
+ let options: SignalWorkflowOptions = opts.into();
273
281
  let target = sig_we::Target::WorkflowExecution(NamespacedWorkflowExecution {
274
282
  namespace: self.namespace.clone(),
275
- workflow_id: workflow_id.into(),
276
- run_id: run_id.into(),
283
+ workflow_id: options.workflow_id,
284
+ run_id: options.run_id.unwrap_or_default(),
277
285
  });
278
- self.send_signal_wf(signal_name, payload, target)
286
+ self.send_signal_wf(target, options.signal)
287
+ }
288
+
289
+ /// Add or create a set of search attributes
290
+ pub fn upsert_search_attributes(&self, attr_iter: impl IntoIterator<Item = (String, Payload)>) {
291
+ self.send(RustWfCmd::NewNonblockingCmd(
292
+ workflow_command::Variant::UpsertWorkflowSearchAttributesCommandAttributes(
293
+ UpsertWorkflowSearchAttributes {
294
+ seq: self.seq_nums.write().next_upsert_search_attrs_wf_seq(),
295
+ search_attributes: HashMap::from_iter(attr_iter.into_iter()),
296
+ },
297
+ ),
298
+ ))
279
299
  }
280
300
 
281
301
  /// Return a stream that produces values when the named signal is sent to this workflow
282
302
  pub fn make_signal_channel(
283
303
  &self,
284
304
  signal_name: impl Into<String>,
285
- ) -> impl Stream<Item = Vec<Payload>> {
305
+ ) -> impl Stream<Item = SignalData> {
286
306
  let (tx, rx) = mpsc::unbounded_channel();
287
307
  self.send(RustWfCmd::SubscribeSignal(signal_name.into(), tx));
288
308
  UnboundedReceiverStream::new(rx)
@@ -318,9 +338,8 @@ impl WfContext {
318
338
 
319
339
  fn send_signal_wf(
320
340
  &self,
321
- signal_name: impl Into<String>,
322
- payload: impl Into<Payload>,
323
341
  target: sig_we::Target,
342
+ signal: Signal,
324
343
  ) -> impl CancellableFuture<SignalExternalWfResult> {
325
344
  let seq = self.seq_nums.write().next_signal_external_wf_seq();
326
345
  let (cmd, unblocker) =
@@ -329,9 +348,10 @@ impl WfContext {
329
348
  CommandCreateRequest {
330
349
  cmd: SignalExternalWorkflowExecution {
331
350
  seq,
332
- signal_name: signal_name.into(),
333
- args: vec![payload.into()],
351
+ signal_name: signal.signal_name,
352
+ args: signal.data.input,
334
353
  target: Some(target),
354
+ headers: signal.data.headers,
335
355
  }
336
356
  .into(),
337
357
  unblocker,
@@ -636,10 +656,9 @@ impl StartedChildWorkflow {
636
656
  pub fn signal(
637
657
  &self,
638
658
  cx: &WfContext,
639
- signal_name: impl Into<String>,
640
- payload: impl Into<Payload>,
659
+ data: impl Into<Signal>,
641
660
  ) -> impl CancellableFuture<SignalExternalWfResult> {
642
661
  let target = sig_we::Target::ChildWorkflowId(self.common.workflow_id.clone());
643
- cx.send_signal_wf(signal_name, payload, target)
662
+ cx.send_signal_wf(target, data.into())
644
663
  }
645
664
  }
@@ -1,6 +1,7 @@
1
1
  use crate::{
2
2
  conversions::anyhow_to_fail, workflow_context::WfContextSharedData, CancellableID, RustWfCmd,
3
- TimerResult, UnblockEvent, WfContext, WfExitValue, WorkflowFunction, WorkflowResult,
3
+ SignalData, TimerResult, UnblockEvent, WfContext, WfExitValue, WorkflowFunction,
4
+ WorkflowResult,
4
5
  };
5
6
  use anyhow::{anyhow, bail, Context as AnyhowContext, Error};
6
7
  use crossbeam::channel::Receiver;
@@ -55,12 +56,10 @@ impl WorkflowFunction {
55
56
  UnboundedSender<WorkflowActivation>,
56
57
  ) {
57
58
  let (cancel_tx, cancel_rx) = watch::channel(false);
58
- let (wf_context, cmd_receiver) =
59
- WfContext::new(namespace, task_queue.clone(), args, cancel_rx);
59
+ let (wf_context, cmd_receiver) = WfContext::new(namespace, task_queue, args, cancel_rx);
60
60
  let (tx, incoming_activations) = unbounded_channel();
61
61
  (
62
62
  WorkflowFuture {
63
- task_queue,
64
63
  ctx_shared: wf_context.get_shared_data(),
65
64
  // We need to mark the workflow future as unconstrained, otherwise Tokio will impose
66
65
  // an artificial limit on how many commands we can unblock in one poll round.
@@ -88,13 +87,11 @@ struct WFCommandFutInfo {
88
87
  // production-ready SDK design, or if desired to allow dynamic signal registration, prevent this
89
88
  // from growing unbounded if being sent lots of unhandled signals.
90
89
  enum SigChanOrBuffer {
91
- Chan(UnboundedSender<Vec<Payload>>),
92
- Buffer(Vec<Vec<Payload>>),
90
+ Chan(UnboundedSender<SignalData>),
91
+ Buffer(Vec<SignalData>),
93
92
  }
94
93
 
95
94
  pub struct WorkflowFuture {
96
- /// What task queue this workflow belongs to
97
- task_queue: String,
98
95
  /// Future produced by calling the workflow function
99
96
  inner: BoxFuture<'static, WorkflowResult<()>>,
100
97
  /// Commands produced inside user's wf code
@@ -138,7 +135,6 @@ impl WorkflowFuture {
138
135
  warn!("Workflow task failed for {}: {}", run_id, fail);
139
136
  self.outgoing_completions
140
137
  .send(WorkflowActivationCompletion::fail(
141
- &self.task_queue,
142
138
  run_id,
143
139
  anyhow_to_fail(fail),
144
140
  ))
@@ -148,7 +144,6 @@ impl WorkflowFuture {
148
144
  fn send_completion(&self, run_id: String, activation_cmds: Vec<workflow_command::Variant>) {
149
145
  self.outgoing_completions
150
146
  .send(WorkflowActivationCompletion::from_cmds(
151
- &self.task_queue,
152
147
  run_id,
153
148
  activation_cmds,
154
149
  ))
@@ -199,17 +194,21 @@ impl WorkflowFuture {
199
194
  .send(true)
200
195
  .expect("Cancel rx not dropped");
201
196
  }
202
- Variant::SignalWorkflow(sig) => match self.sig_chans.entry(sig.signal_name) {
203
- Entry::Occupied(mut o) => match o.get_mut() {
204
- SigChanOrBuffer::Chan(chan) => {
205
- let _ = chan.send(sig.input);
197
+ Variant::SignalWorkflow(sig) => {
198
+ let mut dat = SignalData::new(sig.input);
199
+ dat.headers = sig.headers;
200
+ match self.sig_chans.entry(sig.signal_name) {
201
+ Entry::Occupied(mut o) => match o.get_mut() {
202
+ SigChanOrBuffer::Chan(chan) => {
203
+ let _ = chan.send(dat);
204
+ }
205
+ SigChanOrBuffer::Buffer(ref mut buf) => buf.push(dat),
206
+ },
207
+ Entry::Vacant(v) => {
208
+ v.insert(SigChanOrBuffer::Buffer(vec![dat]));
206
209
  }
207
- SigChanOrBuffer::Buffer(ref mut buf) => buf.push(sig.input),
208
- },
209
- Entry::Vacant(v) => {
210
- v.insert(SigChanOrBuffer::Buffer(vec![sig.input]));
211
210
  }
212
- },
211
+ }
213
212
  Variant::NotifyHasPatch(NotifyHasPatch { patch_id }) => {
214
213
  self.ctx_shared.write().changes.insert(patch_id, true);
215
214
  }
@@ -268,11 +267,7 @@ impl Future for WorkflowFuture {
268
267
  if is_only_eviction {
269
268
  // No need to do anything with the workflow code in this case
270
269
  self.outgoing_completions
271
- .send(WorkflowActivationCompletion::from_cmds(
272
- &self.task_queue,
273
- run_id,
274
- vec![],
275
- ))
270
+ .send(WorkflowActivationCompletion::from_cmds(run_id, vec![]))
276
271
  .expect("Completion channel intact");
277
272
  return Ok(WfExitValue::Evicted).into();
278
273
  }
@@ -291,7 +286,6 @@ impl Future for WorkflowFuture {
291
286
  warn!("{}", errmsg);
292
287
  self.outgoing_completions
293
288
  .send(WorkflowActivationCompletion::fail(
294
- &self.task_queue,
295
289
  run_id,
296
290
  Failure {
297
291
  message: errmsg,
@@ -27,4 +27,4 @@ tonic = "0.6"
27
27
  uuid = { version = "0.8.2", features = ["v4"], optional = true }
28
28
 
29
29
  [build-dependencies]
30
- tonic-build = "0.5"
30
+ tonic-build = "0.6"
@@ -1,4 +1,5 @@
1
1
  fn main() -> Result<(), Box<dyn std::error::Error>> {
2
+ println!("cargo:rerun-if-changed=../protos");
2
3
  tonic_build::configure()
3
4
  // We don't actually want to build the grpc definitions - we don't need them (for now).
4
5
  // Just build the message structs.
@@ -3,7 +3,7 @@ use crate::temporal::api::{
3
3
  enums::v1::{EventType, TaskQueueKind},
4
4
  history::v1::{history_event, History, HistoryEvent},
5
5
  taskqueue::v1::TaskQueue,
6
- workflowservice::v1::PollWorkflowTaskQueueResponse,
6
+ workflowservice::v1::{GetWorkflowExecutionHistoryResponse, PollWorkflowTaskQueueResponse},
7
7
  };
8
8
  use anyhow::{anyhow, bail};
9
9
  use rand::{thread_rng, Rng};
@@ -42,9 +42,9 @@ impl HistoryInfo {
42
42
  attrs
43
43
  .workflow_type
44
44
  .as_ref()
45
- .ok_or(anyhow!(
46
- "No workflow type defined in execution started attributes"
47
- ))?
45
+ .ok_or_else(|| {
46
+ anyhow!("No workflow type defined in execution started attributes")
47
+ })?
48
48
  .name
49
49
  .clone()
50
50
  }
@@ -117,6 +117,10 @@ impl HistoryInfo {
117
117
  /// Remove events from the beginning of this history such that it looks like what would've been
118
118
  /// delivered on a sticky queue where the previously started task was the one before the last
119
119
  /// task in this history.
120
+ ///
121
+ /// This is not *fully* accurate in that it will include commands that were part of the last
122
+ /// WFT completion, which the server would typically not include, but it's good enough for
123
+ /// testing.
120
124
  pub fn make_incremental(&mut self) {
121
125
  let last_complete_ix = self
122
126
  .events
@@ -182,6 +186,15 @@ impl From<HistoryInfo> for History {
182
186
  }
183
187
  }
184
188
 
189
+ impl From<HistoryInfo> for GetWorkflowExecutionHistoryResponse {
190
+ fn from(i: HistoryInfo) -> Self {
191
+ Self {
192
+ history: Some(i.into()),
193
+ ..Default::default()
194
+ }
195
+ }
196
+ }
197
+
185
198
  #[cfg(test)]
186
199
  mod tests {
187
200
  use crate::{temporal::api::enums::v1::EventType, TestHistoryBuilder};