@temporalio/core-bridge 1.5.2 → 1.6.0

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 (153) hide show
  1. package/Cargo.lock +255 -48
  2. package/package.json +4 -4
  3. package/releases/aarch64-apple-darwin/index.node +0 -0
  4. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  5. package/releases/x86_64-apple-darwin/index.node +0 -0
  6. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  7. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  8. package/sdk-core/.buildkite/pipeline.yml +1 -3
  9. package/sdk-core/.cargo/config.toml +5 -2
  10. package/sdk-core/.github/workflows/heavy.yml +28 -0
  11. package/sdk-core/Cargo.toml +1 -1
  12. package/sdk-core/README.md +9 -5
  13. package/sdk-core/client/src/lib.rs +211 -36
  14. package/sdk-core/client/src/raw.rs +1 -1
  15. package/sdk-core/client/src/retry.rs +32 -20
  16. package/sdk-core/core/Cargo.toml +23 -9
  17. package/sdk-core/core/src/abstractions.rs +11 -0
  18. package/sdk-core/core/src/core_tests/activity_tasks.rs +6 -5
  19. package/sdk-core/core/src/core_tests/local_activities.rs +263 -22
  20. package/sdk-core/core/src/core_tests/queries.rs +2 -2
  21. package/sdk-core/core/src/core_tests/workflow_tasks.rs +249 -5
  22. package/sdk-core/core/src/ephemeral_server/mod.rs +5 -6
  23. package/sdk-core/core/src/lib.rs +2 -0
  24. package/sdk-core/core/src/protosext/mod.rs +1 -1
  25. package/sdk-core/core/src/telemetry/log_export.rs +1 -1
  26. package/sdk-core/core/src/telemetry/mod.rs +23 -8
  27. package/sdk-core/core/src/test_help/mod.rs +8 -1
  28. package/sdk-core/core/src/worker/activities/local_activities.rs +259 -125
  29. package/sdk-core/core/src/worker/activities.rs +3 -2
  30. package/sdk-core/core/src/worker/mod.rs +53 -26
  31. package/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
  32. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
  33. package/sdk-core/core/src/worker/workflow/history_update.rs +835 -277
  34. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +9 -17
  35. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +3 -5
  36. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -2
  37. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +3 -5
  38. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -2
  39. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +1 -2
  40. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -2
  41. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +73 -51
  42. package/sdk-core/core/src/worker/workflow/machines/mod.rs +3 -3
  43. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +4 -4
  44. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -2
  45. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +3 -5
  46. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +6 -7
  47. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  48. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +4 -4
  49. package/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
  50. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +89 -58
  51. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +4 -7
  52. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +21 -9
  53. package/sdk-core/core/src/worker/workflow/managed_run.rs +1021 -360
  54. package/sdk-core/core/src/worker/workflow/mod.rs +306 -346
  55. package/sdk-core/core/src/worker/workflow/run_cache.rs +29 -53
  56. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
  57. package/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
  58. package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +115 -0
  59. package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
  60. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +444 -714
  61. package/sdk-core/core-api/Cargo.toml +2 -0
  62. package/sdk-core/core-api/src/errors.rs +1 -34
  63. package/sdk-core/core-api/src/lib.rs +6 -2
  64. package/sdk-core/core-api/src/worker.rs +14 -1
  65. package/sdk-core/etc/deps.svg +115 -140
  66. package/sdk-core/etc/regen-depgraph.sh +5 -0
  67. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -6
  68. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +7 -3
  69. package/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  70. package/sdk-core/protos/api_upstream/Makefile +5 -5
  71. package/sdk-core/protos/api_upstream/build/go.mod +7 -0
  72. package/sdk-core/protos/api_upstream/build/go.sum +5 -0
  73. package/sdk-core/protos/api_upstream/build/tools.go +29 -0
  74. package/sdk-core/protos/api_upstream/go.mod +6 -0
  75. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +9 -2
  76. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +12 -19
  77. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +2 -2
  78. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
  79. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +3 -2
  80. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
  81. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +3 -3
  82. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +20 -2
  83. package/sdk-core/protos/api_upstream/temporal/api/{update/v1/message.proto → enums/v1/interaction_type.proto} +11 -18
  84. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
  85. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
  86. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
  87. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
  88. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
  89. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +2 -13
  90. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
  91. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
  92. package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
  93. package/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
  94. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +13 -19
  95. package/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +87 -0
  96. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -2
  97. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +2 -2
  98. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -2
  99. package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
  100. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
  101. package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
  102. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
  103. package/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
  104. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -2
  105. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +13 -8
  106. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
  107. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  108. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
  109. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
  110. package/sdk-core/sdk/Cargo.toml +4 -3
  111. package/sdk-core/sdk/src/lib.rs +87 -21
  112. package/sdk-core/sdk/src/workflow_future.rs +7 -12
  113. package/sdk-core/sdk-core-protos/Cargo.toml +5 -2
  114. package/sdk-core/sdk-core-protos/build.rs +36 -2
  115. package/sdk-core/sdk-core-protos/src/history_builder.rs +26 -19
  116. package/sdk-core/sdk-core-protos/src/history_info.rs +4 -0
  117. package/sdk-core/sdk-core-protos/src/lib.rs +78 -34
  118. package/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
  119. package/sdk-core/test-utils/Cargo.toml +3 -1
  120. package/sdk-core/test-utils/src/histfetch.rs +1 -1
  121. package/sdk-core/test-utils/src/lib.rs +50 -18
  122. package/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
  123. package/sdk-core/test-utils/src/workflows.rs +29 -0
  124. package/sdk-core/tests/fuzzy_workflow.rs +130 -0
  125. package/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +114 -7
  126. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -2
  127. package/sdk-core/tests/integ_tests/metrics_tests.rs +1 -1
  128. package/sdk-core/tests/integ_tests/polling_tests.rs +1 -39
  129. package/sdk-core/tests/integ_tests/queries_tests.rs +2 -127
  130. package/sdk-core/tests/integ_tests/visibility_tests.rs +52 -5
  131. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +74 -1
  132. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +5 -13
  133. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +1 -1
  134. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +2 -10
  135. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +69 -197
  136. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +4 -28
  137. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +12 -7
  138. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +14 -14
  139. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +3 -19
  140. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +3 -19
  141. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +1 -1
  142. package/sdk-core/tests/integ_tests/workflow_tests.rs +5 -6
  143. package/sdk-core/tests/main.rs +2 -12
  144. package/sdk-core/tests/runner.rs +71 -34
  145. package/sdk-core/tests/wf_input_replay.rs +32 -0
  146. package/sdk-core/bridge-ffi/Cargo.toml +0 -24
  147. package/sdk-core/bridge-ffi/LICENSE.txt +0 -23
  148. package/sdk-core/bridge-ffi/build.rs +0 -25
  149. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -224
  150. package/sdk-core/bridge-ffi/src/lib.rs +0 -746
  151. package/sdk-core/bridge-ffi/src/wrappers.rs +0 -221
  152. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
  153. package/sdk-core/sdk/src/conversions.rs +0 -8
@@ -1,7 +1,5 @@
1
1
  mod local_acts;
2
2
 
3
- pub(crate) use temporal_sdk_core_api::errors::WFMachinesError;
4
-
5
3
  use super::{
6
4
  activity_state_machine::new_activity, cancel_external_state_machine::new_external_cancel,
7
5
  cancel_workflow_state_machine::cancel_workflow,
@@ -20,9 +18,10 @@ use crate::{
20
18
  telemetry::{metrics::MetricsContext, VecDisplayer},
21
19
  worker::{
22
20
  workflow::{
21
+ history_update::NextWFT,
23
22
  machines::modify_workflow_properties_state_machine::modify_workflow_properties,
24
23
  CommandID, DrivenWorkflow, HistoryUpdate, LocalResolution, OutgoingJob, WFCommand,
25
- WorkflowFetcher, WorkflowStartedInfo,
24
+ WFMachinesError, WorkflowFetcher, WorkflowStartedInfo,
26
25
  },
27
26
  ExecutingLAId, LocalActRequest, LocalActivityExecutionResult, LocalActivityResolution,
28
27
  },
@@ -133,7 +132,7 @@ pub(crate) struct WorkflowMachines {
133
132
  }
134
133
 
135
134
  #[derive(Debug, derive_more::Display)]
136
- #[display(fmt = "Cmd&Machine({})", "command")]
135
+ #[display(fmt = "Cmd&Machine({command})")]
137
136
  struct CommandAndMachine {
138
137
  command: MachineAssociatedCommand,
139
138
  machine: MachineKey,
@@ -142,7 +141,7 @@ struct CommandAndMachine {
142
141
  #[derive(Debug, derive_more::Display)]
143
142
  enum MachineAssociatedCommand {
144
143
  Real(Box<ProtoCommand>),
145
- #[display(fmt = "FakeLocalActivityMarker({})", "_0")]
144
+ #[display(fmt = "FakeLocalActivityMarker({_0})")]
146
145
  FakeLocalActivityMarker(u32),
147
146
  }
148
147
 
@@ -156,7 +155,7 @@ struct ChangeInfo {
156
155
  #[must_use]
157
156
  #[allow(clippy::large_enum_variant)]
158
157
  pub(super) enum MachineResponse {
159
- #[display(fmt = "PushWFJob({})", "_0")]
158
+ #[display(fmt = "PushWFJob({_0})")]
160
159
  PushWFJob(OutgoingJob),
161
160
 
162
161
  /// Pushes a new command into the list that will be sent to server once we respond with the
@@ -165,31 +164,31 @@ pub(super) enum MachineResponse {
165
164
  /// The machine requests the creation of another *different* machine. This acts as if lang
166
165
  /// had replied to the activation with a command, but we use a special set of IDs to avoid
167
166
  /// collisions.
168
- #[display(fmt = "NewCoreOriginatedCommand({:?})", "_0")]
167
+ #[display(fmt = "NewCoreOriginatedCommand({_0:?})")]
169
168
  NewCoreOriginatedCommand(ProtoCmdAttrs),
170
- #[display(fmt = "IssueFakeLocalActivityMarker({})", "_0")]
169
+ #[display(fmt = "IssueFakeLocalActivityMarker({_0})")]
171
170
  IssueFakeLocalActivityMarker(u32),
172
171
  #[display(fmt = "TriggerWFTaskStarted")]
173
172
  TriggerWFTaskStarted {
174
173
  task_started_event_id: i64,
175
174
  time: SystemTime,
176
175
  },
177
- #[display(fmt = "UpdateRunIdOnWorkflowReset({})", run_id)]
176
+ #[display(fmt = "UpdateRunIdOnWorkflowReset({run_id})")]
178
177
  UpdateRunIdOnWorkflowReset { run_id: String },
179
178
 
180
179
  /// Queue a local activity to be processed by the worker
181
180
  #[display(fmt = "QueueLocalActivity")]
182
181
  QueueLocalActivity(ValidScheduleLA),
183
182
  /// Request cancellation of an executing local activity
184
- #[display(fmt = "RequestCancelLocalActivity({})", "_0")]
183
+ #[display(fmt = "RequestCancelLocalActivity({_0})")]
185
184
  RequestCancelLocalActivity(u32),
186
185
  /// Indicates we are abandoning the indicated LA, so we can remove it from "outstanding" LAs
187
186
  /// and we will not try to WFT heartbeat because of it.
188
- #[display(fmt = "AbandonLocalActivity({:?})", "_0")]
187
+ #[display(fmt = "AbandonLocalActivity({_0:?})")]
189
188
  AbandonLocalActivity(u32),
190
189
 
191
190
  /// Set the workflow time to the provided time
192
- #[display(fmt = "UpdateWFTime({:?})", "_0")]
191
+ #[display(fmt = "UpdateWFTime({_0:?})")]
193
192
  UpdateWFTime(Option<SystemTime>),
194
193
  }
195
194
 
@@ -212,7 +211,7 @@ impl WorkflowMachines {
212
211
  driven_wf: DrivenWorkflow,
213
212
  metrics: MetricsContext,
214
213
  ) -> Self {
215
- let replaying = history.previous_started_event_id > 0;
214
+ let replaying = history.previous_wft_started_id > 0;
216
215
  Self {
217
216
  last_history_from_server: history,
218
217
  namespace,
@@ -255,10 +254,10 @@ impl WorkflowMachines {
255
254
  .and_then(|(st, et)| et.duration_since(st).ok())
256
255
  }
257
256
 
258
- pub(crate) async fn new_history_from_server(&mut self, update: HistoryUpdate) -> Result<()> {
257
+ pub(crate) fn new_history_from_server(&mut self, update: HistoryUpdate) -> Result<()> {
259
258
  self.last_history_from_server = update;
260
- self.replaying = self.last_history_from_server.previous_started_event_id > 0;
261
- self.apply_next_wft_from_history().await?;
259
+ self.replaying = self.last_history_from_server.previous_wft_started_id > 0;
260
+ self.apply_next_wft_from_history()?;
262
261
  Ok(())
263
262
  }
264
263
 
@@ -290,9 +289,8 @@ impl WorkflowMachines {
290
289
  self.process_machine_responses(mk, resps)?;
291
290
  } else {
292
291
  return Err(WFMachinesError::Nondeterminism(format!(
293
- "Command matching activity with seq num {} existed but was not a \
294
- local activity!",
295
- seq
292
+ "Command matching activity with seq num {seq} existed but was not a \
293
+ local activity!"
296
294
  )));
297
295
  }
298
296
  self.local_activity_data.done_executing(seq);
@@ -366,8 +364,8 @@ impl WorkflowMachines {
366
364
 
367
365
  /// Iterate the state machines, which consists of grabbing any pending outgoing commands from
368
366
  /// the workflow code, handling them, and preparing them to be sent off to the server.
369
- pub(crate) async fn iterate_machines(&mut self) -> Result<()> {
370
- let results = self.drive_me.fetch_workflow_iteration_output().await;
367
+ pub(crate) fn iterate_machines(&mut self) -> Result<()> {
368
+ let results = self.drive_me.fetch_workflow_iteration_output();
371
369
  self.handle_driven_results(results)?;
372
370
  self.prepare_commands()?;
373
371
  if self.workflow_is_finished() {
@@ -378,10 +376,16 @@ impl WorkflowMachines {
378
376
  Ok(())
379
377
  }
380
378
 
379
+ /// Returns true if machines are ready to apply the next WFT sequence, false if events will need
380
+ /// to be fetched in order to create a complete update with the entire next WFT sequence.
381
+ pub(crate) fn ready_to_apply_next_wft(&self) -> bool {
382
+ self.last_history_from_server
383
+ .can_take_next_wft_sequence(self.current_started_event_id)
384
+ }
385
+
381
386
  /// Apply the next (unapplied) entire workflow task from history to these machines. Will replay
382
- /// any events that need to be replayed until caught up to the newest WFT. May also fetch
383
- /// history from server if needed.
384
- pub(crate) async fn apply_next_wft_from_history(&mut self) -> Result<usize> {
387
+ /// any events that need to be replayed until caught up to the newest WFT.
388
+ pub(crate) fn apply_next_wft_from_history(&mut self) -> Result<usize> {
385
389
  // If we have already seen the terminal event for the entire workflow in a previous WFT,
386
390
  // then we don't need to do anything here, and in fact we need to avoid re-applying the
387
391
  // final WFT.
@@ -390,16 +394,25 @@ impl WorkflowMachines {
390
394
  }
391
395
 
392
396
  let last_handled_wft_started_id = self.current_started_event_id;
393
- let events = {
394
- let mut evts = self
397
+ let events =
398
+ match self
395
399
  .last_history_from_server
396
400
  .take_next_wft_sequence(last_handled_wft_started_id)
397
- .await
398
- .map_err(WFMachinesError::HistoryFetchingError)?;
399
- // Do not re-process events we have already processed
400
- evts.retain(|e| e.event_id > self.last_processed_event);
401
- evts
402
- };
401
+ {
402
+ NextWFT::ReplayOver => {
403
+ vec![]
404
+ }
405
+ NextWFT::WFT(mut evts) => {
406
+ // Do not re-process events we have already processed
407
+ evts.retain(|e| e.event_id > self.last_processed_event);
408
+ evts
409
+ }
410
+ NextWFT::NeedFetch => return Err(WFMachinesError::Fatal(
411
+ "Need to fetch history events to continue applying workflow task, but this \
412
+ should be prevented ahead of time! This is a Core SDK bug."
413
+ .to_string(),
414
+ )),
415
+ };
403
416
  let num_events_to_process = events.len();
404
417
 
405
418
  // We're caught up on reply if there are no new events to process
@@ -434,7 +447,11 @@ impl WorkflowMachines {
434
447
 
435
448
  // Scan through to the next WFT, searching for any patch / la markers, so that we can
436
449
  // pre-resolve them.
437
- for e in self.last_history_from_server.peek_next_wft_sequence() {
450
+ let mut wake_las = vec![];
451
+ for e in self
452
+ .last_history_from_server
453
+ .peek_next_wft_sequence(last_handled_wft_started_id)
454
+ {
438
455
  if let Some((patch_id, _)) = e.get_patch_marker_details() {
439
456
  self.encountered_change_markers.insert(
440
457
  patch_id.clone(),
@@ -448,7 +465,30 @@ impl WorkflowMachines {
448
465
  .into(),
449
466
  );
450
467
  } else if e.is_local_activity_marker() {
451
- self.local_activity_data.process_peekahead_marker(e)?;
468
+ if let Some(la_dat) = e.clone().into_local_activity_marker_details() {
469
+ if let Ok(mk) =
470
+ self.get_machine_key(CommandID::LocalActivity(la_dat.marker_dat.seq))
471
+ {
472
+ wake_las.push((mk, la_dat));
473
+ } else {
474
+ self.local_activity_data.insert_peeked_marker(la_dat);
475
+ }
476
+ } else {
477
+ return Err(WFMachinesError::Fatal(format!(
478
+ "Local activity marker was unparsable: {e:?}"
479
+ )));
480
+ }
481
+ }
482
+ }
483
+ for (mk, la_dat) in wake_las {
484
+ let mach = self.machine_mut(mk);
485
+ if let Machines::LocalActivityMachine(ref mut lam) = *mach {
486
+ if lam.will_accept_resolve_marker() {
487
+ let resps = lam.try_resolve_with_dat(la_dat.into())?;
488
+ self.process_machine_responses(mk, resps)?;
489
+ } else {
490
+ self.local_activity_data.insert_peeked_marker(la_dat);
491
+ }
452
492
  }
453
493
  }
454
494
 
@@ -488,7 +528,7 @@ impl WorkflowMachines {
488
528
  }
489
529
  if self.replaying
490
530
  && self.current_started_event_id
491
- >= self.last_history_from_server.previous_started_event_id
531
+ >= self.last_history_from_server.previous_wft_started_id
492
532
  && event.event_type() != EventType::WorkflowTaskCompleted
493
533
  {
494
534
  // Replay is finished
@@ -497,8 +537,7 @@ impl WorkflowMachines {
497
537
  if event.event_type() == EventType::Unspecified || event.attributes.is_none() {
498
538
  return if !event.worker_may_ignore {
499
539
  Err(WFMachinesError::Fatal(format!(
500
- "Event type is unspecified! This history is invalid. Event detail: {:?}",
501
- event
540
+ "Event type is unspecified! This history is invalid. Event detail: {event:?}"
502
541
  )))
503
542
  } else {
504
543
  debug!("Event is ignorable");
@@ -526,8 +565,7 @@ impl WorkflowMachines {
526
565
  None => {
527
566
  return Err(WFMachinesError::Nondeterminism(format!(
528
567
  "During event handling, this event had an initial command ID but we \
529
- could not find a matching command for it: {:?}",
530
- event
568
+ could not find a matching command for it: {event:?}"
531
569
  )));
532
570
  }
533
571
  }
@@ -550,7 +588,7 @@ impl WorkflowMachines {
550
588
  fn handle_command_event(&mut self, event: HistoryEvent) -> Result<()> {
551
589
  if event.is_local_activity_marker() {
552
590
  let deets = event.extract_local_activity_marker_data().ok_or_else(|| {
553
- WFMachinesError::Fatal(format!("Local activity marker was unparsable: {:?}", event))
591
+ WFMachinesError::Fatal(format!("Local activity marker was unparsable: {event:?}"))
554
592
  })?;
555
593
  let cmdid = CommandID::LocalActivity(deets.seq);
556
594
  let mkey = self.get_machine_key(cmdid)?;
@@ -562,8 +600,7 @@ impl WorkflowMachines {
562
600
  } else {
563
601
  return Err(WFMachinesError::Fatal(format!(
564
602
  "Encountered local activity marker but the associated machine was of the \
565
- wrong type! {:?}",
566
- event
603
+ wrong type! {event:?}"
567
604
  )));
568
605
  }
569
606
  }
@@ -588,8 +625,7 @@ impl WorkflowMachines {
588
625
  c
589
626
  } else {
590
627
  return Err(WFMachinesError::Nondeterminism(format!(
591
- "No command scheduled for event {}",
592
- event
628
+ "No command scheduled for event {event}"
593
629
  )));
594
630
  };
595
631
 
@@ -645,8 +681,7 @@ impl WorkflowMachines {
645
681
  );
646
682
  } else {
647
683
  return Err(WFMachinesError::Fatal(format!(
648
- "WorkflowExecutionStarted event did not have appropriate attributes: {}",
649
- event
684
+ "WorkflowExecutionStarted event did not have appropriate attributes: {event}"
650
685
  )));
651
686
  }
652
687
  }
@@ -682,8 +717,7 @@ impl WorkflowMachines {
682
717
  }
683
718
  _ => {
684
719
  return Err(WFMachinesError::Fatal(format!(
685
- "The event is not a non-stateful event, but we tried to handle it as one: {}",
686
- event
720
+ "The event is not a non-stateful event, but we tried to handle it as one: {event}"
687
721
  )));
688
722
  }
689
723
  }
@@ -756,7 +790,7 @@ impl WorkflowMachines {
756
790
  ) -> Result<()> {
757
791
  let sm = self.machine(smk);
758
792
  if !machine_responses.is_empty() {
759
- debug!(responses = %machine_responses.display(), machine_name = %sm.name(),
793
+ trace!(responses = %machine_responses.display(), machine_name = %sm.name(),
760
794
  "Machine produced responses");
761
795
  }
762
796
  self.process_machine_resps_impl(smk, machine_responses)
@@ -811,8 +845,7 @@ impl WorkflowMachines {
811
845
  }
812
846
  c => {
813
847
  return Err(WFMachinesError::Fatal(format!(
814
- "A machine requested to create a new command of an unsupported type: {:?}",
815
- c
848
+ "A machine requested to create a new command of an unsupported type: {c:?}"
816
849
  )))
817
850
  }
818
851
  },
@@ -849,7 +882,7 @@ impl WorkflowMachines {
849
882
  Duration::from_secs(0),
850
883
  removed_act.attempt,
851
884
  None,
852
- None,
885
+ removed_act.original_schedule_time,
853
886
  )?;
854
887
  self.process_machine_responses(smk, more_responses)?;
855
888
  } else {
@@ -937,8 +970,7 @@ impl WorkflowMachines {
937
970
  )
938
971
  .map_err(|e| {
939
972
  WFMachinesError::Fatal(format!(
940
- "Invalid schedule local activity request (seq {}): {}",
941
- seq, e
973
+ "Invalid schedule local activity request (seq {seq}): {e}"
942
974
  ))
943
975
  })?;
944
976
  let (la, mach_resp) = new_local_activity(
@@ -1075,7 +1107,7 @@ impl WorkflowMachines {
1075
1107
 
1076
1108
  fn get_machine_key(&self, id: CommandID) -> Result<MachineKey> {
1077
1109
  Ok(*self.id_to_machine.get(&id).ok_or_else(|| {
1078
- WFMachinesError::Fatal(format!("Missing associated machine for {:?}", id))
1110
+ WFMachinesError::Fatal(format!("Missing associated machine for {id:?}"))
1079
1111
  })?)
1080
1112
  }
1081
1113
 
@@ -1173,9 +1205,8 @@ fn change_marker_handling(event: &HistoryEvent, mach: &Machines) -> Result<Chang
1173
1205
  return Ok(ChangeMarkerOutcome::SkipEvent);
1174
1206
  }
1175
1207
  return Err(WFMachinesError::Nondeterminism(format!(
1176
- "Non-deprecated patch marker encountered for change {}, \
1177
- but there is no corresponding change command!",
1178
- patch_name
1208
+ "Non-deprecated patch marker encountered for change {patch_name}, \
1209
+ but there is no corresponding change command!"
1179
1210
  )));
1180
1211
  }
1181
1212
  // Patch machines themselves may also not *have* matching markers, where non-deprecated
@@ -48,7 +48,7 @@ pub(super) enum WFTaskMachineCommand {
48
48
  task_started_event_id: i64,
49
49
  time: SystemTime,
50
50
  },
51
- #[display(fmt = "RunIdOnWorkflowResetUpdate({})", run_id)]
51
+ #[display(fmt = "RunIdOnWorkflowResetUpdate({run_id})")]
52
52
  RunIdOnWorkflowResetUpdate { run_id: String },
53
53
  }
54
54
 
@@ -121,8 +121,7 @@ impl TryFrom<HistoryEvent> for WorkflowTaskMachineEvents {
121
121
  }
122
122
  } else {
123
123
  return Err(WFMachinesError::Fatal(format!(
124
- "Workflow task started event must contain timestamp: {}",
125
- e
124
+ "Workflow task started event must contain timestamp: {e}"
126
125
  )));
127
126
  };
128
127
  WFTStartedDat {
@@ -150,15 +149,13 @@ impl TryFrom<HistoryEvent> for WorkflowTaskMachineEvents {
150
149
  })
151
150
  } else {
152
151
  return Err(WFMachinesError::Fatal(format!(
153
- "Workflow task failed is missing attributes: {}",
154
- e
152
+ "Workflow task failed is missing attributes: {e}"
155
153
  )));
156
154
  }
157
155
  }
158
156
  _ => {
159
157
  return Err(WFMachinesError::Nondeterminism(format!(
160
- "Event does not apply to a wf task machine: {}",
161
- e
158
+ "Event does not apply to a wf task machine: {e}"
162
159
  )))
163
160
  }
164
161
  })
@@ -4,11 +4,13 @@ use crate::{
4
4
  test_help::TEST_Q,
5
5
  worker::{
6
6
  workflow::{
7
- history_update::TestHBExt, machines::WorkflowMachines, WFCommand, WorkflowFetcher,
7
+ history_update::tests::TestHBExt, machines::WorkflowMachines, WFCommand,
8
+ WorkflowFetcher,
8
9
  },
9
10
  LocalActRequest, LocalActivityResolution,
10
11
  },
11
12
  };
13
+ use crossbeam::channel::bounded;
12
14
  use std::{convert::TryInto, time::Duration};
13
15
  use temporal_sdk::{WorkflowFunction, WorkflowResult};
14
16
  use temporal_sdk_core_protos::{
@@ -27,13 +29,12 @@ use tokio::{
27
29
  };
28
30
 
29
31
  pub(crate) struct WFFutureDriver {
30
- completions_rx: UnboundedReceiver<WorkflowActivationCompletion>,
32
+ completions_q: crossbeam::channel::Receiver<WorkflowActivationCompletion>,
31
33
  }
32
34
 
33
- #[async_trait::async_trait]
34
35
  impl WorkflowFetcher for WFFutureDriver {
35
- async fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand> {
36
- if let Some(completion) = self.completions_rx.recv().await {
36
+ fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand> {
37
+ if let Ok(completion) = self.completions_q.try_recv() {
37
38
  debug!("Managed wf completion: {}", completion);
38
39
  completion
39
40
  .status
@@ -57,6 +58,8 @@ impl WorkflowFetcher for WFFutureDriver {
57
58
  pub struct ManagedWFFunc {
58
59
  mgr: WorkflowManager,
59
60
  activation_tx: UnboundedSender<WorkflowActivation>,
61
+ completions_rx: UnboundedReceiver<WorkflowActivationCompletion>,
62
+ completions_sync_tx: crossbeam::channel::Sender<WorkflowActivationCompletion>,
60
63
  future_handle: Option<JoinHandle<WorkflowResult<()>>>,
61
64
  was_shutdown: bool,
62
65
  }
@@ -79,7 +82,10 @@ impl ManagedWFFunc {
79
82
  completions_tx,
80
83
  );
81
84
  let spawned = tokio::spawn(wff);
82
- let driver = WFFutureDriver { completions_rx };
85
+ let (completions_sync_tx, completions_sync_rx) = bounded(1);
86
+ let driver = WFFutureDriver {
87
+ completions_q: completions_sync_rx,
88
+ };
83
89
  let state_machines = WorkflowMachines::new(
84
90
  "test_namespace".to_string(),
85
91
  "wfid".to_string(),
@@ -93,6 +99,8 @@ impl ManagedWFFunc {
93
99
  Self {
94
100
  mgr,
95
101
  activation_tx: activations,
102
+ completions_rx,
103
+ completions_sync_tx,
96
104
  future_handle: Some(spawned),
97
105
  was_shutdown: false,
98
106
  }
@@ -100,7 +108,7 @@ impl ManagedWFFunc {
100
108
 
101
109
  #[instrument(skip(self))]
102
110
  pub(crate) async fn get_next_activation(&mut self) -> Result<WorkflowActivation> {
103
- let res = self.mgr.get_next_activation().await?;
111
+ let res = self.mgr.get_next_activation()?;
104
112
  debug!("Managed wf next activation: {}", &res);
105
113
  self.push_activation_to_wf(&res).await?;
106
114
  Ok(res)
@@ -121,7 +129,7 @@ impl ManagedWFFunc {
121
129
  &mut self,
122
130
  update: HistoryUpdate,
123
131
  ) -> Result<WorkflowActivation> {
124
- let res = self.mgr.feed_history_from_server(update).await?;
132
+ let res = self.mgr.feed_history_from_server(update)?;
125
133
  self.push_activation_to_wf(&res).await?;
126
134
  Ok(res)
127
135
  }
@@ -183,7 +191,11 @@ impl ManagedWFFunc {
183
191
  self.activation_tx
184
192
  .send(res.clone())
185
193
  .expect("Workflow should not be dropped if we are still sending activations");
186
- self.mgr.machines.iterate_machines().await?;
194
+ // Move the completion response to the sync workflow bridge
195
+ self.completions_sync_tx
196
+ .send(self.completions_rx.recv().await.unwrap())
197
+ .unwrap();
198
+ self.mgr.machines.iterate_machines()?;
187
199
  Ok(())
188
200
  }
189
201
  }