@temporalio/core-bridge 1.6.0 → 1.7.1

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 (138) hide show
  1. package/Cargo.lock +520 -456
  2. package/lib/index.d.ts +8 -6
  3. package/lib/index.js.map +1 -1
  4. package/package.json +8 -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 +2 -2
  11. package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
  12. package/sdk-core/.buildkite/pipeline.yml +1 -1
  13. package/sdk-core/.github/workflows/heavy.yml +1 -0
  14. package/sdk-core/README.md +13 -7
  15. package/sdk-core/client/src/lib.rs +27 -9
  16. package/sdk-core/client/src/metrics.rs +17 -8
  17. package/sdk-core/client/src/raw.rs +3 -3
  18. package/sdk-core/core/Cargo.toml +3 -4
  19. package/sdk-core/core/src/abstractions/take_cell.rs +28 -0
  20. package/sdk-core/core/src/abstractions.rs +197 -18
  21. package/sdk-core/core/src/core_tests/activity_tasks.rs +137 -45
  22. package/sdk-core/core/src/core_tests/child_workflows.rs +6 -5
  23. package/sdk-core/core/src/core_tests/determinism.rs +212 -2
  24. package/sdk-core/core/src/core_tests/local_activities.rs +183 -36
  25. package/sdk-core/core/src/core_tests/queries.rs +32 -14
  26. package/sdk-core/core/src/core_tests/workers.rs +8 -5
  27. package/sdk-core/core/src/core_tests/workflow_tasks.rs +340 -51
  28. package/sdk-core/core/src/ephemeral_server/mod.rs +110 -8
  29. package/sdk-core/core/src/internal_flags.rs +141 -0
  30. package/sdk-core/core/src/lib.rs +14 -9
  31. package/sdk-core/core/src/replay/mod.rs +16 -27
  32. package/sdk-core/core/src/telemetry/metrics.rs +69 -35
  33. package/sdk-core/core/src/telemetry/mod.rs +38 -14
  34. package/sdk-core/core/src/telemetry/prometheus_server.rs +19 -13
  35. package/sdk-core/core/src/test_help/mod.rs +65 -13
  36. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +119 -160
  37. package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
  38. package/sdk-core/core/src/worker/activities/local_activities.rs +122 -6
  39. package/sdk-core/core/src/worker/activities.rs +347 -173
  40. package/sdk-core/core/src/worker/client/mocks.rs +22 -2
  41. package/sdk-core/core/src/worker/client.rs +18 -2
  42. package/sdk-core/core/src/worker/mod.rs +137 -44
  43. package/sdk-core/core/src/worker/workflow/history_update.rs +132 -51
  44. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +207 -166
  45. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +6 -7
  46. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +6 -7
  47. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +157 -82
  48. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +12 -12
  49. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +6 -7
  50. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +13 -15
  51. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +170 -60
  52. package/sdk-core/core/src/worker/workflow/machines/mod.rs +24 -16
  53. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +6 -8
  54. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +320 -204
  55. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +10 -13
  56. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +15 -23
  57. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +187 -46
  58. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +237 -111
  59. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +13 -13
  60. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +10 -6
  61. package/sdk-core/core/src/worker/workflow/managed_run.rs +81 -62
  62. package/sdk-core/core/src/worker/workflow/mod.rs +341 -79
  63. package/sdk-core/core/src/worker/workflow/run_cache.rs +18 -11
  64. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +15 -3
  65. package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +2 -0
  66. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +75 -52
  67. package/sdk-core/core-api/Cargo.toml +0 -1
  68. package/sdk-core/core-api/src/lib.rs +13 -7
  69. package/sdk-core/core-api/src/telemetry.rs +4 -6
  70. package/sdk-core/core-api/src/worker.rs +5 -0
  71. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +80 -55
  72. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +22 -68
  73. package/sdk-core/histories/ends_empty_wft_complete.bin +0 -0
  74. package/sdk-core/histories/old_change_marker_format.bin +0 -0
  75. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +2 -1
  76. package/sdk-core/protos/api_upstream/Makefile +1 -1
  77. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +5 -17
  78. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +11 -0
  79. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -6
  80. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +6 -6
  81. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +5 -0
  82. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +22 -6
  83. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +48 -19
  84. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -0
  85. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +3 -0
  86. package/sdk-core/protos/api_upstream/temporal/api/{enums/v1/interaction_type.proto → protocol/v1/message.proto} +29 -11
  87. package/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
  88. package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +111 -0
  89. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +59 -28
  90. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
  91. package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +7 -8
  92. package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +10 -7
  93. package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +19 -30
  94. package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
  95. package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
  96. package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +8 -0
  97. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +65 -60
  98. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +85 -84
  99. package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +9 -3
  100. package/sdk-core/sdk/Cargo.toml +1 -1
  101. package/sdk-core/sdk/src/lib.rs +21 -5
  102. package/sdk-core/sdk/src/workflow_context/options.rs +7 -1
  103. package/sdk-core/sdk/src/workflow_context.rs +24 -17
  104. package/sdk-core/sdk/src/workflow_future.rs +9 -3
  105. package/sdk-core/sdk-core-protos/src/history_builder.rs +114 -89
  106. package/sdk-core/sdk-core-protos/src/history_info.rs +6 -1
  107. package/sdk-core/sdk-core-protos/src/lib.rs +205 -64
  108. package/sdk-core/test-utils/src/canned_histories.rs +106 -296
  109. package/sdk-core/test-utils/src/lib.rs +32 -5
  110. package/sdk-core/tests/heavy_tests.rs +10 -43
  111. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
  112. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -3
  113. package/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
  114. package/sdk-core/tests/integ_tests/polling_tests.rs +3 -8
  115. package/sdk-core/tests/integ_tests/queries_tests.rs +4 -2
  116. package/sdk-core/tests/integ_tests/visibility_tests.rs +34 -23
  117. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +97 -81
  118. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
  119. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -0
  120. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +80 -3
  121. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +5 -1
  122. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +1 -0
  123. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +25 -3
  124. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +2 -4
  125. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +30 -0
  126. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +64 -0
  127. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
  128. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +4 -0
  129. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +3 -1
  130. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +7 -2
  131. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -7
  132. package/sdk-core/tests/integ_tests/workflow_tests.rs +8 -8
  133. package/sdk-core/tests/main.rs +16 -25
  134. package/sdk-core/tests/runner.rs +11 -9
  135. package/src/conversions.rs +14 -8
  136. package/src/runtime.rs +9 -8
  137. package/ts/index.ts +8 -6
  138. package/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +0 -87
@@ -3,8 +3,15 @@ use super::{
3
3
  WFMachinesError,
4
4
  };
5
5
  use crate::{
6
+ internal_flags::CoreInternalFlags,
6
7
  protosext::{CompleteLocalActivityData, HistoryEventExt, ValidScheduleLA},
7
- worker::{workflow::OutgoingJob, LocalActivityExecutionResult},
8
+ worker::{
9
+ workflow::{
10
+ machines::{activity_state_machine::activity_fail_info, HistEventData},
11
+ InternalFlagsRef, OutgoingJob,
12
+ },
13
+ LocalActivityExecutionResult,
14
+ },
8
15
  };
9
16
  use rustfsm::{fsm, MachineError, StateMachine, TransitionResult};
10
17
  use std::{
@@ -24,8 +31,8 @@ use temporal_sdk_core_protos::{
24
31
  },
25
32
  temporal::api::{
26
33
  command::v1::{Command, RecordMarkerCommandAttributes},
27
- enums::v1::{CommandType, EventType},
28
- failure::v1::failure::FailureInfo,
34
+ enums::v1::{CommandType, EventType, RetryState},
35
+ failure::v1::{failure::FailureInfo, Failure},
29
36
  history::v1::HistoryEvent,
30
37
  },
31
38
  utilities::TryIntoOrNone,
@@ -113,7 +120,12 @@ impl From<CompleteLocalActivityData> for ResolveDat {
113
120
  result: match d.result {
114
121
  Ok(res) => LocalActivityExecutionResult::Completed(Success { result: Some(res) }),
115
122
  Err(fail) => {
116
- if matches!(fail.failure_info, Some(FailureInfo::CanceledFailureInfo(_))) {
123
+ if matches!(fail.failure_info, Some(FailureInfo::CanceledFailureInfo(_)))
124
+ || matches!(
125
+ fail.cause.as_deref().and_then(|f| f.failure_info.as_ref()),
126
+ Some(FailureInfo::CanceledFailureInfo(_))
127
+ )
128
+ {
117
129
  LocalActivityExecutionResult::Cancelled(Cancellation {
118
130
  failure: Some(fail),
119
131
  })
@@ -141,6 +153,7 @@ pub(super) fn new_local_activity(
141
153
  replaying_when_invoked: bool,
142
154
  maybe_pre_resolved: Option<ResolveDat>,
143
155
  wf_time: Option<SystemTime>,
156
+ internal_flags: InternalFlagsRef,
144
157
  ) -> Result<(LocalActivityMachine, Vec<MachineResponse>), WFMachinesError> {
145
158
  let initial_state = if replaying_when_invoked {
146
159
  if let Some(dat) = maybe_pre_resolved {
@@ -162,14 +175,15 @@ pub(super) fn new_local_activity(
162
175
  .original_schedule_time
163
176
  .get_or_insert(SystemTime::now());
164
177
 
165
- let mut machine = LocalActivityMachine {
166
- state: initial_state,
167
- shared_state: SharedState {
178
+ let mut machine = LocalActivityMachine::from_parts(
179
+ initial_state,
180
+ SharedState {
168
181
  attrs,
169
182
  replaying_when_invoked,
170
183
  wf_time_when_started: wf_time,
184
+ internal_flags,
171
185
  },
172
- };
186
+ );
173
187
 
174
188
  let mut res = OnEventWrapper::on_event_mut(&mut machine, LocalActivityMachineEvents::Schedule)
175
189
  .expect("Scheduling local activities doesn't fail");
@@ -193,13 +207,13 @@ impl LocalActivityMachine {
193
207
  ///
194
208
  /// Attempting the check in any other state likely means a bug in the SDK.
195
209
  pub(super) fn marker_should_get_special_handling(&self) -> Result<bool, WFMachinesError> {
196
- match &self.state {
210
+ match self.state() {
197
211
  LocalActivityMachineState::ResultNotified(_) => Ok(false),
198
212
  LocalActivityMachineState::WaitingMarkerEvent(_) => Ok(true),
199
213
  LocalActivityMachineState::WaitingMarkerEventPreResolved(_) => Ok(true),
200
214
  _ => Err(WFMachinesError::Fatal(format!(
201
215
  "Attempted to check for LA marker handling in invalid state {}",
202
- self.state
216
+ self.state()
203
217
  ))),
204
218
  }
205
219
  }
@@ -207,7 +221,10 @@ impl LocalActivityMachine {
207
221
  /// Returns true if the machine will willingly accept data from a marker in its current state.
208
222
  /// IE: Calling [Self::try_resolve_with_dat] makes sense.
209
223
  pub(super) fn will_accept_resolve_marker(&self) -> bool {
210
- matches!(self.state, LocalActivityMachineState::WaitingMarkerEvent(_))
224
+ matches!(
225
+ self.state(),
226
+ LocalActivityMachineState::WaitingMarkerEvent(_)
227
+ )
211
228
  }
212
229
 
213
230
  /// Must be called if the workflow encounters a non-replay workflow task
@@ -303,6 +320,7 @@ pub(super) struct SharedState {
303
320
  attrs: ValidScheduleLA,
304
321
  replaying_when_invoked: bool,
305
322
  wf_time_when_started: Option<SystemTime>,
323
+ internal_flags: InternalFlagsRef,
306
324
  }
307
325
 
308
326
  impl SharedState {
@@ -344,9 +362,11 @@ pub(super) struct Executing {}
344
362
  impl Executing {
345
363
  pub(super) fn on_schedule(
346
364
  self,
347
- dat: SharedState,
365
+ dat: &mut SharedState,
348
366
  ) -> LocalActivityMachineTransition<RequestSent> {
349
- TransitionResult::commands([LocalActivityCommand::RequestActivityExecution(dat.attrs)])
367
+ TransitionResult::commands([LocalActivityCommand::RequestActivityExecution(
368
+ dat.attrs.clone(),
369
+ )])
350
370
  }
351
371
  }
352
372
 
@@ -456,7 +476,7 @@ impl RequestSent {
456
476
 
457
477
  fn on_no_wait_cancel(
458
478
  self,
459
- shared: SharedState,
479
+ shared: &mut SharedState,
460
480
  cancel_type: ActivityCancellationType,
461
481
  ) -> LocalActivityMachineTransition<MarkerCommandCreated> {
462
482
  let mut cmds = vec![];
@@ -495,7 +515,7 @@ pub(super) struct ResultNotified {
495
515
  impl ResultNotified {
496
516
  pub(super) fn on_marker_recorded(
497
517
  self,
498
- shared: SharedState,
518
+ shared: &mut SharedState,
499
519
  dat: CompleteLocalActivityData,
500
520
  ) -> LocalActivityMachineTransition<MarkerCommandRecorded> {
501
521
  if self.result_type == ResultType::Completed && dat.result.is_err() {
@@ -510,7 +530,7 @@ impl ResultNotified {
510
530
  shared.attrs.seq
511
531
  )));
512
532
  }
513
- verify_marker_dat!(&shared, &dat, TransitionResult::default())
533
+ verify_marker_dat!(shared, &dat, TransitionResult::default())
514
534
  }
515
535
  }
516
536
 
@@ -522,11 +542,11 @@ pub(super) struct WaitingMarkerEvent {
522
542
  impl WaitingMarkerEvent {
523
543
  pub(super) fn on_marker_recorded(
524
544
  self,
525
- shared: SharedState,
545
+ shared: &mut SharedState,
526
546
  dat: CompleteLocalActivityData,
527
547
  ) -> LocalActivityMachineTransition<MarkerCommandRecorded> {
528
548
  verify_marker_dat!(
529
- &shared,
549
+ shared,
530
550
  &dat,
531
551
  TransitionResult::commands(if self.already_resolved {
532
552
  vec![]
@@ -548,17 +568,13 @@ impl WaitingMarkerEvent {
548
568
  }
549
569
  pub(super) fn on_started_non_replay_wft(
550
570
  self,
551
- mut dat: SharedState,
571
+ dat: &mut SharedState,
552
572
  ) -> LocalActivityMachineTransition<RequestSent> {
553
573
  // We aren't really "replaying" anymore for our purposes, and want to record the marker.
554
574
  dat.replaying_when_invoked = false;
555
- TransitionResult::ok_shared(
556
- [LocalActivityCommand::RequestActivityExecution(
557
- dat.attrs.clone(),
558
- )],
559
- RequestSent::default(),
560
- dat,
561
- )
575
+ TransitionResult::commands([LocalActivityCommand::RequestActivityExecution(
576
+ dat.attrs.clone(),
577
+ )])
562
578
  }
563
579
 
564
580
  fn on_cancel_requested(self) -> LocalActivityMachineTransition<WaitingMarkerEvent> {
@@ -582,10 +598,10 @@ pub(super) struct WaitingMarkerEventPreResolved {}
582
598
  impl WaitingMarkerEventPreResolved {
583
599
  pub(super) fn on_marker_recorded(
584
600
  self,
585
- shared: SharedState,
601
+ shared: &mut SharedState,
586
602
  dat: CompleteLocalActivityData,
587
603
  ) -> LocalActivityMachineTransition<MarkerCommandRecorded> {
588
- verify_marker_dat!(&shared, &dat, TransitionResult::default())
604
+ verify_marker_dat!(shared, &dat, TransitionResult::default())
589
605
  }
590
606
  }
591
607
 
@@ -667,8 +683,61 @@ impl WFMachinesAdapter for LocalActivityMachine {
667
683
  ),
668
684
  }
669
685
  } else {
670
- result.into()
686
+ // Cancels and timeouts are to be wrapped with an activity failure
687
+ macro_rules! wrap_fail {
688
+ ($me:ident, $fail:ident, $msg:expr, $info:pat) => {
689
+ let mut fail = $fail.failure.take();
690
+ let fail_info = fail.as_ref().and_then(|f| f.failure_info.as_ref());
691
+ if matches!(fail_info, Some($info)) {
692
+ fail = Some(Failure {
693
+ message: $msg,
694
+ cause: fail.map(Box::new),
695
+ failure_info: Some(activity_fail_info(
696
+ $me.shared_state.attrs.activity_type.clone(),
697
+ $me.shared_state.attrs.activity_id.clone(),
698
+ None,
699
+ RetryState::CancelRequested,
700
+ 0,
701
+ 0,
702
+ )),
703
+ ..Default::default()
704
+ });
705
+ }
706
+ $fail.failure = fail;
707
+ };
708
+ }
709
+ match result {
710
+ LocalActivityExecutionResult::Completed(c) => ActivityResolution {
711
+ status: Some(c.into()),
712
+ },
713
+ LocalActivityExecutionResult::Failed(f) => ActivityResolution {
714
+ status: Some(f.into()),
715
+ },
716
+ LocalActivityExecutionResult::TimedOut(mut failure) => {
717
+ wrap_fail!(
718
+ self,
719
+ failure,
720
+ "Local Activity timed out".to_string(),
721
+ FailureInfo::TimeoutFailureInfo(_)
722
+ );
723
+ ActivityResolution {
724
+ status: Some(failure.into()),
725
+ }
726
+ }
727
+ LocalActivityExecutionResult::Cancelled(mut cancel) => {
728
+ wrap_fail!(
729
+ self,
730
+ cancel,
731
+ "Local Activity cancelled".to_string(),
732
+ FailureInfo::CanceledFailureInfo(_)
733
+ );
734
+ ActivityResolution {
735
+ status: Some(cancel.into()),
736
+ }
737
+ }
738
+ }
671
739
  };
740
+
672
741
  let mut responses = vec![
673
742
  MachineResponse::PushWFJob(OutgoingJob {
674
743
  variant: ResolveActivity {
@@ -749,10 +818,11 @@ impl TryFrom<CommandType> for LocalActivityMachineEvents {
749
818
  }
750
819
  }
751
820
 
752
- impl TryFrom<HistoryEvent> for LocalActivityMachineEvents {
821
+ impl TryFrom<HistEventData> for LocalActivityMachineEvents {
753
822
  type Error = WFMachinesError;
754
823
 
755
- fn try_from(e: HistoryEvent) -> Result<Self, Self::Error> {
824
+ fn try_from(e: HistEventData) -> Result<Self, Self::Error> {
825
+ let e = e.event;
756
826
  if e.event_type() != EventType::MarkerRecorded {
757
827
  return Err(WFMachinesError::Nondeterminism(format!(
758
828
  "Local activity machine cannot handle this event: {e}"
@@ -779,26 +849,30 @@ fn verify_marker_data_matches(
779
849
  dat.marker_dat.seq, shared.attrs.seq
780
850
  )));
781
851
  }
782
-
783
- Ok(())
784
- }
785
-
786
- impl From<LocalActivityExecutionResult> for ActivityResolution {
787
- fn from(lar: LocalActivityExecutionResult) -> Self {
788
- match lar {
789
- LocalActivityExecutionResult::Completed(c) => ActivityResolution {
790
- status: Some(c.into()),
791
- },
792
- LocalActivityExecutionResult::Failed(f) | LocalActivityExecutionResult::TimedOut(f) => {
793
- ActivityResolution {
794
- status: Some(f.into()),
795
- }
796
- }
797
- LocalActivityExecutionResult::Cancelled(cancel) => ActivityResolution {
798
- status: Some(cancel.into()),
799
- },
852
+ // Here we use whether or not we were replaying when we _first invoked_ the LA, because we
853
+ // are always replaying when we see the marker recorded event, and that would make this check
854
+ // a bit pointless.
855
+ if shared.internal_flags.borrow_mut().try_use(
856
+ CoreInternalFlags::IdAndTypeDeterminismChecks,
857
+ !shared.replaying_when_invoked,
858
+ ) {
859
+ if dat.marker_dat.activity_id != shared.attrs.activity_id {
860
+ return Err(WFMachinesError::Nondeterminism(format!(
861
+ "Activity id of recorded marker '{}' does not \
862
+ match activity id of local activity command '{}'",
863
+ dat.marker_dat.activity_id, shared.attrs.activity_id
864
+ )));
865
+ }
866
+ if dat.marker_dat.activity_type != shared.attrs.activity_type {
867
+ return Err(WFMachinesError::Nondeterminism(format!(
868
+ "Activity type of recorded marker '{}' does not \
869
+ match activity type of local activity command '{}'",
870
+ dat.marker_dat.activity_type, shared.attrs.activity_type
871
+ )));
800
872
  }
801
873
  }
874
+
875
+ Ok(())
802
876
  }
803
877
 
804
878
  #[cfg(test)]
@@ -816,15 +890,19 @@ mod tests {
816
890
  coresdk::{
817
891
  activity_result::ActivityExecutionResult,
818
892
  workflow_activation::{workflow_activation_job, WorkflowActivationJob},
819
- workflow_commands::ActivityCancellationType::WaitCancellationCompleted,
820
893
  },
821
894
  temporal::api::{
822
895
  command::v1::command, enums::v1::WorkflowTaskFailedCause, failure::v1::Failure,
823
896
  },
897
+ DEFAULT_ACTIVITY_TYPE,
824
898
  };
825
899
 
826
900
  async fn la_wf(ctx: WfContext) -> WorkflowResult<()> {
827
- ctx.local_activity(LocalActivityOptions::default()).await;
901
+ ctx.local_activity(LocalActivityOptions {
902
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
903
+ ..Default::default()
904
+ })
905
+ .await;
828
906
  Ok(().into())
829
907
  }
830
908
 
@@ -937,8 +1015,16 @@ mod tests {
937
1015
  }
938
1016
 
939
1017
  async fn two_la_wf(ctx: WfContext) -> WorkflowResult<()> {
940
- ctx.local_activity(LocalActivityOptions::default()).await;
941
- ctx.local_activity(LocalActivityOptions::default()).await;
1018
+ ctx.local_activity(LocalActivityOptions {
1019
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1020
+ ..Default::default()
1021
+ })
1022
+ .await;
1023
+ ctx.local_activity(LocalActivityOptions {
1024
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1025
+ ..Default::default()
1026
+ })
1027
+ .await;
942
1028
  Ok(().into())
943
1029
  }
944
1030
 
@@ -1031,8 +1117,14 @@ mod tests {
1031
1117
 
1032
1118
  async fn two_la_wf_parallel(ctx: WfContext) -> WorkflowResult<()> {
1033
1119
  tokio::join!(
1034
- ctx.local_activity(LocalActivityOptions::default()),
1035
- ctx.local_activity(LocalActivityOptions::default())
1120
+ ctx.local_activity(LocalActivityOptions {
1121
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1122
+ ..Default::default()
1123
+ }),
1124
+ ctx.local_activity(LocalActivityOptions {
1125
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1126
+ ..Default::default()
1127
+ })
1036
1128
  );
1037
1129
  Ok(().into())
1038
1130
  }
@@ -1115,9 +1207,17 @@ mod tests {
1115
1207
  }
1116
1208
 
1117
1209
  async fn la_timer_la(ctx: WfContext) -> WorkflowResult<()> {
1118
- ctx.local_activity(LocalActivityOptions::default()).await;
1210
+ ctx.local_activity(LocalActivityOptions {
1211
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1212
+ ..Default::default()
1213
+ })
1214
+ .await;
1119
1215
  ctx.timer(Duration::from_secs(5)).await;
1120
- ctx.local_activity(LocalActivityOptions::default()).await;
1216
+ ctx.local_activity(LocalActivityOptions {
1217
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1218
+ ..Default::default()
1219
+ })
1220
+ .await;
1121
1221
  Ok(().into())
1122
1222
  }
1123
1223
 
@@ -1358,6 +1458,7 @@ mod tests {
1358
1458
  let func = WorkflowFunction::new(move |ctx| async move {
1359
1459
  let la = ctx.local_activity(LocalActivityOptions {
1360
1460
  cancel_type,
1461
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
1361
1462
  ..Default::default()
1362
1463
  });
1363
1464
  ctx.timer(Duration::from_secs(1)).await;
@@ -1367,20 +1468,29 @@ mod tests {
1367
1468
  ctx.timer(Duration::from_secs(1)).await;
1368
1469
  let resolution = la.await;
1369
1470
  assert!(resolution.cancelled());
1471
+ let rfail = resolution.unwrap_failure();
1472
+ assert_matches!(
1473
+ rfail.failure_info,
1474
+ Some(FailureInfo::ActivityFailureInfo(_))
1475
+ );
1476
+ assert_matches!(
1477
+ rfail.cause.unwrap().failure_info,
1478
+ Some(FailureInfo::CanceledFailureInfo(_))
1479
+ );
1370
1480
  Ok(().into())
1371
1481
  });
1372
1482
 
1373
1483
  let mut t = TestHistoryBuilder::default();
1374
1484
  t.add_by_type(EventType::WorkflowExecutionStarted);
1375
1485
  t.add_full_wf_task();
1376
- let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
1486
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
1377
1487
  t.add_timer_fired(timer_started_event_id, "1".to_string());
1378
1488
  t.add_full_wf_task();
1379
1489
  if cancel_type != ActivityCancellationType::WaitCancellationCompleted {
1380
1490
  // With non-wait cancels, the cancel is immediate
1381
1491
  t.add_local_activity_cancel_marker(1, "1");
1382
1492
  }
1383
- let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
1493
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
1384
1494
  if cancel_type == ActivityCancellationType::WaitCancellationCompleted {
1385
1495
  // With wait cancels, the cancel marker is not recorded until activity reports.
1386
1496
  t.add_local_activity_cancel_marker(1, "1");
@@ -1434,7 +1544,7 @@ mod tests {
1434
1544
  // what would have happened if we woke up with new history -- but it does mean we
1435
1545
  // generate the commands at this point. This matters b/c we want to make sure the record
1436
1546
  // marker command is sent as soon as cancel happens.
1437
- if cancel_type == WaitCancellationCompleted {
1547
+ if cancel_type == ActivityCancellationType::WaitCancellationCompleted {
1438
1548
  wfm.complete_local_activity(1, ActivityExecutionResult::cancel_from_details(None))
1439
1549
  .unwrap();
1440
1550
  }
@@ -73,7 +73,7 @@ enum Machines {
73
73
  ///
74
74
  /// Formerly known as `EntityStateMachine` in Java.
75
75
  #[enum_dispatch::enum_dispatch(Machines)]
76
- trait TemporalStateMachine: Send {
76
+ trait TemporalStateMachine {
77
77
  fn handle_command(
78
78
  &mut self,
79
79
  command_type: CommandType,
@@ -88,8 +88,7 @@ trait TemporalStateMachine: Send {
88
88
  /// to update the overall state of the workflow. EX: To issue outgoing WF activations.
89
89
  fn handle_event(
90
90
  &mut self,
91
- event: HistoryEvent,
92
- has_next_event: bool,
91
+ event: HistEventData,
93
92
  ) -> Result<Vec<MachineResponse>, WFMachinesError>;
94
93
 
95
94
  /// Attempt to cancel the command associated with this state machine, if it is cancellable
@@ -108,9 +107,9 @@ trait TemporalStateMachine: Send {
108
107
 
109
108
  impl<SM> TemporalStateMachine for SM
110
109
  where
111
- SM: StateMachine + WFMachinesAdapter + Cancellable + OnEventWrapper + Clone + Send + 'static,
112
- <SM as StateMachine>::Event: TryFrom<HistoryEvent> + TryFrom<CommandType> + Display,
113
- WFMachinesError: From<<<SM as StateMachine>::Event as TryFrom<HistoryEvent>>::Error>,
110
+ SM: StateMachine + WFMachinesAdapter + Cancellable + OnEventWrapper + Clone + 'static,
111
+ <SM as StateMachine>::Event: TryFrom<HistEventData> + TryFrom<CommandType> + Display,
112
+ WFMachinesError: From<<<SM as StateMachine>::Event as TryFrom<HistEventData>>::Error>,
114
113
  <SM as StateMachine>::Command: Debug + Display,
115
114
  <SM as StateMachine>::State: Display,
116
115
  <SM as StateMachine>::Error: Into<WFMachinesError> + 'static + Send + Sync,
@@ -152,21 +151,19 @@ where
152
151
 
153
152
  fn handle_event(
154
153
  &mut self,
155
- event: HistoryEvent,
156
- has_next_event: bool,
154
+ event_dat: HistEventData,
157
155
  ) -> Result<Vec<MachineResponse>, WFMachinesError> {
158
156
  trace!(
159
- event = %event,
157
+ event = %event_dat.event,
160
158
  machine_name = %self.name(),
161
159
  state = %self.state(),
162
160
  "handling event"
163
161
  );
164
162
  let event_info = EventInfo {
165
- event_id: event.event_id,
166
- event_type: event.event_type(),
167
- has_next_event,
163
+ event_id: event_dat.event.event_id,
164
+ event_type: event_dat.event.event_type(),
168
165
  };
169
- let converted_event: <Self as StateMachine>::Event = event.try_into()?;
166
+ let converted_event: <Self as StateMachine>::Event = event_dat.try_into()?;
170
167
 
171
168
  match OnEventWrapper::on_event_mut(self, converted_event) {
172
169
  Ok(c) => process_machine_commands(self, c, Some(event_info)),
@@ -245,11 +242,22 @@ trait WFMachinesAdapter: StateMachine {
245
242
  fn matches_event(&self, event: &HistoryEvent) -> bool;
246
243
  }
247
244
 
245
+ /// Wraps a history event with extra relevant data that a machine might care about while the event
246
+ /// is being applied to it.
247
+ #[derive(Debug, derive_more::Display)]
248
+ #[display(fmt = "{event}")]
249
+ struct HistEventData {
250
+ event: HistoryEvent,
251
+ /// Is the current workflow task under replay or not during application of this event?
252
+ replaying: bool,
253
+ /// Is the current workflow task the last task in history?
254
+ current_task_is_last_in_history: bool,
255
+ }
256
+
248
257
  #[derive(Debug, Copy, Clone)]
249
258
  struct EventInfo {
250
259
  event_id: i64,
251
260
  event_type: EventType,
252
- has_next_event: bool,
253
261
  }
254
262
 
255
263
  trait Cancellable: StateMachine {
@@ -270,7 +278,7 @@ trait Cancellable: StateMachine {
270
278
  }
271
279
  }
272
280
 
273
- /// We need to wrap calls to [StateMachine::on_event_mut] to track coverage, or anything else
281
+ /// We need to wrap calls to [StateMachine::on_event] to track coverage, or anything else
274
282
  /// we'd like to do on every call.
275
283
  pub(crate) trait OnEventWrapper: StateMachine
276
284
  where
@@ -287,7 +295,7 @@ where
287
295
  #[cfg(test)]
288
296
  let converted_event_str = event.to_string();
289
297
 
290
- let res = StateMachine::on_event_mut(self, event);
298
+ let res = StateMachine::on_event(self, event);
291
299
  if res.is_ok() {
292
300
  #[cfg(test)]
293
301
  add_coverage(
@@ -1,9 +1,9 @@
1
1
  use super::{workflow_machines::MachineResponse, NewMachineWithCommand};
2
2
  use crate::worker::workflow::{
3
- machines::{Cancellable, EventInfo, WFMachinesAdapter},
3
+ machines::{Cancellable, EventInfo, HistEventData, WFMachinesAdapter},
4
4
  WFMachinesError,
5
5
  };
6
- use rustfsm::{fsm, TransitionResult};
6
+ use rustfsm::{fsm, StateMachine, TransitionResult};
7
7
  use temporal_sdk_core_protos::{
8
8
  coresdk::workflow_commands::ModifyWorkflowProperties,
9
9
  temporal::api::{
@@ -28,10 +28,7 @@ fsm! {
28
28
  pub(super) fn modify_workflow_properties(
29
29
  lang_cmd: ModifyWorkflowProperties,
30
30
  ) -> NewMachineWithCommand {
31
- let sm = ModifyWorkflowPropertiesMachine {
32
- state: Created {}.into(),
33
- shared_state: (),
34
- };
31
+ let sm = ModifyWorkflowPropertiesMachine::from_parts(Created {}.into(), ());
35
32
  let cmd = Command {
36
33
  command_type: CommandType::ModifyWorkflowProperties as i32,
37
34
  attributes: Some(lang_cmd.into()),
@@ -74,10 +71,11 @@ impl WFMachinesAdapter for ModifyWorkflowPropertiesMachine {
74
71
 
75
72
  impl Cancellable for ModifyWorkflowPropertiesMachine {}
76
73
 
77
- impl TryFrom<HistoryEvent> for ModifyWorkflowPropertiesMachineEvents {
74
+ impl TryFrom<HistEventData> for ModifyWorkflowPropertiesMachineEvents {
78
75
  type Error = WFMachinesError;
79
76
 
80
- fn try_from(e: HistoryEvent) -> Result<Self, Self::Error> {
77
+ fn try_from(e: HistEventData) -> Result<Self, Self::Error> {
78
+ let e = e.event;
81
79
  match e.event_type() {
82
80
  EventType::WorkflowPropertiesModified => {
83
81
  Ok(ModifyWorkflowPropertiesMachineEvents::CommandRecorded)