@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.
- package/Cargo.lock +327 -419
- package/Cargo.toml +1 -1
- package/index.js +25 -2
- package/lib/errors.d.ts +22 -0
- package/lib/errors.js +65 -0
- package/lib/errors.js.map +1 -0
- package/lib/index.d.ts +440 -0
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -0
- package/package.json +11 -5
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.buildkite/docker/Dockerfile +1 -1
- package/sdk-core/.buildkite/docker/docker-compose.yaml +2 -2
- package/sdk-core/bridge-ffi/Cargo.toml +1 -1
- package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -25
- package/sdk-core/bridge-ffi/src/lib.rs +29 -108
- package/sdk-core/bridge-ffi/src/wrappers.rs +35 -25
- package/sdk-core/client/Cargo.toml +1 -1
- package/sdk-core/client/src/lib.rs +12 -20
- package/sdk-core/client/src/raw.rs +9 -8
- package/sdk-core/client/src/retry.rs +100 -23
- package/sdk-core/core/Cargo.toml +5 -5
- package/sdk-core/core/benches/workflow_replay.rs +13 -10
- package/sdk-core/core/src/abstractions.rs +22 -22
- package/sdk-core/core/src/core_tests/activity_tasks.rs +1 -1
- package/sdk-core/core/src/core_tests/local_activities.rs +228 -6
- package/sdk-core/core/src/core_tests/queries.rs +247 -89
- package/sdk-core/core/src/core_tests/workers.rs +2 -2
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +46 -27
- package/sdk-core/core/src/lib.rs +139 -32
- package/sdk-core/core/src/replay/mod.rs +185 -41
- package/sdk-core/core/src/telemetry/log_export.rs +190 -0
- package/sdk-core/core/src/telemetry/metrics.rs +184 -139
- package/sdk-core/core/src/telemetry/mod.rs +296 -318
- package/sdk-core/core/src/telemetry/prometheus_server.rs +4 -3
- package/sdk-core/core/src/test_help/mod.rs +9 -7
- package/sdk-core/core/src/worker/activities/local_activities.rs +2 -1
- package/sdk-core/core/src/worker/activities.rs +40 -23
- package/sdk-core/core/src/worker/client/mocks.rs +1 -1
- package/sdk-core/core/src/worker/client.rs +30 -4
- package/sdk-core/core/src/worker/mod.rs +22 -18
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +10 -19
- package/sdk-core/core/src/worker/workflow/history_update.rs +99 -25
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +2 -6
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +18 -21
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -38
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +178 -0
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +8 -2
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +232 -216
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +1 -6
- package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +4 -4
- package/sdk-core/core/src/worker/workflow/managed_run.rs +13 -5
- package/sdk-core/core/src/worker/workflow/mod.rs +61 -9
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +2 -2
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +56 -11
- package/sdk-core/core-api/Cargo.toml +4 -3
- package/sdk-core/core-api/src/lib.rs +1 -43
- package/sdk-core/core-api/src/telemetry.rs +147 -0
- package/sdk-core/core-api/src/worker.rs +13 -0
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
- package/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
- package/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
- package/sdk-core/protos/api_upstream/.github/CODEOWNERS +1 -1
- package/sdk-core/protos/api_upstream/buf.yaml +0 -3
- package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +3 -7
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +8 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +2 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +3 -0
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +13 -0
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +19 -59
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -19
- package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +108 -29
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +47 -8
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +15 -1
- package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +8 -1
- package/sdk-core/sdk/src/interceptors.rs +36 -3
- package/sdk-core/sdk/src/lib.rs +7 -4
- package/sdk-core/sdk/src/workflow_context.rs +13 -2
- package/sdk-core/sdk-core-protos/src/history_builder.rs +47 -1
- package/sdk-core/sdk-core-protos/src/history_info.rs +22 -22
- package/sdk-core/sdk-core-protos/src/lib.rs +49 -27
- package/sdk-core/test-utils/Cargo.toml +1 -0
- package/sdk-core/test-utils/src/lib.rs +81 -29
- package/sdk-core/tests/integ_tests/metrics_tests.rs +37 -0
- package/sdk-core/tests/integ_tests/polling_tests.rs +0 -13
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +145 -4
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +53 -0
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +106 -20
- package/sdk-core/tests/integ_tests/workflow_tests.rs +18 -8
- package/sdk-core/tests/main.rs +6 -4
- package/src/conversions.rs +52 -47
- package/src/errors.rs +28 -86
- package/src/helpers.rs +3 -4
- package/src/lib.rs +2 -2
- package/src/runtime.rs +132 -61
- package/src/testing.rs +7 -4
- package/src/worker.rs +67 -50
- package/ts/errors.ts +55 -0
- package/{index.d.ts → ts/index.ts} +121 -15
- package/sdk-core/core/src/log_export.rs +0 -62
- package/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
- package/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
- package/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
- 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,
|
|
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
|
|
211
|
-
self.buffered.
|
|
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,
|
|
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
|
|
220
|
-
self.buffered.
|
|
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>,
|
|
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
|
|
244
|
-
// events (exclusive) as soon as we see an event
|
|
245
|
-
// failed or
|
|
246
|
-
let mut
|
|
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
|
|
251
|
-
|
|
253
|
+
} else if e.event_type() == EventType::WorkflowTaskStarted {
|
|
254
|
+
next_wft_state = NextWftState::Seen;
|
|
252
255
|
return true;
|
|
253
256
|
}
|
|
254
257
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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 {}
|
package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
use super::{
|
|
2
|
-
Cancellable, EventInfo, HistoryEvent,
|
|
3
|
-
|
|
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,
|
|
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,
|
|
3
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
1214
|
-
//
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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::
|
|
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
|
-
}
|