@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
@@ -184,8 +184,7 @@ impl TryFrom<HistoryEvent> for ActivityMachineEvents {
184
184
  Self::ActivityTaskCompleted(attrs)
185
185
  } else {
186
186
  return Err(WFMachinesError::Fatal(format!(
187
- "Activity completion attributes were unset: {}",
188
- e
187
+ "Activity completion attributes were unset: {e}"
189
188
  )));
190
189
  }
191
190
  }
@@ -196,8 +195,7 @@ impl TryFrom<HistoryEvent> for ActivityMachineEvents {
196
195
  Self::ActivityTaskFailed(attrs)
197
196
  } else {
198
197
  return Err(WFMachinesError::Fatal(format!(
199
- "Activity failure attributes were unset: {}",
200
- e
198
+ "Activity failure attributes were unset: {e}"
201
199
  )));
202
200
  }
203
201
  }
@@ -208,8 +206,7 @@ impl TryFrom<HistoryEvent> for ActivityMachineEvents {
208
206
  Self::ActivityTaskTimedOut(attrs)
209
207
  } else {
210
208
  return Err(WFMachinesError::Fatal(format!(
211
- "Activity timeout attributes were unset: {}",
212
- e
209
+ "Activity timeout attributes were unset: {e}"
213
210
  )));
214
211
  }
215
212
  }
@@ -221,15 +218,13 @@ impl TryFrom<HistoryEvent> for ActivityMachineEvents {
221
218
  Self::ActivityTaskCanceled(attrs)
222
219
  } else {
223
220
  return Err(WFMachinesError::Fatal(format!(
224
- "Activity cancellation attributes were unset: {}",
225
- e
221
+ "Activity cancellation attributes were unset: {e}"
226
222
  )));
227
223
  }
228
224
  }
229
225
  _ => {
230
226
  return Err(WFMachinesError::Nondeterminism(format!(
231
- "Activity machine does not handle this event: {}",
232
- e
227
+ "Activity machine does not handle this event: {e}"
233
228
  )))
234
229
  }
235
230
  })
@@ -339,7 +334,7 @@ impl Cancellable for ActivityMachine {
339
334
  )
340
335
  .into()]
341
336
  }
342
- x => panic!("Invalid cancel event response {:?}", x),
337
+ x => panic!("Invalid cancel event response {x:?}"),
343
338
  })
344
339
  .collect();
345
340
  Ok(res)
@@ -648,8 +643,7 @@ impl Canceled {
648
643
  } else {
649
644
  TransitionResult::Err(WFMachinesError::Nondeterminism(format!(
650
645
  "Non-Abandon cancel mode activities cannot be started after being cancelled. \
651
- Seq: {:?}",
652
- seq_num
646
+ Seq: {seq_num:?}"
653
647
  )))
654
648
  }
655
649
  }
@@ -663,8 +657,7 @@ impl Canceled {
663
657
  TransitionResult::default()
664
658
  } else {
665
659
  TransitionResult::Err(WFMachinesError::Nondeterminism(format!(
666
- "Non-Abandon cancel mode activities cannot be completed after being cancelled: {:?}",
667
- attrs
660
+ "Non-Abandon cancel mode activities cannot be completed after being cancelled: {attrs:?}"
668
661
  )))
669
662
  }
670
663
  }
@@ -769,8 +762,7 @@ fn convert_payloads(
769
762
  ) -> Result<Option<Payload>, WFMachinesError> {
770
763
  result.map(TryInto::try_into).transpose().map_err(|pe| {
771
764
  WFMachinesError::Fatal(format!(
772
- "Not exactly one payload in activity result ({}) for event: {:?}",
773
- pe, event_info
765
+ "Not exactly one payload in activity result ({pe}) for event: {event_info:?}"
774
766
  ))
775
767
  })
776
768
  }
@@ -161,15 +161,13 @@ impl TryFrom<HistoryEvent> for CancelExternalMachineEvents {
161
161
  Self::RequestCancelExternalWorkflowExecutionFailed(attrs.cause())
162
162
  } else {
163
163
  return Err(WFMachinesError::Fatal(format!(
164
- "Cancelworkflow failed attributes were unset: {}",
165
- e
164
+ "Cancelworkflow failed attributes were unset: {e}"
166
165
  )));
167
166
  }
168
167
  }
169
168
  _ => {
170
169
  return Err(WFMachinesError::Nondeterminism(format!(
171
- "Cancel external WF machine does not handle this event: {}",
172
- e
170
+ "Cancel external WF machine does not handle this event: {e}"
173
171
  )))
174
172
  }
175
173
  })
@@ -199,7 +197,7 @@ impl WFMachinesAdapter for CancelExternalMachine {
199
197
  vec![ResolveRequestCancelExternalWorkflow {
200
198
  seq: self.shared_state.seq,
201
199
  failure: Some(Failure {
202
- message: format!("Unable to cancel external workflow because {}", reason),
200
+ message: format!("Unable to cancel external workflow because {reason}"),
203
201
  failure_info: Some(FailureInfo::ApplicationFailureInfo(
204
202
  ApplicationFailureInfo {
205
203
  r#type: f.to_string(),
@@ -80,8 +80,7 @@ impl TryFrom<HistoryEvent> for CancelWorkflowMachineEvents {
80
80
  Some(EventType::WorkflowExecutionCanceled) => Self::WorkflowExecutionCanceled,
81
81
  _ => {
82
82
  return Err(WFMachinesError::Nondeterminism(format!(
83
- "Cancel workflow machine does not handle this event: {}",
84
- e
83
+ "Cancel workflow machine does not handle this event: {e}"
85
84
  )))
86
85
  }
87
86
  })
@@ -471,8 +471,7 @@ impl TryFrom<HistoryEvent> for ChildWorkflowMachineEvents {
471
471
  }
472
472
  _ => {
473
473
  return Err(WFMachinesError::Fatal(format!(
474
- "Child workflow machine does not handle this event: {:?}",
475
- e
474
+ "Child workflow machine does not handle this event: {e:?}"
476
475
  )))
477
476
  }
478
477
  })
@@ -612,7 +611,7 @@ impl Cancellable for ChildWorkflowMachine {
612
611
  | c @ ChildWorkflowCommand::IssueCancelAfterStarted { .. } => {
613
612
  self.adapt_response(c, None)
614
613
  }
615
- x => panic!("Invalid cancel event response {:?}", x),
614
+ x => panic!("Invalid cancel event response {x:?}"),
616
615
  })
617
616
  .collect::<Result<Vec<_>, _>>()?
618
617
  .into_iter()
@@ -650,8 +649,7 @@ fn convert_payloads(
650
649
  ) -> Result<Option<Payload>, WFMachinesError> {
651
650
  result.map(TryInto::try_into).transpose().map_err(|pe| {
652
651
  WFMachinesError::Fatal(format!(
653
- "Not exactly one payload in child workflow result ({}) for event: {:?}",
654
- pe, event_info
652
+ "Not exactly one payload in child workflow result ({pe}) for event: {event_info:?}"
655
653
  ))
656
654
  })
657
655
  }
@@ -69,8 +69,7 @@ impl TryFrom<HistoryEvent> for CompleteWorkflowMachineEvents {
69
69
  EventType::WorkflowExecutionCompleted => Self::WorkflowExecutionCompleted,
70
70
  _ => {
71
71
  return Err(WFMachinesError::Nondeterminism(format!(
72
- "Complete workflow machine does not handle this event: {}",
73
- e
72
+ "Complete workflow machine does not handle this event: {e}"
74
73
  )))
75
74
  }
76
75
  })
@@ -77,8 +77,7 @@ impl TryFrom<HistoryEvent> for ContinueAsNewWorkflowMachineEvents {
77
77
  EventType::WorkflowExecutionContinuedAsNew => Self::WorkflowExecutionContinuedAsNew,
78
78
  _ => {
79
79
  return Err(WFMachinesError::Nondeterminism(format!(
80
- "Continue as new workflow machine does not handle this event: {}",
81
- e
80
+ "Continue as new workflow machine does not handle this event: {e}"
82
81
  )))
83
82
  }
84
83
  })
@@ -93,8 +93,7 @@ impl TryFrom<HistoryEvent> for FailWorkflowMachineEvents {
93
93
  EventType::WorkflowExecutionFailed => Self::WorkflowExecutionFailed,
94
94
  _ => {
95
95
  return Err(WFMachinesError::Nondeterminism(format!(
96
- "Fail workflow machine does not handle this event: {}",
97
- e
96
+ "Fail workflow machine does not handle this event: {e}"
98
97
  )))
99
98
  }
100
99
  })
@@ -59,15 +59,17 @@ fsm! {
59
59
  --> MarkerCommandRecorded;
60
60
 
61
61
  // Replay path ================================================================================
62
- // LAs on the replay path should never have handle result explicitly called on them, but do need
63
- // to eventually see the marker
62
+ // LAs on the replay path always need to eventually see the marker
64
63
  WaitingMarkerEvent --(MarkerRecorded(CompleteLocalActivityData), shared on_marker_recorded)
65
64
  --> MarkerCommandRecorded;
66
65
  // If we are told to cancel while waiting for the marker, we still need to wait for the marker.
67
- WaitingMarkerEvent --(Cancel, on_cancel_requested) --> WaitingMarkerEventCancelled;
66
+ WaitingMarkerEvent --(Cancel, on_cancel_requested) --> WaitingMarkerEvent;
67
+ // Because there could be non-heartbeat WFTs (ex: signals being received) between scheduling
68
+ // the LA and the marker being recorded, peekahead might not always resolve the LA *before*
69
+ // scheduling it. This transition accounts for that.
70
+ WaitingMarkerEvent --(HandleKnownResult(ResolveDat), on_handle_result) --> WaitingMarkerEvent;
68
71
  WaitingMarkerEvent --(NoWaitCancel(ActivityCancellationType),
69
- on_no_wait_cancel) --> WaitingMarkerEventCancelled;
70
- WaitingMarkerEventCancelled --(HandleResult(ResolveDat), on_handle_result) --> WaitingMarkerEvent;
72
+ on_no_wait_cancel) --> WaitingMarkerEvent;
71
73
 
72
74
  // It is entirely possible to have started the LA while replaying, only to find that we have
73
75
  // reached a new WFT and there still was no marker. In such cases we need to execute the LA.
@@ -135,7 +137,7 @@ impl From<CompleteLocalActivityData> for ResolveDat {
135
137
  /// must resolve before we send a record marker command. A [MachineResponse] may be produced,
136
138
  /// to queue the LA for execution if it needs to be.
137
139
  pub(super) fn new_local_activity(
138
- attrs: ValidScheduleLA,
140
+ mut attrs: ValidScheduleLA,
139
141
  replaying_when_invoked: bool,
140
142
  maybe_pre_resolved: Option<ResolveDat>,
141
143
  wf_time: Option<SystemTime>,
@@ -155,6 +157,11 @@ pub(super) fn new_local_activity(
155
157
  Executing {}.into()
156
158
  };
157
159
 
160
+ // If the scheduled LA doesn't already have an "original" schedule time, assign one.
161
+ attrs
162
+ .original_schedule_time
163
+ .get_or_insert(SystemTime::now());
164
+
158
165
  let mut machine = LocalActivityMachine {
159
166
  state: initial_state,
160
167
  shared_state: SharedState {
@@ -197,6 +204,12 @@ impl LocalActivityMachine {
197
204
  }
198
205
  }
199
206
 
207
+ /// Returns true if the machine will willingly accept data from a marker in its current state.
208
+ /// IE: Calling [Self::try_resolve_with_dat] makes sense.
209
+ pub(super) fn will_accept_resolve_marker(&self) -> bool {
210
+ matches!(self.state, LocalActivityMachineState::WaitingMarkerEvent(_))
211
+ }
212
+
200
213
  /// Must be called if the workflow encounters a non-replay workflow task
201
214
  pub(super) fn encountered_non_replay_wft(
202
215
  &mut self,
@@ -235,28 +248,45 @@ impl LocalActivityMachine {
235
248
  backoff: Option<prost_types::Duration>,
236
249
  original_schedule_time: Option<SystemTime>,
237
250
  ) -> Result<Vec<MachineResponse>, WFMachinesError> {
238
- self.try_resolve_with_dat(ResolveDat {
239
- result,
240
- complete_time: self.shared_state.wf_time_when_started.map(|t| t + runtime),
241
- attempt,
242
- backoff,
243
- original_schedule_time,
244
- })
251
+ self._try_resolve(
252
+ ResolveDat {
253
+ result,
254
+ complete_time: self.shared_state.wf_time_when_started.map(|t| t + runtime),
255
+ attempt,
256
+ backoff,
257
+ original_schedule_time,
258
+ },
259
+ false,
260
+ )
245
261
  }
262
+
246
263
  /// Attempt to resolve the local activity with already known data, ex pre-resolved data
247
264
  pub(super) fn try_resolve_with_dat(
248
265
  &mut self,
249
266
  dat: ResolveDat,
250
267
  ) -> Result<Vec<MachineResponse>, WFMachinesError> {
251
- let res = OnEventWrapper::on_event_mut(self, LocalActivityMachineEvents::HandleResult(dat))
252
- .map_err(|e| match e {
253
- MachineError::InvalidTransition => WFMachinesError::Fatal(format!(
254
- "Invalid transition resolving local activity (seq {}) in {}",
255
- self.shared_state.attrs.seq,
256
- self.state(),
257
- )),
258
- MachineError::Underlying(e) => e,
259
- })?;
268
+ self._try_resolve(dat, true)
269
+ }
270
+
271
+ fn _try_resolve(
272
+ &mut self,
273
+ dat: ResolveDat,
274
+ from_marker: bool,
275
+ ) -> Result<Vec<MachineResponse>, WFMachinesError> {
276
+ let evt = if from_marker {
277
+ LocalActivityMachineEvents::HandleKnownResult(dat)
278
+ } else {
279
+ LocalActivityMachineEvents::HandleResult(dat)
280
+ };
281
+ let res = OnEventWrapper::on_event_mut(self, evt).map_err(|e| match e {
282
+ MachineError::InvalidTransition => WFMachinesError::Fatal(format!(
283
+ "Invalid transition resolving local activity (seq {}, from marker: {}) in {}",
284
+ self.shared_state.attrs.seq,
285
+ from_marker,
286
+ self.state(),
287
+ )),
288
+ MachineError::Underlying(e) => e,
289
+ })?;
260
290
 
261
291
  Ok(res
262
292
  .into_iter()
@@ -505,6 +535,17 @@ impl WaitingMarkerEvent {
505
535
  })
506
536
  )
507
537
  }
538
+ fn on_handle_result(
539
+ self,
540
+ dat: ResolveDat,
541
+ ) -> LocalActivityMachineTransition<WaitingMarkerEvent> {
542
+ TransitionResult::ok(
543
+ [LocalActivityCommand::Resolved(dat)],
544
+ WaitingMarkerEvent {
545
+ already_resolved: true,
546
+ },
547
+ )
548
+ }
508
549
  pub(super) fn on_started_non_replay_wft(
509
550
  self,
510
551
  mut dat: SharedState,
@@ -520,41 +561,22 @@ impl WaitingMarkerEvent {
520
561
  )
521
562
  }
522
563
 
523
- fn on_cancel_requested(self) -> LocalActivityMachineTransition<WaitingMarkerEventCancelled> {
564
+ fn on_cancel_requested(self) -> LocalActivityMachineTransition<WaitingMarkerEvent> {
524
565
  // We still "request a cancel" even though we know the local activity should not be running
525
566
  // because the data might be in the pre-resolved list.
526
- TransitionResult::ok(
527
- [LocalActivityCommand::RequestCancel],
528
- WaitingMarkerEventCancelled {},
529
- )
567
+ TransitionResult::ok([LocalActivityCommand::RequestCancel], self)
530
568
  }
531
569
 
532
570
  fn on_no_wait_cancel(
533
571
  self,
534
572
  _: ActivityCancellationType,
535
- ) -> LocalActivityMachineTransition<WaitingMarkerEventCancelled> {
573
+ ) -> LocalActivityMachineTransition<WaitingMarkerEvent> {
536
574
  // Markers are always recorded when cancelling, so this is the same as a normal cancel on
537
575
  // the replay path
538
576
  self.on_cancel_requested()
539
577
  }
540
578
  }
541
579
 
542
- #[derive(Default, Clone)]
543
- pub(super) struct WaitingMarkerEventCancelled {}
544
- impl WaitingMarkerEventCancelled {
545
- fn on_handle_result(
546
- self,
547
- dat: ResolveDat,
548
- ) -> LocalActivityMachineTransition<WaitingMarkerEvent> {
549
- TransitionResult::ok(
550
- [LocalActivityCommand::Resolved(dat)],
551
- WaitingMarkerEvent {
552
- already_resolved: true,
553
- },
554
- )
555
- }
556
- }
557
-
558
580
  #[derive(Default, Clone)]
559
581
  pub(super) struct WaitingMarkerEventPreResolved {}
560
582
  impl WaitingMarkerEventPreResolved {
@@ -733,8 +755,7 @@ impl TryFrom<HistoryEvent> for LocalActivityMachineEvents {
733
755
  fn try_from(e: HistoryEvent) -> Result<Self, Self::Error> {
734
756
  if e.event_type() != EventType::MarkerRecorded {
735
757
  return Err(WFMachinesError::Nondeterminism(format!(
736
- "Local activity machine cannot handle this event: {}",
737
- e
758
+ "Local activity machine cannot handle this event: {e}"
738
759
  )));
739
760
  }
740
761
 
@@ -1403,8 +1424,9 @@ mod tests {
1403
1424
  assert_eq!(commands[1].command_type, CommandType::StartTimer as i32);
1404
1425
  }
1405
1426
 
1406
- if replay {
1407
- wfm.get_next_activation().await.unwrap()
1427
+ let commands = if replay {
1428
+ wfm.get_next_activation().await.unwrap();
1429
+ wfm.get_server_commands().commands
1408
1430
  } else {
1409
1431
  // On non replay, there's an additional activation, because completing with the cancel
1410
1432
  // wants to wake up the workflow to see if resolving the LA as cancelled did anything.
@@ -1429,11 +1451,11 @@ mod tests {
1429
1451
 
1430
1452
  wfm.new_history(t.get_history_info(3).unwrap().into())
1431
1453
  .await
1432
- .unwrap()
1454
+ .unwrap();
1455
+ wfm.get_next_activation().await.unwrap();
1456
+ wfm.get_server_commands().commands
1433
1457
  };
1434
1458
 
1435
- wfm.get_next_activation().await.unwrap();
1436
- let commands = wfm.get_server_commands().commands;
1437
1459
  assert_eq!(commands.len(), 1);
1438
1460
  assert_eq!(
1439
1461
  commands[0].command_type,
@@ -18,9 +18,9 @@ mod workflow_task_state_machine;
18
18
  #[cfg(test)]
19
19
  mod transition_coverage;
20
20
 
21
- pub(crate) use workflow_machines::{WFMachinesError, WorkflowMachines};
21
+ pub(crate) use workflow_machines::WorkflowMachines;
22
22
 
23
- use crate::telemetry::VecDisplayer;
23
+ use crate::{telemetry::VecDisplayer, worker::workflow::WFMachinesError};
24
24
  use activity_state_machine::ActivityMachine;
25
25
  use cancel_external_state_machine::CancelExternalMachine;
26
26
  use cancel_workflow_state_machine::CancelWorkflowMachine;
@@ -217,7 +217,7 @@ where
217
217
  <SM as StateMachine>::State: Display,
218
218
  {
219
219
  if !commands.is_empty() {
220
- debug!(commands=%commands.display(), state=%machine.state(),
220
+ trace!(commands=%commands.display(), state=%machine.state(),
221
221
  machine_name=%TemporalStateMachine::name(machine), "Machine produced commands");
222
222
  }
223
223
  let mut machine_responses = vec![];
@@ -1,8 +1,8 @@
1
- use super::{
2
- workflow_machines::{MachineResponse, WFMachinesError},
3
- NewMachineWithCommand,
1
+ use super::{workflow_machines::MachineResponse, NewMachineWithCommand};
2
+ use crate::worker::workflow::{
3
+ machines::{Cancellable, EventInfo, WFMachinesAdapter},
4
+ WFMachinesError,
4
5
  };
5
- use crate::worker::workflow::machines::{Cancellable, EventInfo, WFMachinesAdapter};
6
6
  use rustfsm::{fsm, TransitionResult};
7
7
  use temporal_sdk_core_protos::{
8
8
  coresdk::workflow_commands::ModifyWorkflowProperties,
@@ -208,8 +208,7 @@ impl TryFrom<HistoryEvent> for PatchMachineEvents {
208
208
  match e.get_patch_marker_details() {
209
209
  Some((id, _)) => Ok(Self::MarkerRecorded(id)),
210
210
  _ => Err(WFMachinesError::Nondeterminism(format!(
211
- "Change machine cannot handle this event: {}",
212
- e
211
+ "Change machine cannot handle this event: {e}"
213
212
  ))),
214
213
  }
215
214
  }
@@ -202,15 +202,13 @@ impl TryFrom<HistoryEvent> for SignalExternalMachineEvents {
202
202
  Self::SignalExternalWorkflowExecutionFailed(attrs.cause())
203
203
  } else {
204
204
  return Err(WFMachinesError::Fatal(format!(
205
- "Signal workflow failed attributes were unset: {}",
206
- e
205
+ "Signal workflow failed attributes were unset: {e}"
207
206
  )));
208
207
  }
209
208
  }
210
209
  _ => {
211
210
  return Err(WFMachinesError::Nondeterminism(format!(
212
- "Signal external WF machine does not handle this event: {}",
213
- e
211
+ "Signal external WF machine does not handle this event: {e}"
214
212
  )))
215
213
  }
216
214
  })
@@ -242,7 +240,7 @@ impl WFMachinesAdapter for SignalExternalMachine {
242
240
  seq: self.shared_state.seq,
243
241
  // TODO: Create new failure type upstream for this
244
242
  failure: Some(Failure {
245
- message: format!("Unable to signal external workflow because {}", reason),
243
+ message: format!("Unable to signal external workflow because {reason}"),
246
244
  failure_info: Some(FailureInfo::ApplicationFailureInfo(
247
245
  ApplicationFailureInfo {
248
246
  r#type: f.to_string(),
@@ -1,9 +1,10 @@
1
1
  #![allow(clippy::large_enum_variant)]
2
2
 
3
3
  use super::{
4
- workflow_machines::{MachineResponse, WFMachinesError},
5
- Cancellable, EventInfo, NewMachineWithCommand, OnEventWrapper, WFMachinesAdapter,
4
+ workflow_machines::MachineResponse, Cancellable, EventInfo, NewMachineWithCommand,
5
+ OnEventWrapper, WFMachinesAdapter,
6
6
  };
7
+ use crate::worker::workflow::WFMachinesError;
7
8
  use rustfsm::{fsm, MachineError, StateMachine, TransitionResult};
8
9
  use std::convert::TryFrom;
9
10
  use temporal_sdk_core_protos::{
@@ -107,15 +108,13 @@ impl TryFrom<HistoryEvent> for TimerMachineEvents {
107
108
  Self::TimerFired(attrs)
108
109
  } else {
109
110
  return Err(WFMachinesError::Fatal(format!(
110
- "Timer fired attribs were unset: {}",
111
- e
111
+ "Timer fired attribs were unset: {e}"
112
112
  )));
113
113
  }
114
114
  }
115
115
  _ => {
116
116
  return Err(WFMachinesError::Nondeterminism(format!(
117
- "Timer machine does not handle this event: {}",
118
- e
117
+ "Timer machine does not handle this event: {e}"
119
118
  )))
120
119
  }
121
120
  })
@@ -256,7 +255,7 @@ impl Cancellable for TimerMachine {
256
255
  vec![MachineResponse::IssueNewCommand(cmd)]
257
256
  }
258
257
  None => vec![],
259
- x => panic!("Invalid cancel event response {:?}", x),
258
+ x => panic!("Invalid cancel event response {x:?}"),
260
259
  },
261
260
  )
262
261
  }
@@ -144,7 +144,7 @@ mod machine_coverage_report {
144
144
  m @ "ModifyWorkflowPropertiesMachine" => {
145
145
  cover_transitions(m, &mut modify_wf_props, coverage)
146
146
  }
147
- m => panic!("Unknown machine {}", m),
147
+ m => panic!("Unknown machine {m}"),
148
148
  }
149
149
  }
150
150
  }
@@ -168,7 +168,7 @@ mod machine_coverage_report {
168
168
  let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
169
169
  d.push("machine_coverage");
170
170
  std::fs::create_dir_all(&d).unwrap();
171
- d.push(format!("{}_Coverage.puml", machine));
171
+ d.push(format!("{machine}_Coverage.puml"));
172
172
  let mut file = File::create(d).unwrap();
173
173
  file.write_all(viz.as_bytes()).unwrap();
174
174
  }
@@ -1,8 +1,8 @@
1
- use super::{
2
- workflow_machines::{MachineResponse, WFMachinesError},
3
- NewMachineWithCommand,
1
+ use super::{workflow_machines::MachineResponse, NewMachineWithCommand};
2
+ use crate::worker::workflow::{
3
+ machines::{Cancellable, EventInfo, WFMachinesAdapter},
4
+ WFMachinesError,
4
5
  };
5
- use crate::worker::workflow::machines::{Cancellable, EventInfo, WFMachinesAdapter};
6
6
  use rustfsm::{fsm, TransitionResult};
7
7
  use temporal_sdk_core_protos::{
8
8
  coresdk::workflow_commands::UpsertWorkflowSearchAttributes,
@@ -1,15 +1,13 @@
1
- use super::super::{local_activity_state_machine::ResolveDat, WFMachinesError};
1
+ use super::super::local_activity_state_machine::ResolveDat;
2
2
  use crate::{
3
- protosext::{HistoryEventExt, ValidScheduleLA},
3
+ protosext::{CompleteLocalActivityData, ValidScheduleLA},
4
4
  worker::{ExecutingLAId, LocalActRequest, NewLocalAct},
5
5
  };
6
6
  use std::{
7
7
  collections::{HashMap, HashSet},
8
8
  time::SystemTime,
9
9
  };
10
- use temporal_sdk_core_protos::temporal::api::{
11
- common::v1::WorkflowExecution, history::v1::HistoryEvent,
12
- };
10
+ use temporal_sdk_core_protos::temporal::api::common::v1::WorkflowExecution;
13
11
 
14
12
  #[derive(Default)]
15
13
  pub(super) struct LocalActivityData {
@@ -53,7 +51,7 @@ impl LocalActivityData {
53
51
  .chain(self.new_requests.drain(..).map(|sa| {
54
52
  self.executing.insert(sa.seq);
55
53
  LocalActRequest::New(NewLocalAct {
56
- schedule_time: sa.original_schedule_time.unwrap_or_else(SystemTime::now),
54
+ schedule_time: SystemTime::now(),
57
55
  schedule_cmd: sa,
58
56
  workflow_type: wf_type.to_string(),
59
57
  workflow_exec_info: WorkflowExecution {
@@ -70,17 +68,8 @@ impl LocalActivityData {
70
68
  self.executing.len() + self.new_requests.len()
71
69
  }
72
70
 
73
- pub(super) fn process_peekahead_marker(&mut self, e: &HistoryEvent) -> super::Result<()> {
74
- if let Some(la_dat) = e.clone().into_local_activity_marker_details() {
75
- self.preresolutions
76
- .insert(la_dat.marker_dat.seq, la_dat.into());
77
- } else {
78
- return Err(WFMachinesError::Fatal(format!(
79
- "Local activity marker was unparsable: {:?}",
80
- e
81
- )));
82
- }
83
- Ok(())
71
+ pub(super) fn insert_peeked_marker(&mut self, dat: CompleteLocalActivityData) {
72
+ self.preresolutions.insert(dat.marker_dat.seq, dat.into());
84
73
  }
85
74
 
86
75
  pub(super) fn take_preresolution(&mut self, seq: u32) -> Option<ResolveDat> {