@temporalio/core-bridge 0.14.0 → 0.16.4
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 +162 -38
- package/Cargo.toml +3 -3
- package/index.d.ts +14 -1
- package/index.node +0 -0
- package/package.json +8 -5
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/{x86_64-pc-windows-gnu → 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/scripts/build.js +77 -34
- package/sdk-core/.buildkite/docker/Dockerfile +1 -1
- package/sdk-core/Cargo.toml +6 -5
- package/sdk-core/fsm/Cargo.toml +1 -1
- package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +2 -2
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +8 -9
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +13 -7
- package/sdk-core/fsm/rustfsm_trait/Cargo.toml +2 -2
- package/sdk-core/fsm/rustfsm_trait/src/lib.rs +1 -1
- package/sdk-core/protos/local/workflow_activation.proto +6 -3
- package/sdk-core/sdk-core-protos/Cargo.toml +4 -4
- package/sdk-core/sdk-core-protos/src/lib.rs +38 -50
- package/sdk-core/src/core_tests/activity_tasks.rs +5 -5
- package/sdk-core/src/core_tests/child_workflows.rs +55 -29
- package/sdk-core/src/core_tests/determinism.rs +19 -9
- package/sdk-core/src/core_tests/mod.rs +3 -3
- package/sdk-core/src/core_tests/retry.rs +14 -8
- package/sdk-core/src/core_tests/workers.rs +1 -1
- package/sdk-core/src/core_tests/workflow_tasks.rs +347 -4
- package/sdk-core/src/errors.rs +27 -44
- package/sdk-core/src/lib.rs +13 -3
- package/sdk-core/src/machines/activity_state_machine.rs +44 -5
- package/sdk-core/src/machines/child_workflow_state_machine.rs +31 -11
- package/sdk-core/src/machines/complete_workflow_state_machine.rs +1 -1
- package/sdk-core/src/machines/continue_as_new_workflow_state_machine.rs +1 -1
- package/sdk-core/src/machines/mod.rs +18 -23
- package/sdk-core/src/machines/patch_state_machine.rs +8 -8
- package/sdk-core/src/machines/signal_external_state_machine.rs +22 -1
- package/sdk-core/src/machines/timer_state_machine.rs +21 -3
- package/sdk-core/src/machines/transition_coverage.rs +3 -3
- package/sdk-core/src/machines/workflow_machines.rs +11 -11
- package/sdk-core/src/pending_activations.rs +27 -22
- package/sdk-core/src/pollers/gateway.rs +15 -7
- package/sdk-core/src/pollers/poll_buffer.rs +6 -5
- package/sdk-core/src/pollers/retry.rs +153 -120
- package/sdk-core/src/prototype_rust_sdk/workflow_context.rs +61 -46
- package/sdk-core/src/prototype_rust_sdk/workflow_future.rs +13 -12
- package/sdk-core/src/prototype_rust_sdk.rs +17 -23
- package/sdk-core/src/telemetry/metrics.rs +2 -4
- package/sdk-core/src/telemetry/mod.rs +6 -7
- package/sdk-core/src/test_help/canned_histories.rs +17 -93
- package/sdk-core/src/test_help/history_builder.rs +61 -2
- package/sdk-core/src/test_help/history_info.rs +21 -2
- package/sdk-core/src/test_help/mod.rs +26 -34
- package/sdk-core/src/worker/activities/activity_heartbeat_manager.rs +246 -138
- package/sdk-core/src/worker/activities.rs +46 -45
- package/sdk-core/src/worker/config.rs +11 -0
- package/sdk-core/src/worker/dispatcher.rs +5 -5
- package/sdk-core/src/worker/mod.rs +86 -56
- package/sdk-core/src/workflow/driven_workflow.rs +3 -3
- package/sdk-core/src/workflow/history_update.rs +1 -1
- package/sdk-core/src/workflow/mod.rs +2 -1
- package/sdk-core/src/workflow/workflow_tasks/cache_manager.rs +13 -17
- package/sdk-core/src/workflow/workflow_tasks/concurrency_manager.rs +10 -18
- package/sdk-core/src/workflow/workflow_tasks/mod.rs +72 -57
- package/sdk-core/test_utils/Cargo.toml +1 -1
- package/sdk-core/test_utils/src/lib.rs +2 -2
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +61 -1
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +2 -2
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +49 -0
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +2 -2
- package/sdk-core/tests/integ_tests/workflow_tests.rs +1 -0
- package/src/conversions.rs +17 -0
- package/src/errors.rs +0 -7
- package/src/lib.rs +0 -20
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
extern crate proc_macro;
|
|
2
|
-
|
|
3
1
|
use proc_macro::TokenStream;
|
|
4
2
|
use quote::{quote, quote_spanned};
|
|
5
3
|
use std::collections::{hash_map::Entry, HashMap, HashSet};
|
|
@@ -82,7 +80,7 @@ use syn::{
|
|
|
82
80
|
/// ReadingCard { card_data: data.clone() }.into(),
|
|
83
81
|
/// SharedState { last_id: Some(data) }
|
|
84
82
|
/// )
|
|
85
|
-
/// }
|
|
83
|
+
/// }
|
|
86
84
|
/// }
|
|
87
85
|
/// }
|
|
88
86
|
/// }
|
|
@@ -200,7 +198,7 @@ impl Parse for StateMachineDefinition {
|
|
|
200
198
|
// Parse visibility if present
|
|
201
199
|
let visibility = input.parse()?;
|
|
202
200
|
// parse the state machine name, command type, and error type
|
|
203
|
-
let (name, command_type, error_type, shared_state_type) = parse_machine_types(
|
|
201
|
+
let (name, command_type, error_type, shared_state_type) = parse_machine_types(input)
|
|
204
202
|
.map_err(|mut e| {
|
|
205
203
|
e.combine(Error::new(
|
|
206
204
|
e.span(),
|
|
@@ -235,7 +233,7 @@ impl Parse for StateMachineDefinition {
|
|
|
235
233
|
}
|
|
236
234
|
}
|
|
237
235
|
|
|
238
|
-
fn parse_machine_types(input:
|
|
236
|
+
fn parse_machine_types(input: ParseStream) -> Result<(Ident, Ident, Ident, Option<Type>)> {
|
|
239
237
|
let _: kw::name = input.parse()?;
|
|
240
238
|
let name: Ident = input.parse()?;
|
|
241
239
|
input.parse::<Token![;]>()?;
|
|
@@ -443,7 +441,7 @@ impl StateMachineDefinition {
|
|
|
443
441
|
},
|
|
444
442
|
multi_dests => {
|
|
445
443
|
let string_dests: Vec<_> = multi_dests.iter()
|
|
446
|
-
.map(
|
|
444
|
+
.map(ToString::to_string).collect();
|
|
447
445
|
let enum_ident = Ident::new(&string_dests.join("Or"),
|
|
448
446
|
multi_dests[0].span());
|
|
449
447
|
let multi_dest_enum = quote! {
|
|
@@ -558,6 +556,7 @@ impl StateMachineDefinition {
|
|
|
558
556
|
fn state(&self) -> &Self::State {
|
|
559
557
|
&self.state
|
|
560
558
|
}
|
|
559
|
+
|
|
561
560
|
fn set_state(&mut self, new: Self::State) {
|
|
562
561
|
self.state = new
|
|
563
562
|
}
|
|
@@ -590,7 +589,7 @@ impl StateMachineDefinition {
|
|
|
590
589
|
#trait_impl
|
|
591
590
|
};
|
|
592
591
|
|
|
593
|
-
output
|
|
592
|
+
TokenStream::from(output)
|
|
594
593
|
}
|
|
595
594
|
|
|
596
595
|
fn all_states(&self) -> HashSet<Ident> {
|
|
@@ -628,7 +627,7 @@ impl StateMachineDefinition {
|
|
|
628
627
|
/// Merge transition's dest state lists for those with the same from state & handler
|
|
629
628
|
fn merge_transition_dests(transitions: Vec<Transition>) -> Vec<Transition> {
|
|
630
629
|
let mut map = HashMap::<_, Transition>::new();
|
|
631
|
-
|
|
630
|
+
for t in transitions {
|
|
632
631
|
// We want to use the transition sans-destinations as the key
|
|
633
632
|
let without_dests = {
|
|
634
633
|
let mut wd = t.clone();
|
|
@@ -643,6 +642,6 @@ fn merge_transition_dests(transitions: Vec<Transition>) -> Vec<Transition> {
|
|
|
643
642
|
v.insert(t);
|
|
644
643
|
}
|
|
645
644
|
}
|
|
646
|
-
}
|
|
645
|
+
}
|
|
647
646
|
map.into_iter().map(|(_, v)| v).collect()
|
|
648
647
|
}
|
package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
error[E0277]: the trait bound `One: From<Two>` is not satisfied
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
11
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
--> tests/trybuild/no_handle_conversions_require_into_fail.rs:11:18
|
|
3
|
+
|
|
|
4
|
+
11 | Two --(B)--> One;
|
|
5
|
+
| ^^^ the trait `From<Two>` is not implemented for `One`
|
|
6
|
+
|
|
|
7
|
+
= note: required because of the requirements on the impl of `Into<One>` for `Two`
|
|
8
|
+
note: required by `TransitionResult::<Sm, Ds>::from`
|
|
9
|
+
--> $WORKSPACE/fsm/rustfsm_trait/src/lib.rs
|
|
10
|
+
|
|
|
11
|
+
| / pub fn from<CurrentState>(current_state: CurrentState) -> Self
|
|
12
|
+
| | where
|
|
13
|
+
| | CurrentState: Into<Ds>,
|
|
14
|
+
| |_______________________________^
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name = "rustfsm_trait"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
authors = ["Spencer Judge <spencer@temporal.io>"]
|
|
5
|
-
edition = "
|
|
5
|
+
edition = "2021"
|
|
6
6
|
license-file = "LICENSE.txt"
|
|
7
7
|
description = "Trait sub-crate of the `rustfsm` crate"
|
|
8
8
|
|
|
@@ -11,4 +11,4 @@ description = "Trait sub-crate of the `rustfsm` crate"
|
|
|
11
11
|
[dependencies]
|
|
12
12
|
|
|
13
13
|
[package.metadata.workspaces]
|
|
14
|
-
independent = true
|
|
14
|
+
independent = true
|
|
@@ -59,9 +59,8 @@ message WFActivationJob {
|
|
|
59
59
|
/// after performing the activation.
|
|
60
60
|
///
|
|
61
61
|
/// If other job variant are present in the list, this variant will be the last job in the
|
|
62
|
-
/// job list. The
|
|
63
|
-
|
|
64
|
-
bool remove_from_cache = 50;
|
|
62
|
+
/// job list. The string value is a reason for eviction.
|
|
63
|
+
RemoveFromCache remove_from_cache = 50;
|
|
65
64
|
}
|
|
66
65
|
}
|
|
67
66
|
|
|
@@ -187,3 +186,7 @@ message ResolveRequestCancelExternalWorkflow {
|
|
|
187
186
|
/// type / info.
|
|
188
187
|
temporal.api.failure.v1.Failure failure = 2;
|
|
189
188
|
}
|
|
189
|
+
|
|
190
|
+
message RemoveFromCache {
|
|
191
|
+
string reason = 1;
|
|
192
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "temporal-sdk-core-protos"
|
|
3
3
|
version = "0.1.0"
|
|
4
|
-
edition = "
|
|
4
|
+
edition = "2021"
|
|
5
5
|
authors = ["Spencer Judge <spencer@temporal.io>"]
|
|
6
6
|
license-file = "LICENSE.txt"
|
|
7
7
|
description = "Protobuf definitions for Temporal SDKs Core/Lang interface"
|
|
@@ -12,9 +12,9 @@ categories = ["development-tools"]
|
|
|
12
12
|
|
|
13
13
|
[dependencies]
|
|
14
14
|
derive_more = "0.99"
|
|
15
|
-
prost = "0.
|
|
16
|
-
prost-types = "0.
|
|
17
|
-
tonic = "0.
|
|
15
|
+
prost = "0.9"
|
|
16
|
+
prost-types = "0.9"
|
|
17
|
+
tonic = "0.6"
|
|
18
18
|
|
|
19
19
|
[build-dependencies]
|
|
20
20
|
tonic-build = "0.5"
|
|
@@ -38,7 +38,7 @@ pub mod coresdk {
|
|
|
38
38
|
activity_id: String,
|
|
39
39
|
reason: ActivityCancelReason,
|
|
40
40
|
) -> Self {
|
|
41
|
-
|
|
41
|
+
Self {
|
|
42
42
|
task_token,
|
|
43
43
|
activity_id,
|
|
44
44
|
variant: Some(activity_task::Variant::Cancel(Cancel {
|
|
@@ -75,7 +75,7 @@ pub mod coresdk {
|
|
|
75
75
|
})),
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
pub fn will_complete_async() -> Self {
|
|
78
|
+
pub const fn will_complete_async() -> Self {
|
|
79
79
|
Self {
|
|
80
80
|
status: Some(activity_result::Status::WillCompleteAsync(
|
|
81
81
|
WillCompleteAsync {},
|
|
@@ -139,13 +139,13 @@ pub mod coresdk {
|
|
|
139
139
|
use std::fmt::{Display, Formatter};
|
|
140
140
|
|
|
141
141
|
tonic::include_proto!("coresdk.workflow_activation");
|
|
142
|
-
pub fn create_evict_activation(run_id: String) -> WfActivation {
|
|
142
|
+
pub fn create_evict_activation(run_id: String, reason: String) -> WfActivation {
|
|
143
143
|
WfActivation {
|
|
144
144
|
timestamp: None,
|
|
145
145
|
run_id,
|
|
146
146
|
is_replaying: false,
|
|
147
147
|
jobs: vec![WfActivationJob::from(
|
|
148
|
-
wf_activation_job::Variant::RemoveFromCache(
|
|
148
|
+
wf_activation_job::Variant::RemoveFromCache(RemoveFromCache { reason }),
|
|
149
149
|
)],
|
|
150
150
|
}
|
|
151
151
|
}
|
|
@@ -195,7 +195,7 @@ pub mod coresdk {
|
|
|
195
195
|
"jobs: {})",
|
|
196
196
|
self.jobs
|
|
197
197
|
.iter()
|
|
198
|
-
.map(
|
|
198
|
+
.map(ToString::to_string)
|
|
199
199
|
.collect::<Vec<_>>()
|
|
200
200
|
.as_slice()
|
|
201
201
|
.join(", ")
|
|
@@ -264,18 +264,18 @@ pub mod coresdk {
|
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
pub mod workflow_completion {
|
|
267
|
-
use crate::coresdk::workflow_completion::wf_activation_completion::Status;
|
|
268
267
|
tonic::include_proto!("coresdk.workflow_completion");
|
|
269
268
|
|
|
270
269
|
impl wf_activation_completion::Status {
|
|
271
|
-
pub fn is_success(&self) -> bool {
|
|
270
|
+
pub const fn is_success(&self) -> bool {
|
|
272
271
|
match &self {
|
|
273
|
-
|
|
274
|
-
|
|
272
|
+
Self::Successful(_) => true,
|
|
273
|
+
Self::Failed(_) => false,
|
|
275
274
|
}
|
|
276
275
|
}
|
|
277
276
|
}
|
|
278
277
|
}
|
|
278
|
+
|
|
279
279
|
pub mod child_workflow {
|
|
280
280
|
tonic::include_proto!("coresdk.child_workflow");
|
|
281
281
|
}
|
|
@@ -370,7 +370,7 @@ pub mod coresdk {
|
|
|
370
370
|
|
|
371
371
|
impl From<wf_activation_job::Variant> for WfActivationJob {
|
|
372
372
|
fn from(a: wf_activation_job::Variant) -> Self {
|
|
373
|
-
|
|
373
|
+
Self { variant: Some(a) }
|
|
374
374
|
}
|
|
375
375
|
}
|
|
376
376
|
|
|
@@ -382,7 +382,7 @@ pub mod coresdk {
|
|
|
382
382
|
|
|
383
383
|
impl From<workflow_command::Variant> for WorkflowCommand {
|
|
384
384
|
fn from(v: workflow_command::Variant) -> Self {
|
|
385
|
-
|
|
385
|
+
Self { variant: Some(v) }
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
|
|
@@ -591,7 +591,7 @@ pub mod coresdk {
|
|
|
591
591
|
}
|
|
592
592
|
|
|
593
593
|
impl ActivityResult {
|
|
594
|
-
pub fn ok(result: Payload) -> Self {
|
|
594
|
+
pub const fn ok(result: Payload) -> Self {
|
|
595
595
|
Self {
|
|
596
596
|
status: Some(activity_result::activity_result::Status::Completed(
|
|
597
597
|
activity_result::Success {
|
|
@@ -615,24 +615,18 @@ pub mod coresdk {
|
|
|
615
615
|
.workflow_execution
|
|
616
616
|
.map(|we| (we.workflow_id, we.run_id))
|
|
617
617
|
.unwrap_or_default();
|
|
618
|
-
|
|
618
|
+
Self {
|
|
619
619
|
task_token: r.task_token,
|
|
620
620
|
activity_id: r.activity_id,
|
|
621
621
|
variant: Some(activity_task::activity_task::Variant::Start(
|
|
622
622
|
activity_task::Start {
|
|
623
623
|
workflow_namespace: r.workflow_namespace,
|
|
624
|
-
workflow_type: r
|
|
625
|
-
.workflow_type
|
|
626
|
-
.map(|wt| wt.name)
|
|
627
|
-
.unwrap_or_else(|| "".to_string()),
|
|
624
|
+
workflow_type: r.workflow_type.map_or_else(|| "".to_string(), |wt| wt.name),
|
|
628
625
|
workflow_execution: Some(common::WorkflowExecution {
|
|
629
626
|
workflow_id,
|
|
630
627
|
run_id,
|
|
631
628
|
}),
|
|
632
|
-
activity_type: r
|
|
633
|
-
.activity_type
|
|
634
|
-
.map(|at| at.name)
|
|
635
|
-
.unwrap_or_else(|| "".to_string()),
|
|
629
|
+
activity_type: r.activity_type.map_or_else(|| "".to_string(), |at| at.name),
|
|
636
630
|
header_fields: r.header.map(Into::into).unwrap_or_default(),
|
|
637
631
|
input: Vec::from_payloads(r.input),
|
|
638
632
|
heartbeat_details: Vec::from_payloads(r.heartbeat_details),
|
|
@@ -664,7 +658,7 @@ pub mod coresdk {
|
|
|
664
658
|
|
|
665
659
|
impl From<common::WorkflowExecution> for WorkflowExecution {
|
|
666
660
|
fn from(exc: common::WorkflowExecution) -> Self {
|
|
667
|
-
|
|
661
|
+
Self {
|
|
668
662
|
workflow_id: exc.workflow_id,
|
|
669
663
|
run_id: exc.run_id,
|
|
670
664
|
}
|
|
@@ -767,7 +761,7 @@ pub mod coresdk {
|
|
|
767
761
|
T: AsRef<[u8]>,
|
|
768
762
|
{
|
|
769
763
|
fn from(v: T) -> Self {
|
|
770
|
-
|
|
764
|
+
Self {
|
|
771
765
|
payloads: vec![v.into()],
|
|
772
766
|
}
|
|
773
767
|
}
|
|
@@ -786,10 +780,10 @@ pub mod coresdk {
|
|
|
786
780
|
match v.payloads.pop() {
|
|
787
781
|
None => Err(PayloadsToPayloadError::NoPayload),
|
|
788
782
|
Some(p) => {
|
|
789
|
-
if
|
|
790
|
-
Err(PayloadsToPayloadError::MoreThanOnePayload)
|
|
791
|
-
} else {
|
|
783
|
+
if v.payloads.is_empty() {
|
|
792
784
|
Ok(p.into())
|
|
785
|
+
} else {
|
|
786
|
+
Err(PayloadsToPayloadError::MoreThanOnePayload)
|
|
793
787
|
}
|
|
794
788
|
}
|
|
795
789
|
}
|
|
@@ -1091,26 +1085,22 @@ pub mod temporal {
|
|
|
1091
1085
|
impl HistoryEvent {
|
|
1092
1086
|
/// Returns true if this is an event created to mirror a command
|
|
1093
1087
|
pub fn is_command_event(&self) -> bool {
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
}
|
|
1111
|
-
} else {
|
|
1112
|
-
false
|
|
1113
|
-
}
|
|
1088
|
+
EventType::from_i32(self.event_type).map_or(false, |et| match et {
|
|
1089
|
+
EventType::ActivityTaskScheduled
|
|
1090
|
+
| EventType::ActivityTaskCancelRequested
|
|
1091
|
+
| EventType::MarkerRecorded
|
|
1092
|
+
| EventType::RequestCancelExternalWorkflowExecutionInitiated
|
|
1093
|
+
| EventType::SignalExternalWorkflowExecutionInitiated
|
|
1094
|
+
| EventType::StartChildWorkflowExecutionInitiated
|
|
1095
|
+
| EventType::TimerCanceled
|
|
1096
|
+
| EventType::TimerStarted
|
|
1097
|
+
| EventType::UpsertWorkflowSearchAttributes
|
|
1098
|
+
| EventType::WorkflowExecutionCanceled
|
|
1099
|
+
| EventType::WorkflowExecutionCompleted
|
|
1100
|
+
| EventType::WorkflowExecutionContinuedAsNew
|
|
1101
|
+
| EventType::WorkflowExecutionFailed => true,
|
|
1102
|
+
_ => false,
|
|
1103
|
+
})
|
|
1114
1104
|
}
|
|
1115
1105
|
|
|
1116
1106
|
/// Returns the command's initiating event id, if present. This is the id of the
|
|
@@ -1262,16 +1252,14 @@ pub mod temporal {
|
|
|
1262
1252
|
let last_event = self
|
|
1263
1253
|
.history
|
|
1264
1254
|
.as_ref()
|
|
1265
|
-
.
|
|
1266
|
-
.flatten()
|
|
1255
|
+
.and_then(|h| h.events.last().map(|he| he.event_id))
|
|
1267
1256
|
.unwrap_or(0);
|
|
1268
1257
|
write!(
|
|
1269
1258
|
f,
|
|
1270
1259
|
"PollWFTQResp(run_id: {}, attempt: {}, last_event: {})",
|
|
1271
1260
|
self.workflow_execution
|
|
1272
1261
|
.as_ref()
|
|
1273
|
-
.
|
|
1274
|
-
.unwrap_or(""),
|
|
1262
|
+
.map_or("", |we| we.run_id.as_str()),
|
|
1275
1263
|
self.attempt,
|
|
1276
1264
|
last_event
|
|
1277
1265
|
)
|
|
@@ -76,7 +76,7 @@ async fn max_activities_respected() {
|
|
|
76
76
|
core.register_worker(
|
|
77
77
|
WorkerConfigBuilder::default()
|
|
78
78
|
.task_queue(TEST_Q)
|
|
79
|
-
.max_outstanding_activities(
|
|
79
|
+
.max_outstanding_activities(2_usize)
|
|
80
80
|
.build()
|
|
81
81
|
.unwrap(),
|
|
82
82
|
)
|
|
@@ -163,7 +163,7 @@ async fn heartbeats_report_cancels_only_once() {
|
|
|
163
163
|
core.record_activity_heartbeat(ActivityHeartbeat {
|
|
164
164
|
task_token: act.task_token.clone(),
|
|
165
165
|
task_queue: TEST_Q.to_string(),
|
|
166
|
-
details: vec![vec![
|
|
166
|
+
details: vec![vec![1_u8, 2, 3].into()],
|
|
167
167
|
});
|
|
168
168
|
// We have to wait a beat for the heartbeat to be processed
|
|
169
169
|
sleep(Duration::from_millis(10)).await;
|
|
@@ -183,7 +183,7 @@ async fn heartbeats_report_cancels_only_once() {
|
|
|
183
183
|
core.record_activity_heartbeat(ActivityHeartbeat {
|
|
184
184
|
task_token: act.task_token,
|
|
185
185
|
task_queue: TEST_Q.to_string(),
|
|
186
|
-
details: vec![vec![
|
|
186
|
+
details: vec![vec![1_u8, 2, 3].into()],
|
|
187
187
|
});
|
|
188
188
|
sleep(Duration::from_millis(10)).await;
|
|
189
189
|
// Since cancels always come before new tasks, if we get a new non-cancel task, we did not
|
|
@@ -251,7 +251,7 @@ async fn activity_cancel_interrupts_poll() {
|
|
|
251
251
|
core.record_activity_heartbeat(ActivityHeartbeat {
|
|
252
252
|
task_token: act.task_token,
|
|
253
253
|
task_queue: TEST_Q.to_string(),
|
|
254
|
-
details: vec![vec![
|
|
254
|
+
details: vec![vec![1_u8, 2, 3].into()],
|
|
255
255
|
});
|
|
256
256
|
last_finisher.store(1, Ordering::SeqCst);
|
|
257
257
|
},
|
|
@@ -358,7 +358,7 @@ async fn many_concurrent_heartbeat_cancels() {
|
|
|
358
358
|
.task_queue(TEST_Q)
|
|
359
359
|
.max_outstanding_activities(CONCURRENCY_NUM)
|
|
360
360
|
// Only 1 poll at a time to avoid over-polling and running out of responses
|
|
361
|
-
.max_concurrent_at_polls(
|
|
361
|
+
.max_concurrent_at_polls(1_usize)
|
|
362
362
|
.build()
|
|
363
363
|
.unwrap(),
|
|
364
364
|
)
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
use crate::{
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
pollers::MockServerGatewayApis,
|
|
3
|
+
prototype_rust_sdk::{
|
|
4
|
+
ChildWorkflowOptions, TestRustWorker, WfContext, WorkflowFunction, WorkflowResult,
|
|
5
|
+
},
|
|
6
|
+
test_help::{
|
|
7
|
+
build_mock_pollers, canned_histories, mock_core, MockPollCfg, ResponseType,
|
|
8
|
+
DEFAULT_WORKFLOW_TYPE, TEST_Q,
|
|
9
|
+
},
|
|
4
10
|
workflow::managed_wf::ManagedWFFunc,
|
|
5
11
|
};
|
|
12
|
+
use std::sync::Arc;
|
|
6
13
|
use temporal_sdk_core_protos::coresdk::child_workflow::{
|
|
7
14
|
child_workflow_result, ChildWorkflowCancellationType,
|
|
8
15
|
};
|
|
@@ -10,33 +17,52 @@ use tokio::join;
|
|
|
10
17
|
|
|
11
18
|
const SIGNAME: &str = "SIGNAME";
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
workflow_type: "child".to_string(),
|
|
17
|
-
..Default::default()
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
let start_res = child
|
|
21
|
-
.start(&mut ctx)
|
|
22
|
-
.await
|
|
23
|
-
.as_started()
|
|
24
|
-
.expect("Child should get started");
|
|
25
|
-
let sigfut = start_res.signal(&mut ctx, SIGNAME, b"Hi!");
|
|
26
|
-
let resfut = start_res.result(&mut ctx);
|
|
27
|
-
let (sigres, res) = join!(sigfut, resfut);
|
|
28
|
-
sigres.expect("signal result is ok");
|
|
29
|
-
res.status.expect("child wf result is ok");
|
|
30
|
-
Ok(().into())
|
|
31
|
-
}
|
|
32
|
-
|
|
20
|
+
#[rstest::rstest]
|
|
21
|
+
#[case::signal_then_result(true)]
|
|
22
|
+
#[case::signal_and_result_concurrent(false)]
|
|
33
23
|
#[tokio::test]
|
|
34
|
-
async fn signal_child_workflow() {
|
|
35
|
-
let
|
|
24
|
+
async fn signal_child_workflow(#[case] serial: bool) {
|
|
25
|
+
let wf_id = "fakeid";
|
|
26
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
36
27
|
let t = canned_histories::single_child_workflow_signaled("child-id-1", SIGNAME);
|
|
37
|
-
let
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
let mock = MockServerGatewayApis::new();
|
|
29
|
+
let mh = MockPollCfg::from_resp_batches(wf_id, t, [ResponseType::AllHistory], mock);
|
|
30
|
+
let mock = build_mock_pollers(mh);
|
|
31
|
+
let core = mock_core(mock);
|
|
32
|
+
let mut worker = TestRustWorker::new(Arc::new(core), TEST_Q.to_string(), None);
|
|
33
|
+
|
|
34
|
+
let wf = move |mut ctx: WfContext| async move {
|
|
35
|
+
let child = ctx.child_workflow(ChildWorkflowOptions {
|
|
36
|
+
workflow_id: "child-id-1".to_string(),
|
|
37
|
+
workflow_type: "child".to_string(),
|
|
38
|
+
..Default::default()
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
let start_res = child
|
|
42
|
+
.start(&mut ctx)
|
|
43
|
+
.await
|
|
44
|
+
.into_started()
|
|
45
|
+
.expect("Child should get started");
|
|
46
|
+
let (sigres, res) = if serial {
|
|
47
|
+
let sigres = start_res.signal(&mut ctx, SIGNAME, b"Hi!").await;
|
|
48
|
+
let res = start_res.result().await;
|
|
49
|
+
(sigres, res)
|
|
50
|
+
} else {
|
|
51
|
+
let sigfut = start_res.signal(&mut ctx, SIGNAME, b"Hi!");
|
|
52
|
+
let resfut = start_res.result();
|
|
53
|
+
join!(sigfut, resfut)
|
|
54
|
+
};
|
|
55
|
+
sigres.expect("signal result is ok");
|
|
56
|
+
res.status.expect("child wf result is ok");
|
|
57
|
+
Ok(().into())
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
worker.register_wf(wf_type.to_owned(), wf);
|
|
61
|
+
worker
|
|
62
|
+
.submit_wf(wf_id.to_owned(), wf_type.to_owned(), vec![])
|
|
63
|
+
.await
|
|
64
|
+
.unwrap();
|
|
65
|
+
worker.run_until_done().await.unwrap();
|
|
40
66
|
}
|
|
41
67
|
|
|
42
68
|
async fn parent_cancels_child_wf(mut ctx: WfContext) -> WorkflowResult<()> {
|
|
@@ -50,10 +76,10 @@ async fn parent_cancels_child_wf(mut ctx: WfContext) -> WorkflowResult<()> {
|
|
|
50
76
|
let start_res = child
|
|
51
77
|
.start(&mut ctx)
|
|
52
78
|
.await
|
|
53
|
-
.
|
|
79
|
+
.into_started()
|
|
54
80
|
.expect("Child should get started");
|
|
55
81
|
let cancel_fut = start_res.cancel(&mut ctx);
|
|
56
|
-
let resfut = start_res.result(
|
|
82
|
+
let resfut = start_res.result();
|
|
57
83
|
let (cancel_res, res) = join!(cancel_fut, resfut);
|
|
58
84
|
cancel_res.expect("cancel result is ok");
|
|
59
85
|
let stat = res.status.expect("child wf result is ok");
|
|
@@ -8,7 +8,7 @@ use crate::{
|
|
|
8
8
|
};
|
|
9
9
|
use std::{
|
|
10
10
|
sync::{
|
|
11
|
-
atomic::{AtomicBool, Ordering},
|
|
11
|
+
atomic::{AtomicBool, AtomicUsize, Ordering},
|
|
12
12
|
Arc,
|
|
13
13
|
},
|
|
14
14
|
time::Duration,
|
|
@@ -64,7 +64,13 @@ async fn test_wf_task_rejected_properly_due_to_nondeterminism(#[case] use_cache:
|
|
|
64
64
|
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
65
65
|
let t = canned_histories::single_timer_wf_completes("1");
|
|
66
66
|
let mock = MockServerGatewayApis::new();
|
|
67
|
-
let mut mh = MockPollCfg::from_resp_batches(
|
|
67
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
68
|
+
wf_id,
|
|
69
|
+
t,
|
|
70
|
+
// Two polls are needed, since the first will fail
|
|
71
|
+
[ResponseType::AllHistory, ResponseType::AllHistory],
|
|
72
|
+
mock,
|
|
73
|
+
);
|
|
68
74
|
// We should see one wft failure which has nondeterminism cause
|
|
69
75
|
mh.num_expected_fails = Some(1);
|
|
70
76
|
mh.expect_fail_wft_matcher =
|
|
@@ -78,10 +84,13 @@ async fn test_wf_task_rejected_properly_due_to_nondeterminism(#[case] use_cache:
|
|
|
78
84
|
let core = mock_core(mock);
|
|
79
85
|
let mut worker = TestRustWorker::new(Arc::new(core), TEST_Q.to_string(), None);
|
|
80
86
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
let started_count: &'static _ = Box::leak(Box::new(AtomicUsize::new(0)));
|
|
88
|
+
worker.register_wf(wf_type.to_owned(), move |mut ctx: WfContext| async move {
|
|
89
|
+
// The workflow is replaying all of history, so the when it schedules an extra timer it
|
|
90
|
+
// should not have, it causes a nondeterminism error.
|
|
91
|
+
if started_count.fetch_add(1, Ordering::Relaxed) == 0 {
|
|
92
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
93
|
+
}
|
|
85
94
|
ctx.timer(Duration::from_secs(1)).await;
|
|
86
95
|
Ok(().into())
|
|
87
96
|
});
|
|
@@ -90,7 +99,8 @@ async fn test_wf_task_rejected_properly_due_to_nondeterminism(#[case] use_cache:
|
|
|
90
99
|
.submit_wf(wf_id.to_owned(), wf_type.to_owned(), vec![])
|
|
91
100
|
.await
|
|
92
101
|
.unwrap();
|
|
93
|
-
|
|
94
|
-
//
|
|
95
|
-
|
|
102
|
+
worker.run_until_done().await.unwrap();
|
|
103
|
+
// Started count is two since we start, restart once due to error, then we unblock the real
|
|
104
|
+
// timer and proceed without restarting
|
|
105
|
+
assert_eq!(2, started_count.load(Ordering::Relaxed));
|
|
96
106
|
}
|
|
@@ -65,7 +65,7 @@ async fn shutdown_interrupts_both_polls() {
|
|
|
65
65
|
mock_gateway
|
|
66
66
|
.expect_poll_workflow_task()
|
|
67
67
|
.times(1)
|
|
68
|
-
.returning(move |_| {
|
|
68
|
+
.returning(move |_, _| {
|
|
69
69
|
async move {
|
|
70
70
|
BARR.wait().await;
|
|
71
71
|
sleep(Duration::from_secs(1)).await;
|
|
@@ -91,8 +91,8 @@ async fn shutdown_interrupts_both_polls() {
|
|
|
91
91
|
WorkerConfigBuilder::default()
|
|
92
92
|
.task_queue(TEST_Q)
|
|
93
93
|
// Need only 1 concurrent pollers for mock expectations to work here
|
|
94
|
-
.max_concurrent_wft_polls(
|
|
95
|
-
.max_concurrent_at_polls(
|
|
94
|
+
.max_concurrent_wft_polls(1_usize)
|
|
95
|
+
.max_concurrent_at_polls(1_usize)
|
|
96
96
|
.build()
|
|
97
97
|
.unwrap(),
|
|
98
98
|
)
|