@temporalio/core-bridge 1.4.4 → 1.5.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 (123) hide show
  1. package/Cargo.lock +327 -419
  2. package/Cargo.toml +1 -1
  3. package/index.js +25 -2
  4. package/lib/errors.d.ts +22 -0
  5. package/lib/errors.js +65 -0
  6. package/lib/errors.js.map +1 -0
  7. package/lib/index.d.ts +440 -0
  8. package/lib/index.js +8 -0
  9. package/lib/index.js.map +1 -0
  10. package/package.json +11 -5
  11. package/releases/aarch64-apple-darwin/index.node +0 -0
  12. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  13. package/releases/x86_64-apple-darwin/index.node +0 -0
  14. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  15. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  16. package/sdk-core/.buildkite/docker/Dockerfile +1 -1
  17. package/sdk-core/.buildkite/docker/docker-compose.yaml +2 -2
  18. package/sdk-core/bridge-ffi/Cargo.toml +1 -1
  19. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -25
  20. package/sdk-core/bridge-ffi/src/lib.rs +29 -108
  21. package/sdk-core/bridge-ffi/src/wrappers.rs +35 -25
  22. package/sdk-core/client/Cargo.toml +1 -1
  23. package/sdk-core/client/src/lib.rs +12 -20
  24. package/sdk-core/client/src/raw.rs +9 -8
  25. package/sdk-core/client/src/retry.rs +100 -23
  26. package/sdk-core/core/Cargo.toml +5 -5
  27. package/sdk-core/core/benches/workflow_replay.rs +13 -10
  28. package/sdk-core/core/src/abstractions.rs +22 -22
  29. package/sdk-core/core/src/core_tests/activity_tasks.rs +1 -1
  30. package/sdk-core/core/src/core_tests/local_activities.rs +228 -6
  31. package/sdk-core/core/src/core_tests/queries.rs +247 -89
  32. package/sdk-core/core/src/core_tests/workers.rs +2 -2
  33. package/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
  34. package/sdk-core/core/src/core_tests/workflow_tasks.rs +46 -27
  35. package/sdk-core/core/src/lib.rs +139 -32
  36. package/sdk-core/core/src/replay/mod.rs +185 -41
  37. package/sdk-core/core/src/telemetry/log_export.rs +190 -0
  38. package/sdk-core/core/src/telemetry/metrics.rs +184 -139
  39. package/sdk-core/core/src/telemetry/mod.rs +296 -318
  40. package/sdk-core/core/src/telemetry/prometheus_server.rs +4 -3
  41. package/sdk-core/core/src/test_help/mod.rs +9 -7
  42. package/sdk-core/core/src/worker/activities/local_activities.rs +2 -1
  43. package/sdk-core/core/src/worker/activities.rs +40 -23
  44. package/sdk-core/core/src/worker/client/mocks.rs +1 -1
  45. package/sdk-core/core/src/worker/client.rs +30 -4
  46. package/sdk-core/core/src/worker/mod.rs +22 -18
  47. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +10 -19
  48. package/sdk-core/core/src/worker/workflow/history_update.rs +99 -25
  49. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -5
  50. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -5
  51. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -5
  52. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -5
  53. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -5
  54. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +2 -6
  55. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -5
  56. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +18 -21
  57. package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -38
  58. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +178 -0
  59. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -5
  60. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -5
  61. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -5
  62. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +8 -2
  63. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +1 -5
  64. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +232 -216
  65. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +1 -6
  66. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +4 -4
  67. package/sdk-core/core/src/worker/workflow/managed_run.rs +13 -5
  68. package/sdk-core/core/src/worker/workflow/mod.rs +61 -9
  69. package/sdk-core/core/src/worker/workflow/wft_poller.rs +2 -2
  70. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +56 -11
  71. package/sdk-core/core-api/Cargo.toml +4 -3
  72. package/sdk-core/core-api/src/lib.rs +1 -43
  73. package/sdk-core/core-api/src/telemetry.rs +147 -0
  74. package/sdk-core/core-api/src/worker.rs +13 -0
  75. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  76. package/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  77. package/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  78. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +1 -1
  79. package/sdk-core/protos/api_upstream/buf.yaml +0 -3
  80. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +3 -7
  81. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +8 -0
  82. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -2
  83. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +2 -0
  84. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +3 -0
  85. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +13 -0
  86. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +19 -59
  87. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -19
  88. package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +108 -29
  89. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
  90. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +1 -0
  91. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +47 -8
  92. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +15 -1
  93. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  94. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +8 -1
  95. package/sdk-core/sdk/src/interceptors.rs +36 -3
  96. package/sdk-core/sdk/src/lib.rs +7 -4
  97. package/sdk-core/sdk/src/workflow_context.rs +13 -2
  98. package/sdk-core/sdk-core-protos/src/history_builder.rs +47 -1
  99. package/sdk-core/sdk-core-protos/src/history_info.rs +22 -22
  100. package/sdk-core/sdk-core-protos/src/lib.rs +49 -27
  101. package/sdk-core/test-utils/Cargo.toml +1 -0
  102. package/sdk-core/test-utils/src/lib.rs +81 -29
  103. package/sdk-core/tests/integ_tests/metrics_tests.rs +37 -0
  104. package/sdk-core/tests/integ_tests/polling_tests.rs +0 -13
  105. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +145 -4
  106. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +53 -0
  107. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +106 -20
  108. package/sdk-core/tests/integ_tests/workflow_tests.rs +18 -8
  109. package/sdk-core/tests/main.rs +6 -4
  110. package/src/conversions.rs +52 -47
  111. package/src/errors.rs +28 -86
  112. package/src/helpers.rs +3 -4
  113. package/src/lib.rs +2 -2
  114. package/src/runtime.rs +132 -61
  115. package/src/testing.rs +7 -4
  116. package/src/worker.rs +67 -50
  117. package/ts/errors.ts +55 -0
  118. package/{index.d.ts → ts/index.ts} +121 -15
  119. package/sdk-core/core/src/log_export.rs +0 -62
  120. package/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
  121. package/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
  122. package/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
  123. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/cluster.proto +0 -40
@@ -204,20 +204,20 @@ impl HistoryUpdate {
204
204
  &mut self,
205
205
  from_wft_started_id: i64,
206
206
  ) -> Result<Vec<HistoryEvent>, tonic::Status> {
207
- let (next_wft_events, maybe_bonus_event) = self
207
+ let (next_wft_events, maybe_bonus_events) = self
208
208
  .take_next_wft_sequence_impl(from_wft_started_id)
209
209
  .await?;
210
- if let Some(be) = maybe_bonus_event {
211
- self.buffered.push_back(be);
210
+ if !maybe_bonus_events.is_empty() {
211
+ self.buffered.extend(maybe_bonus_events);
212
212
  }
213
213
 
214
214
  if let Some(last_event_id) = next_wft_events.last().map(|he| he.event_id) {
215
215
  // Always attempt to fetch the *next* WFT sequence as well, to buffer it for lookahead
216
- let (buffer_these_events, maybe_bonus_event) =
216
+ let (buffer_these_events, maybe_bonus_events) =
217
217
  self.take_next_wft_sequence_impl(last_event_id).await?;
218
218
  self.buffered.extend(buffer_these_events);
219
- if let Some(be) = maybe_bonus_event {
220
- self.buffered.push_back(be);
219
+ if !maybe_bonus_events.is_empty() {
220
+ self.buffered.extend(maybe_bonus_events);
221
221
  }
222
222
  }
223
223
 
@@ -232,44 +232,61 @@ impl HistoryUpdate {
232
232
  self.buffered.iter()
233
233
  }
234
234
 
235
+ /// Retrieve the next WFT sequence, first from buffered events and then from the real stream.
236
+ /// Returns (events up to the next logical wft sequence, extra events that were taken but
237
+ /// should be re-appended to the end of the buffer).
235
238
  async fn take_next_wft_sequence_impl(
236
239
  &mut self,
237
240
  from_event_id: i64,
238
- ) -> Result<(Vec<HistoryEvent>, Option<HistoryEvent>), tonic::Status> {
241
+ ) -> Result<(Vec<HistoryEvent>, Vec<HistoryEvent>), tonic::Status> {
239
242
  let mut events_to_next_wft_started: Vec<HistoryEvent> = vec![];
240
243
 
241
244
  // This flag tracks if, while determining events to be returned, we have seen the next
242
245
  // logically significant WFT started event which follows the one that was passed in as a
243
- // parameter. If a WFT fails or times out, it is not significant. So we will stop returning
244
- // events (exclusive) as soon as we see an event following a WFT started that is *not*
245
- // failed or timed out.
246
- let mut saw_next_wft = false;
246
+ // parameter. If a WFT fails, times out, or is devoid of commands (ie: a heartbeat) it is
247
+ // not significant. So we will stop returning events (exclusive) as soon as we see an event
248
+ // following a WFT started that is *not* failed, timed out, or completed with a command.
249
+ let mut next_wft_state = NextWftState::NotSeen;
247
250
  let mut should_pop = |e: &HistoryEvent| {
248
251
  if e.event_id <= from_event_id {
249
252
  return true;
250
- } else if e.event_type == EventType::WorkflowTaskStarted as i32 {
251
- saw_next_wft = true;
253
+ } else if e.event_type() == EventType::WorkflowTaskStarted {
254
+ next_wft_state = NextWftState::Seen;
252
255
  return true;
253
256
  }
254
257
 
255
- if saw_next_wft {
256
- // Must ignore failures and timeouts
257
- if e.event_type == EventType::WorkflowTaskFailed as i32
258
- || e.event_type == EventType::WorkflowTaskTimedOut as i32
259
- {
260
- saw_next_wft = false;
261
- return true;
258
+ match next_wft_state {
259
+ NextWftState::Seen => {
260
+ // Must ignore failures and timeouts
261
+ if e.event_type() == EventType::WorkflowTaskFailed
262
+ || e.event_type() == EventType::WorkflowTaskTimedOut
263
+ {
264
+ next_wft_state = NextWftState::NotSeen;
265
+ return true;
266
+ } else if e.event_type() == EventType::WorkflowTaskCompleted {
267
+ next_wft_state = NextWftState::SeenCompleted;
268
+ return true;
269
+ }
270
+ false
271
+ }
272
+ NextWftState::SeenCompleted => {
273
+ // If we've seen the WFT be completed, and this event is another scheduled, then
274
+ // this was an empty heartbeat we should ignore.
275
+ if e.event_type() == EventType::WorkflowTaskScheduled {
276
+ next_wft_state = NextWftState::NotSeen;
277
+ return true;
278
+ }
279
+ // Otherwise, we're done here
280
+ false
262
281
  }
263
- return false;
282
+ NextWftState::NotSeen => true,
264
283
  }
265
-
266
- true
267
284
  };
268
285
 
269
286
  // Fetch events from the buffer first, then from the network
270
287
  let mut event_q = stream::iter(self.buffered.drain(..).map(Ok)).chain(&mut self.events);
271
288
 
272
- let mut extra_e = None;
289
+ let mut extra_e = vec![];
273
290
  let mut last_seen_id = None;
274
291
  while let Some(e) = event_q.next().await {
275
292
  let e = e?;
@@ -288,7 +305,17 @@ impl HistoryUpdate {
288
305
  // command on completion), where we may need to skip events we already handled.
289
306
  if e.event_id > from_event_id {
290
307
  if !should_pop(&e) {
291
- extra_e = Some(e);
308
+ if next_wft_state == NextWftState::SeenCompleted {
309
+ // We have seen the wft completed event, but decided to exit. We don't
310
+ // want to return that event as part of this sequence, so include it for
311
+ // re-buffering along with the event we're currently on.
312
+ extra_e.push(
313
+ events_to_next_wft_started
314
+ .pop()
315
+ .expect("There is an element here by definition"),
316
+ );
317
+ }
318
+ extra_e.push(e);
292
319
  break;
293
320
  }
294
321
  events_to_next_wft_started.push(e);
@@ -299,6 +326,13 @@ impl HistoryUpdate {
299
326
  }
300
327
  }
301
328
 
329
+ #[derive(Eq, PartialEq, Debug)]
330
+ enum NextWftState {
331
+ NotSeen,
332
+ Seen,
333
+ SeenCompleted,
334
+ }
335
+
302
336
  impl From<HistoryInfo> for HistoryUpdate {
303
337
  fn from(v: HistoryInfo) -> Self {
304
338
  Self::new_from_events(v.events().to_vec(), v.previous_started_event_id())
@@ -366,6 +400,46 @@ pub mod tests {
366
400
  assert_eq!(seq_2.last().unwrap().event_id, 8);
367
401
  }
368
402
 
403
+ #[tokio::test]
404
+ async fn history_ends_abruptly() {
405
+ let mut timer_hist = canned_histories::single_timer("t");
406
+ timer_hist.add_workflow_execution_terminated();
407
+ let mut update = timer_hist.as_history_update();
408
+ let seq_2 = update.take_next_wft_sequence(3).await.unwrap();
409
+ assert_eq!(seq_2.len(), 5);
410
+ assert_eq!(seq_2.last().unwrap().event_id, 8);
411
+ }
412
+
413
+ #[tokio::test]
414
+ async fn heartbeats_skipped() {
415
+ let mut t = TestHistoryBuilder::default();
416
+ t.add_by_type(EventType::WorkflowExecutionStarted);
417
+ t.add_full_wf_task();
418
+ t.add_full_wf_task();
419
+ t.add_get_event_id(EventType::TimerStarted, None);
420
+ t.add_full_wf_task();
421
+ t.add_full_wf_task();
422
+ t.add_full_wf_task();
423
+ t.add_full_wf_task();
424
+ t.add_get_event_id(EventType::TimerStarted, None);
425
+ t.add_full_wf_task();
426
+ t.add_we_signaled("whee", vec![]);
427
+ t.add_full_wf_task();
428
+ t.add_workflow_execution_completed();
429
+
430
+ let mut update = t.as_history_update();
431
+ let seq = update.take_next_wft_sequence(0).await.unwrap();
432
+ assert_eq!(seq.len(), 6);
433
+ let seq = update.take_next_wft_sequence(6).await.unwrap();
434
+ assert_eq!(seq.len(), 13);
435
+ let seq = update.take_next_wft_sequence(19).await.unwrap();
436
+ assert_eq!(seq.len(), 4);
437
+ let seq = update.take_next_wft_sequence(23).await.unwrap();
438
+ assert_eq!(seq.len(), 4);
439
+ let seq = update.take_next_wft_sequence(27).await.unwrap();
440
+ assert_eq!(seq.len(), 2);
441
+ }
442
+
369
443
  #[tokio::test]
370
444
  async fn paginator_fetches_new_pages() {
371
445
  // Note that this test triggers the "event ids that went backwards" error, acceptably.
@@ -1,7 +1,7 @@
1
1
  #![allow(clippy::large_enum_variant)]
2
2
 
3
3
  use super::{
4
- workflow_machines::MachineResponse, Cancellable, EventInfo, MachineKind, NewMachineWithCommand,
4
+ workflow_machines::MachineResponse, Cancellable, EventInfo, NewMachineWithCommand,
5
5
  OnEventWrapper, WFMachinesAdapter, WFMachinesError,
6
6
  };
7
7
  use rustfsm::{fsm, MachineError, StateMachine, TransitionResult};
@@ -288,10 +288,6 @@ impl WFMachinesAdapter for ActivityMachine {
288
288
  | EventType::ActivityTaskCanceled
289
289
  )
290
290
  }
291
-
292
- fn kind(&self) -> MachineKind {
293
- MachineKind::Activity
294
- }
295
291
  }
296
292
 
297
293
  impl TryFrom<CommandType> for ActivityMachineEvents {
@@ -1,5 +1,5 @@
1
1
  use super::{
2
- workflow_machines::MachineResponse, Cancellable, EventInfo, MachineKind, NewMachineWithCommand,
2
+ workflow_machines::MachineResponse, Cancellable, EventInfo, NewMachineWithCommand,
3
3
  OnEventWrapper, WFMachinesAdapter, WFMachinesError,
4
4
  };
5
5
  use rustfsm::{fsm, TransitionResult};
@@ -222,10 +222,6 @@ impl WFMachinesAdapter for CancelExternalMachine {
222
222
  | EventType::RequestCancelExternalWorkflowExecutionInitiated
223
223
  )
224
224
  }
225
-
226
- fn kind(&self) -> MachineKind {
227
- MachineKind::CancelExternalWorkflow
228
- }
229
225
  }
230
226
 
231
227
  impl Cancellable for CancelExternalMachine {}
@@ -1,5 +1,5 @@
1
1
  use super::{
2
- workflow_machines::MachineResponse, Cancellable, EventInfo, HistoryEvent, MachineKind,
2
+ workflow_machines::MachineResponse, Cancellable, EventInfo, HistoryEvent,
3
3
  NewMachineWithCommand, OnEventWrapper, WFMachinesAdapter, WFMachinesError,
4
4
  };
5
5
  use rustfsm::{fsm, TransitionResult};
@@ -111,10 +111,6 @@ impl WFMachinesAdapter for CancelWorkflowMachine {
111
111
  fn matches_event(&self, event: &HistoryEvent) -> bool {
112
112
  event.event_type() == EventType::WorkflowExecutionCanceled
113
113
  }
114
-
115
- fn kind(&self) -> MachineKind {
116
- MachineKind::CancelWorkflow
117
- }
118
114
  }
119
115
 
120
116
  impl Cancellable for CancelWorkflowMachine {}
@@ -1,5 +1,5 @@
1
1
  use super::{
2
- workflow_machines::MachineResponse, Cancellable, EventInfo, MachineKind, NewMachineWithCommand,
2
+ workflow_machines::MachineResponse, Cancellable, EventInfo, NewMachineWithCommand,
3
3
  OnEventWrapper, WFMachinesAdapter, WFMachinesError,
4
4
  };
5
5
  use rustfsm::{fsm, MachineError, TransitionResult};
@@ -585,10 +585,6 @@ impl WFMachinesAdapter for ChildWorkflowMachine {
585
585
  | EventType::ChildWorkflowExecutionCanceled
586
586
  )
587
587
  }
588
-
589
- fn kind(&self) -> MachineKind {
590
- MachineKind::ChildWorkflow
591
- }
592
588
  }
593
589
 
594
590
  impl TryFrom<CommandType> for ChildWorkflowMachineEvents {
@@ -1,5 +1,5 @@
1
1
  use super::{
2
- workflow_machines::MachineResponse, Cancellable, EventInfo, MachineKind, NewMachineWithCommand,
2
+ workflow_machines::MachineResponse, Cancellable, EventInfo, NewMachineWithCommand,
3
3
  OnEventWrapper, WFMachinesAdapter, WFMachinesError,
4
4
  };
5
5
  use rustfsm::{fsm, TransitionResult};
@@ -131,10 +131,6 @@ impl WFMachinesAdapter for CompleteWorkflowMachine {
131
131
  fn matches_event(&self, event: &HistoryEvent) -> bool {
132
132
  event.event_type() == EventType::WorkflowExecutionCompleted
133
133
  }
134
-
135
- fn kind(&self) -> MachineKind {
136
- MachineKind::CompleteWorkflow
137
- }
138
134
  }
139
135
 
140
136
  impl Cancellable for CompleteWorkflowMachine {}
@@ -1,6 +1,6 @@
1
1
  use super::{
2
- Cancellable, EventInfo, HistoryEvent, MachineKind, MachineResponse, NewMachineWithCommand,
3
- OnEventWrapper, WFMachinesAdapter, WFMachinesError,
2
+ Cancellable, EventInfo, HistoryEvent, MachineResponse, NewMachineWithCommand, OnEventWrapper,
3
+ WFMachinesAdapter, WFMachinesError,
4
4
  };
5
5
  use rustfsm::{fsm, TransitionResult};
6
6
  use std::convert::TryFrom;
@@ -110,10 +110,6 @@ impl WFMachinesAdapter for ContinueAsNewWorkflowMachine {
110
110
  fn matches_event(&self, event: &HistoryEvent) -> bool {
111
111
  event.event_type() == EventType::WorkflowExecutionContinuedAsNew
112
112
  }
113
-
114
- fn kind(&self) -> MachineKind {
115
- MachineKind::ContinueAsNewWorkflow
116
- }
117
113
  }
118
114
 
119
115
  impl Cancellable for ContinueAsNewWorkflowMachine {}
@@ -1,5 +1,5 @@
1
1
  use super::{
2
- workflow_machines::MachineResponse, Cancellable, EventInfo, MachineKind, NewMachineWithCommand,
2
+ workflow_machines::MachineResponse, Cancellable, EventInfo, NewMachineWithCommand,
3
3
  OnEventWrapper, WFMachinesAdapter, WFMachinesError,
4
4
  };
5
5
  use rustfsm::{fsm, TransitionResult};
@@ -124,10 +124,6 @@ impl WFMachinesAdapter for FailWorkflowMachine {
124
124
  fn matches_event(&self, event: &HistoryEvent) -> bool {
125
125
  event.event_type() == EventType::WorkflowExecutionFailed
126
126
  }
127
-
128
- fn kind(&self) -> MachineKind {
129
- MachineKind::FailWorkflow
130
- }
131
127
  }
132
128
 
133
129
  impl Cancellable for FailWorkflowMachine {}
@@ -1,10 +1,10 @@
1
1
  use super::{
2
- workflow_machines::MachineResponse, Cancellable, EventInfo, MachineKind, OnEventWrapper,
3
- WFMachinesAdapter, WFMachinesError,
2
+ workflow_machines::MachineResponse, Cancellable, EventInfo, OnEventWrapper, WFMachinesAdapter,
3
+ WFMachinesError,
4
4
  };
5
5
  use crate::{
6
6
  protosext::{CompleteLocalActivityData, HistoryEventExt, ValidScheduleLA},
7
- worker::LocalActivityExecutionResult,
7
+ worker::{workflow::OutgoingJob, LocalActivityExecutionResult},
8
8
  };
9
9
  use rustfsm::{fsm, MachineError, StateMachine, TransitionResult};
10
10
  use std::{
@@ -79,6 +79,10 @@ fsm! {
79
79
  // even though we already resolved the activity.
80
80
  WaitingMarkerEventPreResolved --(MarkerRecorded(CompleteLocalActivityData),
81
81
  shared on_marker_recorded) --> MarkerCommandRecorded;
82
+ // Ignore cancellations when waiting for the marker after being pre-resolved
83
+ WaitingMarkerEventPreResolved --(Cancel) --> WaitingMarkerEventPreResolved;
84
+ WaitingMarkerEventPreResolved --(NoWaitCancel(ActivityCancellationType))
85
+ --> WaitingMarkerEventPreResolved;
82
86
 
83
87
  // Ignore cancellation in final state
84
88
  MarkerCommandRecorded --(Cancel, on_cancel_requested) --> MarkerCommandRecorded;
@@ -286,6 +290,7 @@ impl SharedState {
286
290
  }
287
291
  }
288
292
 
293
+ #[allow(clippy::large_enum_variant)]
289
294
  #[derive(Debug, derive_more::Display)]
290
295
  pub(super) enum LocalActivityCommand {
291
296
  RequestActivityExecution(ValidScheduleLA),
@@ -643,13 +648,14 @@ impl WFMachinesAdapter for LocalActivityMachine {
643
648
  result.into()
644
649
  };
645
650
  let mut responses = vec![
646
- MachineResponse::PushWFJob(
647
- ResolveActivity {
651
+ MachineResponse::PushWFJob(OutgoingJob {
652
+ variant: ResolveActivity {
648
653
  seq: self.shared_state.attrs.seq,
649
654
  result: Some(resolution),
650
655
  }
651
656
  .into(),
652
- ),
657
+ is_la_resolution: true,
658
+ }),
653
659
  MachineResponse::UpdateWFTime(complete_time),
654
660
  ];
655
661
 
@@ -708,10 +714,6 @@ impl WFMachinesAdapter for LocalActivityMachine {
708
714
  fn matches_event(&self, event: &HistoryEvent) -> bool {
709
715
  event.is_local_activity_marker()
710
716
  }
711
-
712
- fn kind(&self) -> MachineKind {
713
- MachineKind::LocalActivity
714
- }
715
717
  }
716
718
 
717
719
  impl TryFrom<CommandType> for LocalActivityMachineEvents {
@@ -940,7 +942,7 @@ mod tests {
940
942
  let commands = wfm.get_server_commands().commands;
941
943
  assert_eq!(commands.len(), 0);
942
944
  let ready_to_execute_las = wfm.drain_queued_local_activities();
943
- let num_queued = if !replay { 1 } else { 0 };
945
+ let num_queued = usize::from(!replay);
944
946
  assert_eq!(ready_to_execute_las.len(), num_queued);
945
947
 
946
948
  if !replay {
@@ -1116,7 +1118,7 @@ mod tests {
1116
1118
  let commands = wfm.get_server_commands().commands;
1117
1119
  assert_eq!(commands.len(), 0);
1118
1120
  let ready_to_execute_las = wfm.drain_queued_local_activities();
1119
- let num_queued = if !replay { 1 } else { 0 };
1121
+ let num_queued = usize::from(!replay);
1120
1122
  assert_eq!(ready_to_execute_las.len(), num_queued);
1121
1123
 
1122
1124
  if !replay {
@@ -1158,7 +1160,7 @@ mod tests {
1158
1160
  }]
1159
1161
  );
1160
1162
  let ready_to_execute_las = wfm.drain_queued_local_activities();
1161
- let num_queued = if !replay { 1 } else { 0 };
1163
+ let num_queued = usize::from(!replay);
1162
1164
  assert_eq!(ready_to_execute_las.len(), num_queued);
1163
1165
  if !replay {
1164
1166
  wfm.complete_local_activity(2, ActivityExecutionResult::ok(b"Resolved".into()))
@@ -1210,17 +1212,12 @@ mod tests {
1210
1212
  let histinfo = t.get_full_history_info().unwrap().into();
1211
1213
  let mut wfm = ManagedWFFunc::new_from_update(histinfo, func, vec![]);
1212
1214
 
1213
- // First activation will request to run the LA, but it will *not* be queued for execution
1214
- // yet as we're still replaying.
1215
+ // First activation will request to run the LA since the heartbeat & wft failure are skipped
1216
+ // over
1215
1217
  wfm.get_next_activation().await.unwrap();
1216
1218
  let commands = wfm.get_server_commands().commands;
1217
1219
  assert_eq!(commands.len(), 0);
1218
1220
  let ready_to_execute_las = wfm.drain_queued_local_activities();
1219
- assert_eq!(ready_to_execute_las.len(), 0);
1220
-
1221
- // On the *next* activation, we are no longer replaying and the activity should be queued
1222
- wfm.get_next_activation().await.unwrap();
1223
- let ready_to_execute_las = wfm.drain_queued_local_activities();
1224
1221
  assert_eq!(ready_to_execute_las.len(), 1);
1225
1222
  // We can happily complete it now
1226
1223
  wfm.complete_local_activity(1, ActivityExecutionResult::ok(b"hi".into()))
@@ -1383,7 +1380,7 @@ mod tests {
1383
1380
  assert_eq!(commands.len(), 1);
1384
1381
  assert_eq!(commands[0].command_type, CommandType::StartTimer as i32);
1385
1382
  let ready_to_execute_las = wfm.drain_queued_local_activities();
1386
- let num_queued = if !replay { 1 } else { 0 };
1383
+ let num_queued = usize::from(!replay);
1387
1384
  assert_eq!(ready_to_execute_las.len(), num_queued);
1388
1385
 
1389
1386
  // Next activation timer fires and activity cancel will be requested
@@ -8,11 +8,8 @@ mod complete_workflow_state_machine;
8
8
  mod continue_as_new_workflow_state_machine;
9
9
  mod fail_workflow_state_machine;
10
10
  mod local_activity_state_machine;
11
- #[allow(unused)]
12
- mod mutable_side_effect_state_machine;
11
+ mod modify_workflow_properties_state_machine;
13
12
  mod patch_state_machine;
14
- #[allow(unused)]
15
- mod side_effect_state_machine;
16
13
  mod signal_external_state_machine;
17
14
  mod timer_state_machine;
18
15
  mod upsert_search_attributes_state_machine;
@@ -32,8 +29,8 @@ use complete_workflow_state_machine::CompleteWorkflowMachine;
32
29
  use continue_as_new_workflow_state_machine::ContinueAsNewWorkflowMachine;
33
30
  use fail_workflow_state_machine::FailWorkflowMachine;
34
31
  use local_activity_state_machine::LocalActivityMachine;
32
+ use modify_workflow_properties_state_machine::ModifyWorkflowPropertiesMachine;
35
33
  use patch_state_machine::PatchMachine;
36
- use prost::alloc::fmt::Formatter;
37
34
  use rustfsm::{MachineError, StateMachine};
38
35
  use signal_external_state_machine::SignalExternalMachine;
39
36
  use std::{
@@ -53,23 +50,6 @@ use workflow_task_state_machine::WorkflowTaskMachine;
53
50
  #[cfg(test)]
54
51
  use transition_coverage::add_coverage;
55
52
 
56
- #[derive(Copy, Clone, Debug, derive_more::Display, Eq, PartialEq)]
57
- enum MachineKind {
58
- Activity,
59
- CancelWorkflow,
60
- ChildWorkflow,
61
- CompleteWorkflow,
62
- ContinueAsNewWorkflow,
63
- FailWorkflow,
64
- Timer,
65
- Patch,
66
- WorkflowTask,
67
- SignalExternalWorkflow,
68
- CancelExternalWorkflow,
69
- LocalActivity,
70
- UpsertSearchAttributes,
71
- }
72
-
73
53
  #[enum_dispatch::enum_dispatch]
74
54
  #[allow(clippy::enum_variant_names, clippy::large_enum_variant)]
75
55
  enum Machines {
@@ -86,6 +66,7 @@ enum Machines {
86
66
  TimerMachine,
87
67
  WorkflowTaskMachine,
88
68
  UpsertSearchAttributesMachine,
69
+ ModifyWorkflowPropertiesMachine,
89
70
  }
90
71
 
91
72
  /// Extends [rustfsm::StateMachine] with some functionality specific to the temporal SDK.
@@ -93,7 +74,6 @@ enum Machines {
93
74
  /// Formerly known as `EntityStateMachine` in Java.
94
75
  #[enum_dispatch::enum_dispatch(Machines)]
95
76
  trait TemporalStateMachine: Send {
96
- fn kind(&self) -> MachineKind;
97
77
  fn handle_command(
98
78
  &mut self,
99
79
  command_type: CommandType,
@@ -121,6 +101,9 @@ trait TemporalStateMachine: Send {
121
101
 
122
102
  /// Returns true if the state machine is in a final state
123
103
  fn is_final_state(&self) -> bool;
104
+
105
+ /// Returns a friendly name for the type of this machine
106
+ fn name(&self) -> &str;
124
107
  }
125
108
 
126
109
  impl<SM> TemporalStateMachine for SM
@@ -132,10 +115,6 @@ where
132
115
  <SM as StateMachine>::State: Display,
133
116
  <SM as StateMachine>::Error: Into<WFMachinesError> + 'static + Send + Sync,
134
117
  {
135
- fn kind(&self) -> MachineKind {
136
- self.kind()
137
- }
138
-
139
118
  fn handle_command(
140
119
  &mut self,
141
120
  command_type: CommandType,
@@ -162,7 +141,7 @@ where
162
141
  Err(WFMachinesError::Nondeterminism(format!(
163
142
  "Unexpected command {:?} generated by a {:?} machine",
164
143
  command_type,
165
- self.kind()
144
+ self.name()
166
145
  )))
167
146
  }
168
147
  }
@@ -220,6 +199,10 @@ where
220
199
  fn is_final_state(&self) -> bool {
221
200
  self.has_reached_final_state()
222
201
  }
202
+
203
+ fn name(&self) -> &str {
204
+ self.name()
205
+ }
223
206
  }
224
207
 
225
208
  fn process_machine_commands<SM>(
@@ -235,7 +218,7 @@ where
235
218
  {
236
219
  if !commands.is_empty() {
237
220
  debug!(commands=%commands.display(), state=%machine.state(),
238
- machine_name=%TemporalStateMachine::kind(machine), "Machine produced commands");
221
+ machine_name=%TemporalStateMachine::name(machine), "Machine produced commands");
239
222
  }
240
223
  let mut machine_responses = vec![];
241
224
  for cmd in commands {
@@ -260,9 +243,6 @@ trait WFMachinesAdapter: StateMachine {
260
243
  /// ahead of time if it's worth trying to call [TemporalStateMachine::handle_event] without
261
244
  /// requiring mutable access.
262
245
  fn matches_event(&self, event: &HistoryEvent) -> bool;
263
-
264
- /// Allows robust identification of the type of machine
265
- fn kind(&self) -> MachineKind;
266
246
  }
267
247
 
268
248
  #[derive(Debug, Copy, Clone)]
@@ -334,9 +314,3 @@ struct NewMachineWithCommand {
334
314
  command: ProtoCommand,
335
315
  machine: Machines,
336
316
  }
337
-
338
- impl Debug for dyn TemporalStateMachine {
339
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
340
- std::fmt::Display::fmt(&self.kind(), f)
341
- }
342
- }