@temporalio/core-bridge 1.8.4 → 1.8.5
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/package.json +3 -3
- 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/core/src/core_tests/local_activities.rs +142 -62
- package/sdk-core/core/src/core_tests/queries.rs +44 -104
- package/sdk-core/core/src/core_tests/replay_flag.rs +66 -12
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +1 -0
- package/sdk-core/core/src/worker/workflow/managed_run.rs +16 -38
- package/sdk-core/core/src/worker/workflow/mod.rs +57 -13
- package/sdk-core/test-utils/src/lib.rs +15 -2
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temporalio/core-bridge",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.5",
|
|
4
4
|
"description": "Temporal.io SDK Core<>Node bridge",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@opentelemetry/api": "^1.4.1",
|
|
26
|
-
"@temporalio/common": "1.8.
|
|
26
|
+
"@temporalio/common": "1.8.5",
|
|
27
27
|
"arg": "^5.0.2",
|
|
28
28
|
"cargo-cp-artifact": "^0.1.6",
|
|
29
29
|
"which": "^2.0.2"
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"publishConfig": {
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "1a03096ceb2d63345c3f2c190d975c2a54c7b4a5"
|
|
57
57
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3,7 +3,7 @@ use crate::{
|
|
|
3
3
|
replay::{default_wes_attribs, TestHistoryBuilder, DEFAULT_WORKFLOW_TYPE},
|
|
4
4
|
test_help::{
|
|
5
5
|
hist_to_poll_resp, mock_sdk, mock_sdk_cfg, mock_worker, single_hist_mock_sg, MockPollCfg,
|
|
6
|
-
ResponseType,
|
|
6
|
+
ResponseType, WorkerExt,
|
|
7
7
|
},
|
|
8
8
|
worker::{client::mocks::mock_workflow_client, LEGACY_QUERY_ID},
|
|
9
9
|
};
|
|
@@ -32,9 +32,7 @@ use temporal_sdk_core_protos::{
|
|
|
32
32
|
coresdk::{
|
|
33
33
|
activity_result::ActivityExecutionResult,
|
|
34
34
|
workflow_activation::{workflow_activation_job, WorkflowActivationJob},
|
|
35
|
-
workflow_commands::{
|
|
36
|
-
ActivityCancellationType, QueryResult, QuerySuccess, ScheduleLocalActivity,
|
|
37
|
-
},
|
|
35
|
+
workflow_commands::{ActivityCancellationType, ScheduleLocalActivity},
|
|
38
36
|
workflow_completion::WorkflowActivationCompletion,
|
|
39
37
|
ActivityTaskCompletion, AsJsonPayloadExt,
|
|
40
38
|
},
|
|
@@ -47,7 +45,7 @@ use temporal_sdk_core_protos::{
|
|
|
47
45
|
DEFAULT_ACTIVITY_TYPE,
|
|
48
46
|
};
|
|
49
47
|
use temporal_sdk_core_test_utils::{
|
|
50
|
-
schedule_local_activity_cmd, start_timer_cmd, WorkerTestHelpers,
|
|
48
|
+
query_ok, schedule_local_activity_cmd, start_timer_cmd, WorkerTestHelpers,
|
|
51
49
|
};
|
|
52
50
|
use tokio::{join, select, sync::Barrier};
|
|
53
51
|
|
|
@@ -527,16 +525,7 @@ async fn query_during_wft_heartbeat_doesnt_accidentally_fail_to_continue_heartbe
|
|
|
527
525
|
barrier.wait().await;
|
|
528
526
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
529
527
|
task.run_id,
|
|
530
|
-
|
|
531
|
-
query_id: query.query_id.clone(),
|
|
532
|
-
variant: Some(
|
|
533
|
-
QuerySuccess {
|
|
534
|
-
response: Some("whatever".into()),
|
|
535
|
-
}
|
|
536
|
-
.into(),
|
|
537
|
-
),
|
|
538
|
-
}
|
|
539
|
-
.into(),
|
|
528
|
+
query_ok(&query.query_id, "whatev"),
|
|
540
529
|
))
|
|
541
530
|
.await
|
|
542
531
|
.unwrap();
|
|
@@ -582,10 +571,8 @@ async fn la_resolve_during_legacy_query_does_not_combine(#[case] impossible_quer
|
|
|
582
571
|
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
583
572
|
|
|
584
573
|
// nonlegacy query got here & LA started here
|
|
574
|
+
// then next task is incremental w/ legacy query (for impossible query case)
|
|
585
575
|
t.add_full_wf_task();
|
|
586
|
-
// legacy query got here, at the same time that the LA is resolved
|
|
587
|
-
t.add_local_activity_result_marker(1, "1", "whatever".into());
|
|
588
|
-
t.add_workflow_execution_completed();
|
|
589
576
|
|
|
590
577
|
let barr = Arc::new(Barrier::new(2));
|
|
591
578
|
let barr_c = barr.clone();
|
|
@@ -612,9 +599,6 @@ async fn la_resolve_during_legacy_query_does_not_combine(#[case] impossible_quer
|
|
|
612
599
|
ResponseType::UntilResolved(
|
|
613
600
|
async move {
|
|
614
601
|
barr_c.wait().await;
|
|
615
|
-
// This sleep is the only not-incredibly-invasive way to ensure the LA
|
|
616
|
-
// resolves & updates machines before we process this task
|
|
617
|
-
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
618
602
|
}
|
|
619
603
|
.boxed(),
|
|
620
604
|
2,
|
|
@@ -662,42 +646,26 @@ async fn la_resolve_during_legacy_query_does_not_combine(#[case] impossible_quer
|
|
|
662
646
|
))
|
|
663
647
|
.await
|
|
664
648
|
.unwrap();
|
|
649
|
+
|
|
665
650
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
666
651
|
assert_matches!(
|
|
667
652
|
task.jobs.as_slice(),
|
|
668
|
-
&[
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
},
|
|
672
|
-
WorkflowActivationJob {
|
|
673
|
-
variant: Some(workflow_activation_job::Variant::QueryWorkflow(_)),
|
|
674
|
-
}
|
|
675
|
-
]
|
|
653
|
+
&[WorkflowActivationJob {
|
|
654
|
+
variant: Some(workflow_activation_job::Variant::FireTimer(_)),
|
|
655
|
+
},]
|
|
676
656
|
);
|
|
677
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::
|
|
657
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
678
658
|
task.run_id,
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
),
|
|
686
|
-
QueryResult {
|
|
687
|
-
query_id: "q1".to_string(),
|
|
688
|
-
variant: Some(
|
|
689
|
-
QuerySuccess {
|
|
690
|
-
response: Some("whatev".into()),
|
|
691
|
-
}
|
|
692
|
-
.into(),
|
|
693
|
-
),
|
|
694
|
-
}
|
|
695
|
-
.into(),
|
|
696
|
-
],
|
|
659
|
+
schedule_local_activity_cmd(
|
|
660
|
+
1,
|
|
661
|
+
"act-id",
|
|
662
|
+
ActivityCancellationType::TryCancel,
|
|
663
|
+
Duration::from_secs(60),
|
|
664
|
+
),
|
|
697
665
|
))
|
|
698
666
|
.await
|
|
699
667
|
.unwrap();
|
|
700
|
-
|
|
668
|
+
|
|
701
669
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
702
670
|
// The next task needs to be resolve, since the LA is completed immediately
|
|
703
671
|
assert_matches!(
|
|
@@ -708,21 +676,30 @@ async fn la_resolve_during_legacy_query_does_not_combine(#[case] impossible_quer
|
|
|
708
676
|
);
|
|
709
677
|
// Complete workflow
|
|
710
678
|
core.complete_execution(&task.run_id).await;
|
|
679
|
+
|
|
680
|
+
// Now we will get the query
|
|
681
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
682
|
+
assert_matches!(
|
|
683
|
+
task.jobs.as_slice(),
|
|
684
|
+
&[WorkflowActivationJob {
|
|
685
|
+
variant: Some(workflow_activation_job::Variant::QueryWorkflow(ref q)),
|
|
686
|
+
}]
|
|
687
|
+
if q.query_id == "q1"
|
|
688
|
+
);
|
|
689
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
690
|
+
task.run_id,
|
|
691
|
+
query_ok("q1", "whatev"),
|
|
692
|
+
))
|
|
693
|
+
.await
|
|
694
|
+
.unwrap();
|
|
695
|
+
barr.wait().await;
|
|
696
|
+
|
|
711
697
|
if impossible_query_in_task {
|
|
712
698
|
// finish last query
|
|
713
699
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
714
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::
|
|
700
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
715
701
|
task.run_id,
|
|
716
|
-
|
|
717
|
-
query_id: LEGACY_QUERY_ID.to_string(),
|
|
718
|
-
variant: Some(
|
|
719
|
-
QuerySuccess {
|
|
720
|
-
response: Some("whatev".into()),
|
|
721
|
-
}
|
|
722
|
-
.into(),
|
|
723
|
-
),
|
|
724
|
-
}
|
|
725
|
-
.into()],
|
|
702
|
+
query_ok(LEGACY_QUERY_ID, "whatev"),
|
|
726
703
|
))
|
|
727
704
|
.await
|
|
728
705
|
.unwrap();
|
|
@@ -738,8 +715,8 @@ async fn la_resolve_during_legacy_query_does_not_combine(#[case] impossible_quer
|
|
|
738
715
|
.unwrap();
|
|
739
716
|
};
|
|
740
717
|
|
|
741
|
-
|
|
742
|
-
core.
|
|
718
|
+
join!(wf_fut, act_fut);
|
|
719
|
+
core.drain_pollers_and_shutdown().await;
|
|
743
720
|
}
|
|
744
721
|
|
|
745
722
|
#[tokio::test]
|
|
@@ -1215,3 +1192,106 @@ async fn local_activities_can_be_delivered_during_shutdown() {
|
|
|
1215
1192
|
assert_matches!(wf_r.unwrap_err(), PollWfError::ShutDown);
|
|
1216
1193
|
assert_matches!(act_r.unwrap_err(), PollActivityError::ShutDown);
|
|
1217
1194
|
}
|
|
1195
|
+
|
|
1196
|
+
#[tokio::test]
|
|
1197
|
+
async fn queries_can_be_received_while_heartbeating() {
|
|
1198
|
+
let wfid = "fake_wf_id";
|
|
1199
|
+
let mut t = TestHistoryBuilder::default();
|
|
1200
|
+
t.add_wfe_started_with_wft_timeout(Duration::from_millis(200));
|
|
1201
|
+
t.add_full_wf_task();
|
|
1202
|
+
t.add_full_wf_task();
|
|
1203
|
+
t.add_full_wf_task();
|
|
1204
|
+
|
|
1205
|
+
let tasks = [
|
|
1206
|
+
hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::ToTaskNum(1)),
|
|
1207
|
+
{
|
|
1208
|
+
let mut pr = hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::OneTask(2));
|
|
1209
|
+
pr.queries = HashMap::new();
|
|
1210
|
+
pr.queries.insert(
|
|
1211
|
+
"q1".to_string(),
|
|
1212
|
+
WorkflowQuery {
|
|
1213
|
+
query_type: "query-type".to_string(),
|
|
1214
|
+
query_args: Some(b"hi".into()),
|
|
1215
|
+
header: None,
|
|
1216
|
+
},
|
|
1217
|
+
);
|
|
1218
|
+
pr
|
|
1219
|
+
},
|
|
1220
|
+
{
|
|
1221
|
+
let mut pr = hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::OneTask(3));
|
|
1222
|
+
pr.query = Some(WorkflowQuery {
|
|
1223
|
+
query_type: "query-type".to_string(),
|
|
1224
|
+
query_args: Some(b"hi".into()),
|
|
1225
|
+
header: None,
|
|
1226
|
+
});
|
|
1227
|
+
pr
|
|
1228
|
+
},
|
|
1229
|
+
];
|
|
1230
|
+
let mut mock = mock_workflow_client();
|
|
1231
|
+
mock.expect_respond_legacy_query()
|
|
1232
|
+
.times(1)
|
|
1233
|
+
.returning(move |_, _| Ok(Default::default()));
|
|
1234
|
+
let mut mock = single_hist_mock_sg(wfid, t, tasks, mock, true);
|
|
1235
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
|
|
1236
|
+
let core = mock_worker(mock);
|
|
1237
|
+
|
|
1238
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
1239
|
+
assert_matches!(
|
|
1240
|
+
task.jobs.as_slice(),
|
|
1241
|
+
&[WorkflowActivationJob {
|
|
1242
|
+
variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
|
|
1243
|
+
},]
|
|
1244
|
+
);
|
|
1245
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1246
|
+
task.run_id,
|
|
1247
|
+
schedule_local_activity_cmd(
|
|
1248
|
+
1,
|
|
1249
|
+
"act-id",
|
|
1250
|
+
ActivityCancellationType::TryCancel,
|
|
1251
|
+
Duration::from_secs(60),
|
|
1252
|
+
),
|
|
1253
|
+
))
|
|
1254
|
+
.await
|
|
1255
|
+
.unwrap();
|
|
1256
|
+
|
|
1257
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
1258
|
+
assert_matches!(
|
|
1259
|
+
task.jobs.as_slice(),
|
|
1260
|
+
&[WorkflowActivationJob {
|
|
1261
|
+
variant: Some(workflow_activation_job::Variant::QueryWorkflow(ref q)),
|
|
1262
|
+
}]
|
|
1263
|
+
if q.query_id == "q1"
|
|
1264
|
+
);
|
|
1265
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1266
|
+
task.run_id,
|
|
1267
|
+
query_ok("q1", "whatev"),
|
|
1268
|
+
))
|
|
1269
|
+
.await
|
|
1270
|
+
.unwrap();
|
|
1271
|
+
|
|
1272
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
1273
|
+
assert_matches!(
|
|
1274
|
+
task.jobs.as_slice(),
|
|
1275
|
+
&[WorkflowActivationJob {
|
|
1276
|
+
variant: Some(workflow_activation_job::Variant::QueryWorkflow(ref q)),
|
|
1277
|
+
}]
|
|
1278
|
+
if q.query_id == LEGACY_QUERY_ID
|
|
1279
|
+
);
|
|
1280
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1281
|
+
task.run_id,
|
|
1282
|
+
query_ok(LEGACY_QUERY_ID, "whatev"),
|
|
1283
|
+
))
|
|
1284
|
+
.await
|
|
1285
|
+
.unwrap();
|
|
1286
|
+
|
|
1287
|
+
// Handle the activity so we can shut down cleanly
|
|
1288
|
+
let act_task = core.poll_activity_task().await.unwrap();
|
|
1289
|
+
core.complete_activity_task(ActivityTaskCompletion {
|
|
1290
|
+
task_token: act_task.task_token,
|
|
1291
|
+
result: Some(ActivityExecutionResult::ok(vec![1].into())),
|
|
1292
|
+
})
|
|
1293
|
+
.await
|
|
1294
|
+
.unwrap();
|
|
1295
|
+
|
|
1296
|
+
core.drain_pollers_and_shutdown().await;
|
|
1297
|
+
}
|
|
@@ -17,7 +17,7 @@ use temporal_sdk_core_protos::{
|
|
|
17
17
|
},
|
|
18
18
|
workflow_commands::{
|
|
19
19
|
query_result, ActivityCancellationType, CompleteWorkflowExecution,
|
|
20
|
-
ContinueAsNewWorkflowExecution, QueryResult,
|
|
20
|
+
ContinueAsNewWorkflowExecution, QueryResult, RequestCancelActivity,
|
|
21
21
|
},
|
|
22
22
|
workflow_completion::WorkflowActivationCompletion,
|
|
23
23
|
},
|
|
@@ -33,7 +33,9 @@ use temporal_sdk_core_protos::{
|
|
|
33
33
|
},
|
|
34
34
|
TestHistoryBuilder,
|
|
35
35
|
};
|
|
36
|
-
use temporal_sdk_core_test_utils::{
|
|
36
|
+
use temporal_sdk_core_test_utils::{
|
|
37
|
+
query_ok, schedule_activity_cmd, start_timer_cmd, WorkerTestHelpers,
|
|
38
|
+
};
|
|
37
39
|
|
|
38
40
|
#[rstest::rstest]
|
|
39
41
|
#[case::with_history(true)]
|
|
@@ -111,16 +113,7 @@ async fn legacy_query(#[case] include_history: bool) {
|
|
|
111
113
|
worker
|
|
112
114
|
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
113
115
|
task.run_id,
|
|
114
|
-
|
|
115
|
-
query_id: query.query_id.clone(),
|
|
116
|
-
variant: Some(
|
|
117
|
-
QuerySuccess {
|
|
118
|
-
response: Some(query_resp.into()),
|
|
119
|
-
}
|
|
120
|
-
.into(),
|
|
121
|
-
),
|
|
122
|
-
}
|
|
123
|
-
.into(),
|
|
116
|
+
query_ok(&query.query_id, query_resp),
|
|
124
117
|
))
|
|
125
118
|
.await
|
|
126
119
|
.unwrap();
|
|
@@ -149,10 +142,7 @@ async fn legacy_query(#[case] include_history: bool) {
|
|
|
149
142
|
|
|
150
143
|
#[rstest::rstest]
|
|
151
144
|
#[tokio::test]
|
|
152
|
-
async fn new_queries(
|
|
153
|
-
#[values(1, 3)] num_queries: usize,
|
|
154
|
-
#[values(false, true)] query_results_after_complete: bool,
|
|
155
|
-
) {
|
|
145
|
+
async fn new_queries(#[values(1, 3)] num_queries: usize) {
|
|
156
146
|
let wfid = "fake_wf_id";
|
|
157
147
|
let query_resp = "response";
|
|
158
148
|
let t = canned_histories::single_timer("1");
|
|
@@ -200,12 +190,20 @@ async fn new_queries(
|
|
|
200
190
|
|
|
201
191
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
202
192
|
assert_matches!(
|
|
203
|
-
task.jobs
|
|
204
|
-
WorkflowActivationJob {
|
|
193
|
+
task.jobs.as_slice(),
|
|
194
|
+
&[WorkflowActivationJob {
|
|
205
195
|
variant: Some(workflow_activation_job::Variant::FireTimer(_)),
|
|
206
|
-
}
|
|
196
|
+
}]
|
|
207
197
|
);
|
|
208
|
-
|
|
198
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
199
|
+
task.run_id,
|
|
200
|
+
CompleteWorkflowExecution { result: None }.into(),
|
|
201
|
+
))
|
|
202
|
+
.await
|
|
203
|
+
.unwrap();
|
|
204
|
+
|
|
205
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
206
|
+
for i in 0..num_queries {
|
|
209
207
|
assert_matches!(
|
|
210
208
|
task.jobs[i],
|
|
211
209
|
WorkflowActivationJob {
|
|
@@ -217,25 +215,8 @@ async fn new_queries(
|
|
|
217
215
|
}
|
|
218
216
|
|
|
219
217
|
let mut commands = vec![];
|
|
220
|
-
if query_results_after_complete {
|
|
221
|
-
commands.push(CompleteWorkflowExecution { result: None }.into());
|
|
222
|
-
}
|
|
223
218
|
for i in 1..=num_queries {
|
|
224
|
-
commands.push(
|
|
225
|
-
QueryResult {
|
|
226
|
-
query_id: format!("q{i}"),
|
|
227
|
-
variant: Some(
|
|
228
|
-
QuerySuccess {
|
|
229
|
-
response: Some(query_resp.into()),
|
|
230
|
-
}
|
|
231
|
-
.into(),
|
|
232
|
-
),
|
|
233
|
-
}
|
|
234
|
-
.into(),
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
if !query_results_after_complete {
|
|
238
|
-
commands.push(CompleteWorkflowExecution { result: None }.into());
|
|
219
|
+
commands.push(query_ok(format!("q{i}"), query_resp));
|
|
239
220
|
}
|
|
240
221
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
241
222
|
task.run_id,
|
|
@@ -411,16 +392,7 @@ async fn legacy_query_after_complete(#[values(false, true)] full_history: bool)
|
|
|
411
392
|
);
|
|
412
393
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
413
394
|
task.run_id,
|
|
414
|
-
|
|
415
|
-
query_id: query.query_id.clone(),
|
|
416
|
-
variant: Some(
|
|
417
|
-
QuerySuccess {
|
|
418
|
-
response: Some("whatever".into()),
|
|
419
|
-
}
|
|
420
|
-
.into(),
|
|
421
|
-
),
|
|
422
|
-
}
|
|
423
|
-
.into(),
|
|
395
|
+
query_ok(query.query_id.clone(), "whatever"),
|
|
424
396
|
))
|
|
425
397
|
.await
|
|
426
398
|
.unwrap();
|
|
@@ -534,16 +506,7 @@ async fn query_cache_miss_causes_page_fetch_dont_reply_wft_too_early(
|
|
|
534
506
|
);
|
|
535
507
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
536
508
|
task.run_id,
|
|
537
|
-
|
|
538
|
-
query_id: "the-query".to_string(),
|
|
539
|
-
variant: Some(
|
|
540
|
-
QuerySuccess {
|
|
541
|
-
response: Some(query_resp.into()),
|
|
542
|
-
}
|
|
543
|
-
.into(),
|
|
544
|
-
),
|
|
545
|
-
}
|
|
546
|
-
.into(),
|
|
509
|
+
query_ok("the-query".to_string(), query_resp),
|
|
547
510
|
))
|
|
548
511
|
.await
|
|
549
512
|
.unwrap();
|
|
@@ -632,16 +595,7 @@ async fn query_replay_with_continue_as_new_doesnt_reply_empty_command() {
|
|
|
632
595
|
|
|
633
596
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
634
597
|
task.run_id,
|
|
635
|
-
|
|
636
|
-
query_id: query.query_id.clone(),
|
|
637
|
-
variant: Some(
|
|
638
|
-
QuerySuccess {
|
|
639
|
-
response: Some("whatever".into()),
|
|
640
|
-
}
|
|
641
|
-
.into(),
|
|
642
|
-
),
|
|
643
|
-
}
|
|
644
|
-
.into(),
|
|
598
|
+
query_ok(query.query_id.clone(), "whatever"),
|
|
645
599
|
))
|
|
646
600
|
.await
|
|
647
601
|
.unwrap();
|
|
@@ -690,16 +644,7 @@ async fn legacy_query_response_gets_not_found_not_fatal() {
|
|
|
690
644
|
// Fail wft which should result in query being failed
|
|
691
645
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
692
646
|
task.run_id,
|
|
693
|
-
|
|
694
|
-
query_id: LEGACY_QUERY_ID.to_string(),
|
|
695
|
-
variant: Some(
|
|
696
|
-
QuerySuccess {
|
|
697
|
-
response: Some("hi".into()),
|
|
698
|
-
}
|
|
699
|
-
.into(),
|
|
700
|
-
),
|
|
701
|
-
}
|
|
702
|
-
.into(),
|
|
647
|
+
query_ok(LEGACY_QUERY_ID.to_string(), "hi"),
|
|
703
648
|
))
|
|
704
649
|
.await
|
|
705
650
|
.unwrap();
|
|
@@ -856,21 +801,9 @@ async fn legacy_query_combined_with_timer_fire_repro() {
|
|
|
856
801
|
.unwrap();
|
|
857
802
|
|
|
858
803
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
859
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::
|
|
804
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
860
805
|
task.run_id,
|
|
861
|
-
|
|
862
|
-
RequestCancelActivity { seq: 1 }.into(),
|
|
863
|
-
QueryResult {
|
|
864
|
-
query_id: "the-query".to_string(),
|
|
865
|
-
variant: Some(
|
|
866
|
-
QuerySuccess {
|
|
867
|
-
response: Some("whatever".into()),
|
|
868
|
-
}
|
|
869
|
-
.into(),
|
|
870
|
-
),
|
|
871
|
-
}
|
|
872
|
-
.into(),
|
|
873
|
-
],
|
|
806
|
+
RequestCancelActivity { seq: 1 }.into(),
|
|
874
807
|
))
|
|
875
808
|
.await
|
|
876
809
|
.unwrap();
|
|
@@ -885,26 +818,33 @@ async fn legacy_query_combined_with_timer_fire_repro() {
|
|
|
885
818
|
);
|
|
886
819
|
core.complete_execution(&task.run_id).await;
|
|
887
820
|
|
|
888
|
-
// Then the
|
|
821
|
+
// Then the queries
|
|
889
822
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
890
823
|
assert_matches!(
|
|
891
824
|
task.jobs.as_slice(),
|
|
892
825
|
[WorkflowActivationJob {
|
|
893
|
-
variant: Some(workflow_activation_job::Variant::QueryWorkflow(
|
|
826
|
+
variant: Some(workflow_activation_job::Variant::QueryWorkflow(ref q)),
|
|
894
827
|
}]
|
|
828
|
+
if q.query_id == "the-query"
|
|
895
829
|
);
|
|
896
830
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
897
831
|
task.run_id,
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
832
|
+
query_ok("the-query".to_string(), "whatever"),
|
|
833
|
+
))
|
|
834
|
+
.await
|
|
835
|
+
.unwrap();
|
|
836
|
+
|
|
837
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
838
|
+
assert_matches!(
|
|
839
|
+
task.jobs.as_slice(),
|
|
840
|
+
[WorkflowActivationJob {
|
|
841
|
+
variant: Some(workflow_activation_job::Variant::QueryWorkflow(ref q)),
|
|
842
|
+
}]
|
|
843
|
+
if q.query_id == LEGACY_QUERY_ID
|
|
844
|
+
);
|
|
845
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
846
|
+
task.run_id,
|
|
847
|
+
query_ok(LEGACY_QUERY_ID.to_string(), "whatever"),
|
|
908
848
|
))
|
|
909
849
|
.await
|
|
910
850
|
.unwrap();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
use crate::{
|
|
2
2
|
test_help::{
|
|
3
3
|
build_mock_pollers, canned_histories, hist_to_poll_resp, mock_worker, MockPollCfg,
|
|
4
|
+
ResponseType,
|
|
4
5
|
},
|
|
5
6
|
worker::{client::mocks::mock_workflow_client, ManagedWFFunc, LEGACY_QUERY_ID},
|
|
6
7
|
};
|
|
@@ -10,12 +11,16 @@ use temporal_sdk::{WfContext, WorkflowFunction};
|
|
|
10
11
|
use temporal_sdk_core_api::Worker;
|
|
11
12
|
use temporal_sdk_core_protos::{
|
|
12
13
|
coresdk::{
|
|
13
|
-
|
|
14
|
+
workflow_activation::{workflow_activation_job, WorkflowActivationJob},
|
|
14
15
|
workflow_completion::WorkflowActivationCompletion,
|
|
15
16
|
},
|
|
16
|
-
temporal::api::{
|
|
17
|
+
temporal::api::{
|
|
18
|
+
enums::v1::{CommandType, EventType},
|
|
19
|
+
query::v1::WorkflowQuery,
|
|
20
|
+
},
|
|
21
|
+
TestHistoryBuilder,
|
|
17
22
|
};
|
|
18
|
-
use temporal_sdk_core_test_utils::start_timer_cmd;
|
|
23
|
+
use temporal_sdk_core_test_utils::{query_ok, start_timer_cmd};
|
|
19
24
|
|
|
20
25
|
fn timers_wf(num_timers: u32) -> WorkflowFunction {
|
|
21
26
|
WorkflowFunction::new(move |command_sink: WfContext| async move {
|
|
@@ -117,15 +122,7 @@ async fn replay_flag_correct_with_query() {
|
|
|
117
122
|
assert!(task.is_replaying);
|
|
118
123
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
119
124
|
task.run_id,
|
|
120
|
-
|
|
121
|
-
query_id: LEGACY_QUERY_ID.to_string(),
|
|
122
|
-
variant: Some(
|
|
123
|
-
QuerySuccess {
|
|
124
|
-
response: Some("hi".into()),
|
|
125
|
-
}
|
|
126
|
-
.into(),
|
|
127
|
-
),
|
|
128
|
-
}),
|
|
125
|
+
query_ok(LEGACY_QUERY_ID, "hi"),
|
|
129
126
|
))
|
|
130
127
|
.await
|
|
131
128
|
.unwrap();
|
|
@@ -133,3 +130,60 @@ async fn replay_flag_correct_with_query() {
|
|
|
133
130
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
134
131
|
assert!(!task.is_replaying);
|
|
135
132
|
}
|
|
133
|
+
|
|
134
|
+
#[tokio::test]
|
|
135
|
+
async fn replay_flag_correct_signal_before_query_ending_on_wft_completed() {
|
|
136
|
+
let wfid = "fake_wf_id";
|
|
137
|
+
let mut t = TestHistoryBuilder::default();
|
|
138
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
139
|
+
t.add_full_wf_task();
|
|
140
|
+
t.add_we_signaled("signal", vec![]);
|
|
141
|
+
t.add_full_wf_task();
|
|
142
|
+
let task = {
|
|
143
|
+
let mut pr = hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::AllHistory);
|
|
144
|
+
pr.query = Some(WorkflowQuery {
|
|
145
|
+
query_type: "query-type".to_string(),
|
|
146
|
+
query_args: Some(b"hi".into()),
|
|
147
|
+
header: None,
|
|
148
|
+
});
|
|
149
|
+
pr
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
let mut mock = MockPollCfg::from_resp_batches(wfid, t, [task], mock_workflow_client());
|
|
153
|
+
mock.num_expected_legacy_query_resps = 1;
|
|
154
|
+
let mut mock = build_mock_pollers(mock);
|
|
155
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
|
|
156
|
+
let core = mock_worker(mock);
|
|
157
|
+
|
|
158
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
159
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
|
|
160
|
+
.await
|
|
161
|
+
.unwrap();
|
|
162
|
+
|
|
163
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
164
|
+
assert!(task.is_replaying);
|
|
165
|
+
assert_matches!(
|
|
166
|
+
task.jobs.as_slice(),
|
|
167
|
+
[WorkflowActivationJob {
|
|
168
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
|
169
|
+
}]
|
|
170
|
+
);
|
|
171
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
|
|
172
|
+
.await
|
|
173
|
+
.unwrap();
|
|
174
|
+
|
|
175
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
176
|
+
assert!(task.is_replaying);
|
|
177
|
+
assert_matches!(
|
|
178
|
+
task.jobs.as_slice(),
|
|
179
|
+
[WorkflowActivationJob {
|
|
180
|
+
variant: Some(workflow_activation_job::Variant::QueryWorkflow(_)),
|
|
181
|
+
}]
|
|
182
|
+
);
|
|
183
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
184
|
+
task.run_id,
|
|
185
|
+
query_ok(LEGACY_QUERY_ID, "hi"),
|
|
186
|
+
))
|
|
187
|
+
.await
|
|
188
|
+
.unwrap();
|
|
189
|
+
}
|
|
@@ -520,6 +520,7 @@ impl WorkflowMachines {
|
|
|
520
520
|
// them.
|
|
521
521
|
if self.replaying
|
|
522
522
|
&& has_final_event
|
|
523
|
+
&& event.event_id > self.last_history_from_server.previous_wft_started_id
|
|
523
524
|
&& event.event_type() != EventType::WorkflowTaskCompleted
|
|
524
525
|
&& !event.is_command_event()
|
|
525
526
|
{
|
|
@@ -148,7 +148,7 @@ impl ManagedRun {
|
|
|
148
148
|
/// Called whenever a new workflow task is obtained for this run
|
|
149
149
|
pub(super) fn incoming_wft(&mut self, pwft: PermittedWFT) -> RunUpdateAct {
|
|
150
150
|
let res = self._incoming_wft(pwft);
|
|
151
|
-
self.update_to_acts(res.map(Into::into)
|
|
151
|
+
self.update_to_acts(res.map(Into::into))
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
fn _incoming_wft(
|
|
@@ -161,7 +161,6 @@ impl ManagedRun {
|
|
|
161
161
|
let start_time = Instant::now();
|
|
162
162
|
|
|
163
163
|
let work = pwft.work;
|
|
164
|
-
let did_miss_cache = !work.is_incremental() || !work.update.is_real();
|
|
165
164
|
debug!(
|
|
166
165
|
run_id = %work.execution.run_id,
|
|
167
166
|
task_token = %&work.task_token,
|
|
@@ -200,7 +199,6 @@ impl ManagedRun {
|
|
|
200
199
|
self.paginator = Some(pwft.paginator);
|
|
201
200
|
self.wft = Some(OutstandingTask {
|
|
202
201
|
info: wft_info,
|
|
203
|
-
hit_cache: !did_miss_cache,
|
|
204
202
|
pending_queries,
|
|
205
203
|
start_time,
|
|
206
204
|
permit: pwft.permit,
|
|
@@ -284,7 +282,7 @@ impl ManagedRun {
|
|
|
284
282
|
/// Checks if any further activations need to go out for this run and produces them if so.
|
|
285
283
|
pub(super) fn check_more_activations(&mut self) -> RunUpdateAct {
|
|
286
284
|
let res = self._check_more_activations();
|
|
287
|
-
self.update_to_acts(res.map(Into::into)
|
|
285
|
+
self.update_to_acts(res.map(Into::into))
|
|
288
286
|
}
|
|
289
287
|
|
|
290
288
|
fn _check_more_activations(&mut self) -> Result<Option<ActivationOrAuto>, RunUpdateErr> {
|
|
@@ -445,17 +443,14 @@ impl ManagedRun {
|
|
|
445
443
|
span: Span::current(),
|
|
446
444
|
})
|
|
447
445
|
} else {
|
|
448
|
-
Ok(self.update_to_acts(
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
"Run's paginator was absent when attempting to fetch next history \
|
|
446
|
+
Ok(self.update_to_acts(Err(RunUpdateErr {
|
|
447
|
+
source: WFMachinesError::Fatal(
|
|
448
|
+
"Run's paginator was absent when attempting to fetch next history \
|
|
452
449
|
page. This is a Core SDK bug."
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
false,
|
|
458
|
-
))
|
|
450
|
+
.to_string(),
|
|
451
|
+
),
|
|
452
|
+
complete_resp_chan: rac.resp_chan,
|
|
453
|
+
})))
|
|
459
454
|
};
|
|
460
455
|
}
|
|
461
456
|
|
|
@@ -473,7 +468,7 @@ impl ManagedRun {
|
|
|
473
468
|
paginator: HistoryPaginator,
|
|
474
469
|
) -> RunUpdateAct {
|
|
475
470
|
let res = self._fetched_page_completion(update, paginator);
|
|
476
|
-
self.update_to_acts(res.map(Into::into)
|
|
471
|
+
self.update_to_acts(res.map(Into::into))
|
|
477
472
|
}
|
|
478
473
|
fn _fetched_page_completion(
|
|
479
474
|
&mut self,
|
|
@@ -564,12 +559,12 @@ impl ManagedRun {
|
|
|
564
559
|
/// Called when local activities resolve
|
|
565
560
|
pub(super) fn local_resolution(&mut self, res: LocalResolution) -> RunUpdateAct {
|
|
566
561
|
let res = self._local_resolution(res);
|
|
567
|
-
self.update_to_acts(res.map(Into::into)
|
|
562
|
+
self.update_to_acts(res.map(Into::into))
|
|
568
563
|
}
|
|
569
564
|
|
|
570
565
|
fn process_completion(&mut self, completion: RunActivationCompletion) -> RunUpdateAct {
|
|
571
566
|
let res = self._process_completion(completion, None);
|
|
572
|
-
self.update_to_acts(res.map(Into::into)
|
|
567
|
+
self.update_to_acts(res.map(Into::into))
|
|
573
568
|
}
|
|
574
569
|
|
|
575
570
|
fn _process_completion(
|
|
@@ -688,7 +683,7 @@ impl ManagedRun {
|
|
|
688
683
|
} else {
|
|
689
684
|
None
|
|
690
685
|
};
|
|
691
|
-
self.update_to_acts(Ok(maybe_act).map(Into::into)
|
|
686
|
+
self.update_to_acts(Ok(maybe_act).map(Into::into))
|
|
692
687
|
}
|
|
693
688
|
/// Returns `true` if autocompletion should be issued, which will actually cause us to end up
|
|
694
689
|
/// in [completion] again, at which point we'll start a new heartbeat timeout, which will
|
|
@@ -812,11 +807,7 @@ impl ManagedRun {
|
|
|
812
807
|
|
|
813
808
|
/// Take the result of some update to ourselves and turn it into a return value of zero or more
|
|
814
809
|
/// actions
|
|
815
|
-
fn update_to_acts(
|
|
816
|
-
&mut self,
|
|
817
|
-
outcome: Result<ActOrFulfill, RunUpdateErr>,
|
|
818
|
-
in_response_to_wft: bool,
|
|
819
|
-
) -> RunUpdateAct {
|
|
810
|
+
fn update_to_acts(&mut self, outcome: Result<ActOrFulfill, RunUpdateErr>) -> RunUpdateAct {
|
|
820
811
|
match outcome {
|
|
821
812
|
Ok(act_or_fulfill) => {
|
|
822
813
|
let (mut maybe_act, maybe_fulfill) = match act_or_fulfill {
|
|
@@ -828,25 +819,12 @@ impl ManagedRun {
|
|
|
828
819
|
match self._check_more_activations() {
|
|
829
820
|
Ok(oa) => maybe_act = oa,
|
|
830
821
|
Err(e) => {
|
|
831
|
-
return self.update_to_acts(Err(e)
|
|
822
|
+
return self.update_to_acts(Err(e));
|
|
832
823
|
}
|
|
833
824
|
}
|
|
834
825
|
}
|
|
835
826
|
let r = match maybe_act {
|
|
836
|
-
Some(ActivationOrAuto::LangActivation(
|
|
837
|
-
if in_response_to_wft {
|
|
838
|
-
let wft = self
|
|
839
|
-
.wft
|
|
840
|
-
.as_mut()
|
|
841
|
-
.expect("WFT must exist for run just updated with one");
|
|
842
|
-
// If there are in-poll queries, insert jobs for those queries into the
|
|
843
|
-
// activation, but only if we hit the cache. If we didn't, those queries
|
|
844
|
-
// will need to be dealt with once replay is over
|
|
845
|
-
if wft.hit_cache {
|
|
846
|
-
put_queries_in_act(&mut activation, wft);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
|
|
827
|
+
Some(ActivationOrAuto::LangActivation(activation)) => {
|
|
850
828
|
if activation.jobs.is_empty() {
|
|
851
829
|
dbg_panic!("Should not send lang activation with no jobs");
|
|
852
830
|
}
|
|
@@ -270,7 +270,7 @@ impl Workflows {
|
|
|
270
270
|
match al {
|
|
271
271
|
ActivationOrAuto::LangActivation(mut act)
|
|
272
272
|
| ActivationOrAuto::ReadyForQueries(mut act) => {
|
|
273
|
-
|
|
273
|
+
prepare_to_ship_activation(&mut act);
|
|
274
274
|
debug!(activation=%act, "Sending activation to lang");
|
|
275
275
|
break Ok(act);
|
|
276
276
|
}
|
|
@@ -527,7 +527,10 @@ impl Workflows {
|
|
|
527
527
|
r
|
|
528
528
|
})
|
|
529
529
|
);
|
|
530
|
-
jh_res?.map_err(|e|
|
|
530
|
+
jh_res?.map_err(|e| {
|
|
531
|
+
let as_str = e.downcast::<&str>();
|
|
532
|
+
anyhow!("Error joining workflow processing thread: {as_str:?}")
|
|
533
|
+
})?;
|
|
531
534
|
}
|
|
532
535
|
Ok(())
|
|
533
536
|
}
|
|
@@ -795,7 +798,6 @@ impl PreparedWFT {
|
|
|
795
798
|
#[derive(Debug)]
|
|
796
799
|
pub(crate) struct OutstandingTask {
|
|
797
800
|
pub info: WorkflowTaskInfo,
|
|
798
|
-
pub hit_cache: bool,
|
|
799
801
|
/// Set if the outstanding task has quer(ies) which must be fulfilled upon finishing replay
|
|
800
802
|
pub pending_queries: Vec<QueryWorkflow>,
|
|
801
803
|
pub start_time: Instant,
|
|
@@ -1334,9 +1336,33 @@ impl LocalActivityRequestSink for LAReqSink {
|
|
|
1334
1336
|
}
|
|
1335
1337
|
}
|
|
1336
1338
|
|
|
1337
|
-
/// Sorts jobs in an activation to be in the order lang expects
|
|
1338
|
-
///
|
|
1339
|
-
|
|
1339
|
+
/// Sorts jobs in an activation to be in the order lang expects, and confirms any invariants
|
|
1340
|
+
/// activations must uphold.
|
|
1341
|
+
///
|
|
1342
|
+
/// ## Ordering
|
|
1343
|
+
/// `patches -> signals -> other -X-> queries`
|
|
1344
|
+
///
|
|
1345
|
+
/// ## Invariants:
|
|
1346
|
+
/// * Queries always go in their own activation
|
|
1347
|
+
fn prepare_to_ship_activation(wfa: &mut WorkflowActivation) {
|
|
1348
|
+
let any_job_is_query = wfa.jobs.iter().any(|j| {
|
|
1349
|
+
matches!(
|
|
1350
|
+
j.variant,
|
|
1351
|
+
Some(workflow_activation_job::Variant::QueryWorkflow(_))
|
|
1352
|
+
)
|
|
1353
|
+
});
|
|
1354
|
+
let all_jobs_are_query = wfa.jobs.iter().all(|j| {
|
|
1355
|
+
matches!(
|
|
1356
|
+
j.variant,
|
|
1357
|
+
Some(workflow_activation_job::Variant::QueryWorkflow(_))
|
|
1358
|
+
)
|
|
1359
|
+
});
|
|
1360
|
+
if any_job_is_query && !all_jobs_are_query {
|
|
1361
|
+
dbg_panic!(
|
|
1362
|
+
"About to issue an activation that contains query jobs with non-query jobs: {:?}",
|
|
1363
|
+
&wfa
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1340
1366
|
wfa.jobs.sort_by(|j1, j2| {
|
|
1341
1367
|
// Unwrapping is fine here since we'll never issue empty variants
|
|
1342
1368
|
let j1v = j1.variant.as_ref().unwrap();
|
|
@@ -1348,6 +1374,9 @@ fn sort_act_jobs(wfa: &mut WorkflowActivation) {
|
|
|
1348
1374
|
match v {
|
|
1349
1375
|
workflow_activation_job::Variant::NotifyHasPatch(_) => 1,
|
|
1350
1376
|
workflow_activation_job::Variant::SignalWorkflow(_) => 2,
|
|
1377
|
+
// In principle we should never actually need to sort these with the others, since
|
|
1378
|
+
// queries always get their own activation, but, maintaining the semantic is
|
|
1379
|
+
// reasonable.
|
|
1351
1380
|
workflow_activation_job::Variant::QueryWorkflow(_) => 4,
|
|
1352
1381
|
_ => 3,
|
|
1353
1382
|
}
|
|
@@ -1375,11 +1404,6 @@ mod tests {
|
|
|
1375
1404
|
Default::default(),
|
|
1376
1405
|
)),
|
|
1377
1406
|
},
|
|
1378
|
-
WorkflowActivationJob {
|
|
1379
|
-
variant: Some(workflow_activation_job::Variant::QueryWorkflow(
|
|
1380
|
-
Default::default(),
|
|
1381
|
-
)),
|
|
1382
|
-
},
|
|
1383
1407
|
WorkflowActivationJob {
|
|
1384
1408
|
variant: Some(workflow_activation_job::Variant::FireTimer(
|
|
1385
1409
|
Default::default(),
|
|
@@ -1393,7 +1417,7 @@ mod tests {
|
|
|
1393
1417
|
],
|
|
1394
1418
|
..Default::default()
|
|
1395
1419
|
};
|
|
1396
|
-
|
|
1420
|
+
prepare_to_ship_activation(&mut act);
|
|
1397
1421
|
let variants = act
|
|
1398
1422
|
.jobs
|
|
1399
1423
|
.into_iter()
|
|
@@ -1406,8 +1430,28 @@ mod tests {
|
|
|
1406
1430
|
workflow_activation_job::Variant::SignalWorkflow(_),
|
|
1407
1431
|
workflow_activation_job::Variant::FireTimer(_),
|
|
1408
1432
|
workflow_activation_job::Variant::ResolveActivity(_),
|
|
1409
|
-
workflow_activation_job::Variant::QueryWorkflow(_)
|
|
1410
1433
|
]
|
|
1411
1434
|
)
|
|
1412
1435
|
}
|
|
1436
|
+
|
|
1437
|
+
#[test]
|
|
1438
|
+
#[should_panic]
|
|
1439
|
+
fn queries_cannot_go_with_other_jobs() {
|
|
1440
|
+
let mut act = WorkflowActivation {
|
|
1441
|
+
jobs: vec![
|
|
1442
|
+
WorkflowActivationJob {
|
|
1443
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(
|
|
1444
|
+
Default::default(),
|
|
1445
|
+
)),
|
|
1446
|
+
},
|
|
1447
|
+
WorkflowActivationJob {
|
|
1448
|
+
variant: Some(workflow_activation_job::Variant::QueryWorkflow(
|
|
1449
|
+
Default::default(),
|
|
1450
|
+
)),
|
|
1451
|
+
},
|
|
1452
|
+
],
|
|
1453
|
+
..Default::default()
|
|
1454
|
+
};
|
|
1455
|
+
prepare_to_ship_activation(&mut act);
|
|
1456
|
+
}
|
|
1413
1457
|
}
|
|
@@ -46,8 +46,8 @@ use temporal_sdk_core_api::{
|
|
|
46
46
|
use temporal_sdk_core_protos::{
|
|
47
47
|
coresdk::{
|
|
48
48
|
workflow_commands::{
|
|
49
|
-
workflow_command, ActivityCancellationType, CompleteWorkflowExecution,
|
|
50
|
-
ScheduleActivity, ScheduleLocalActivity, StartTimer,
|
|
49
|
+
workflow_command, ActivityCancellationType, CompleteWorkflowExecution, QueryResult,
|
|
50
|
+
QuerySuccess, ScheduleActivity, ScheduleLocalActivity, StartTimer,
|
|
51
51
|
},
|
|
52
52
|
workflow_completion::WorkflowActivationCompletion,
|
|
53
53
|
},
|
|
@@ -669,6 +669,19 @@ pub fn start_timer_cmd(seq: u32, duration: Duration) -> workflow_command::Varian
|
|
|
669
669
|
.into()
|
|
670
670
|
}
|
|
671
671
|
|
|
672
|
+
pub fn query_ok(id: impl Into<String>, response: impl Into<Payload>) -> workflow_command::Variant {
|
|
673
|
+
QueryResult {
|
|
674
|
+
query_id: id.into(),
|
|
675
|
+
variant: Some(
|
|
676
|
+
QuerySuccess {
|
|
677
|
+
response: Some(response.into()),
|
|
678
|
+
}
|
|
679
|
+
.into(),
|
|
680
|
+
),
|
|
681
|
+
}
|
|
682
|
+
.into()
|
|
683
|
+
}
|
|
684
|
+
|
|
672
685
|
/// Given a desired number of concurrent executions and a provided function that produces a future,
|
|
673
686
|
/// run that many instances of the future concurrently.
|
|
674
687
|
///
|
|
@@ -22,8 +22,7 @@ use temporal_sdk_core_protos::{
|
|
|
22
22
|
TestHistoryBuilder,
|
|
23
23
|
};
|
|
24
24
|
use temporal_sdk_core_test_utils::{
|
|
25
|
-
history_from_proto_binary,
|
|
26
|
-
CoreWfStarter,
|
|
25
|
+
history_from_proto_binary, replay_sdk_worker, workflows::la_problem_workflow, CoreWfStarter,
|
|
27
26
|
};
|
|
28
27
|
use tokio_util::sync::CancellationToken;
|
|
29
28
|
|
|
@@ -589,7 +588,6 @@ async fn repro_nondeterminism_with_timer_bug() {
|
|
|
589
588
|
#[rstest::rstest]
|
|
590
589
|
#[tokio::test]
|
|
591
590
|
async fn weird_la_nondeterminism_repro(#[values(true, false)] fix_hist: bool) {
|
|
592
|
-
init_integ_telem();
|
|
593
591
|
let mut hist = history_from_proto_binary(
|
|
594
592
|
"histories/evict_while_la_running_no_interference-85_history.bin",
|
|
595
593
|
)
|
|
@@ -618,7 +616,6 @@ async fn weird_la_nondeterminism_repro(#[values(true, false)] fix_hist: bool) {
|
|
|
618
616
|
|
|
619
617
|
#[tokio::test]
|
|
620
618
|
async fn second_weird_la_nondeterminism_repro() {
|
|
621
|
-
init_integ_telem();
|
|
622
619
|
let mut hist = history_from_proto_binary(
|
|
623
620
|
"histories/evict_while_la_running_no_interference-23_history.bin",
|
|
624
621
|
)
|
|
@@ -644,7 +641,6 @@ async fn second_weird_la_nondeterminism_repro() {
|
|
|
644
641
|
|
|
645
642
|
#[tokio::test]
|
|
646
643
|
async fn third_weird_la_nondeterminism_repro() {
|
|
647
|
-
init_integ_telem();
|
|
648
644
|
let mut hist = history_from_proto_binary(
|
|
649
645
|
"histories/evict_while_la_running_no_interference-16_history.bin",
|
|
650
646
|
)
|