Skip to content

Commit 6bfc8ce

Browse files
committed
Working
Move test utils from the Common crate to sdk-core crate
1 parent 64cb6ed commit 6bfc8ce

47 files changed

Lines changed: 1939 additions & 415 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

arch_docs/workflow_task_chunking.md

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ One source of complexity in Core is the chunking of history into "logical" Workf
44

55
Workflow tasks (WFTs) always take the following form in event history:
66

7-
* \[Preceding Events\] (optional)
8-
* WFT Scheduled
9-
* WFT Started
10-
* WFT Completed
11-
* \[Commands\] (optional)
7+
- \[Preceding Events\] (optional)
8+
- WFT Scheduled
9+
- WFT Started
10+
- WFT Completed
11+
- \[Commands\] (optional)
1212

1313
In the typical case, the "logical" WFT consists of all the commands from the last workflow task,
1414
any events generated in the interrim, and the scheduled/started preamble. So:
1515

16-
* WFT Completed
17-
* \[Commands\] (optional)
18-
* \[Events\] (optional)
19-
* WFT Scheduled
20-
* WFT Started
16+
- WFT Completed
17+
- \[Commands\] (optional)
18+
- \[Events\] (optional)
19+
- WFT Scheduled
20+
- WFT Started
2121

2222
Commands and events are both "optional" in the sense that:
2323

@@ -32,8 +32,22 @@ There may be no events for more nuanced reasons:
3232
rather as a "protocol message" attached to the task.
3333
3. Server can forcibly generate a new WFT with some obscure APIs
3434

35-
Core does not consider such empty WFT sequences as worthy of waking lang (on replay - as a new
36-
task, they always will), since nothing meaningful has happened. Thus, they are grouped together
35+
## Handling of empty WFTs (March 2026)
36+
37+
Until now, Core would try to avoid waking lang when replaying empty WFT sequences (i.e. a WFT
38+
Completed immediately followed by a WFT Scheduled and WFT Started, with no commands and no events
39+
in-between), since they would presumably be no-ops and therefore waste execution resources. Instead,
40+
the second WFT (and potentially subsequent WFTs) would be collapsed into the first, resulting in a
41+
single WFT that has the inbound events and start time of the first WFT, but the resulting commands
42+
of the last WFT in the collapsed sequence.
43+
44+
It was found that there are some particular edge cases where WFT collapsing might result in
45+
incorrect replay behavior. One particular example of this is the case where an update request would
46+
be sent after an empty WFT. This led to the development of some heuristics to avoid incorrect
47+
chunking in presence of known problematic patterns. Unfortunately, it has been found that these
48+
heuristics may
49+
50+
Thus, they are grouped together task, they always will), since nothing meaningful has happened. Thus, they are grouped together
3751
as part of a "logical" WFT with the last WFT that had any real work in it.
3852

3953
## Possible issues as of this writing (5/25)
@@ -44,8 +58,8 @@ NDE.
4458

4559
### Possible solutions
4660

47-
* Core can attach a flag on WFT completes in order to be explicit that that WFT may be skipped on
61+
- Core can attach a flag on WFT completes in order to be explicit that that WFT may be skipped on
4862
replay. IE: During WFT heartbeating for LAs.
49-
* We could legislate that server should never send empty WFTs. Seemingly the only case of this
63+
- We could legislate that server should never send empty WFTs. Seemingly the only case of this
5064
is
5165
the [obscure api](https://github.com/temporalio/temporal/blob/d189737aa2ed1b07c221abb9fbdd28ecf68f0492/proto/internal/temporal/server/api/adminservice/v1/service.proto#L151)

crates/common/Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ exclude = ["protos/*/.github/*"]
1414
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1515

1616
[features]
17-
history_builders = ["rand"]
1817
otel = ["dep:opentelemetry", "dep:opentelemetry_sdk", "dep:opentelemetry-otlp"]
1918
prometheus = [
2019
"dep:prometheus",
@@ -25,7 +24,6 @@ prometheus = [
2524
]
2625
envconfig = ["dep:toml", "dep:dirs"]
2726
serde_serialize = []
28-
test-utilities = ["history_builders"]
2927
core-based-sdk = [
3028
"prometheus",
3129
"envconfig",
@@ -41,6 +39,7 @@ bon = { workspace = true }
4139
crc32fast = "1"
4240
dirs = { version = "6.0", optional = true }
4341
derive_more = { workspace = true }
42+
enum-iterator = "2"
4443
erased-serde = "0.4"
4544
futures = { version = "0.3", default-features = false, features = ["alloc"] }
4645
futures-channel = { version = "0.3", default-features = false, features = [
@@ -74,7 +73,6 @@ prometheus = { version = "0.14", optional = true, default-features = false }
7473
prost = { workspace = true }
7574
prost-wkt = "0.7"
7675
prost-types = { workspace = true }
77-
rand = { version = "0.10", optional = true }
7876
ringbuf = { version = "0.4", optional = true }
7977
serde = { version = "1.0", features = ["derive"] }
8078
serde_json = { workspace = true }

crates/common/src/protos/mod.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,10 @@ pub mod constants;
66
/// Utility functions for working with protobuf types.
77
pub mod utilities;
88

9-
#[cfg(feature = "test-utilities")]
10-
/// Pre-built test histories for common workflow patterns.
11-
pub mod canned_histories;
12-
#[cfg(feature = "history_builders")]
13-
mod history_builder;
14-
#[cfg(feature = "history_builders")]
15-
mod history_info;
169
mod task_token;
17-
#[cfg(feature = "test-utilities")]
18-
pub mod test_utils;
1910

2011
use std::time::Duration;
2112

22-
#[cfg(feature = "history_builders")]
23-
pub use history_builder::{
24-
DEFAULT_ACTIVITY_TYPE, DEFAULT_WORKFLOW_TYPE, TestHistoryBuilder, default_act_sched,
25-
default_wes_attribs,
26-
};
27-
#[cfg(feature = "history_builders")]
28-
pub use history_info::HistoryInfo;
2913
pub use task_token::TaskToken;
3014

3115
/// Payload metadata key that identifies the encoding format.

crates/sdk-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ zip = { version = "8.4", optional = true, default-features = false, features = [
110110
[dependencies.temporalio-common]
111111
path = "../common"
112112
version = "0.2"
113-
features = ["core-based-sdk", "history_builders", "test-utilities"]
113+
features = ["core-based-sdk"]
114114

115115
[dependencies.temporalio-client]
116116
path = "../client"

crates/sdk-core/benches/workflow_replay_bench.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ use std::{
1212
thread,
1313
time::Duration,
1414
};
15-
use temporalio_common::{
16-
protos::{DEFAULT_WORKFLOW_TYPE, canned_histories},
17-
telemetry::metrics::{MetricKeyValue, MetricParameters, NewAttributes},
18-
};
15+
use temporalio_common::telemetry::metrics::{MetricKeyValue, MetricParameters, NewAttributes};
1916
use temporalio_macros::{workflow, workflow_methods};
2017
use temporalio_sdk::{SyncWorkflowContext, WorkflowContext, WorkflowResult};
21-
use temporalio_sdk_core::{CoreRuntime, replay::HistoryForReplay};
18+
use temporalio_sdk_core::{
19+
CoreRuntime,
20+
replay::{DEFAULT_WORKFLOW_TYPE, HistoryForReplay, canned_histories},
21+
};
2222

2323
pub fn criterion_benchmark(c: &mut Criterion) {
2424
let tokio_runtime = tokio::runtime::Builder::new_current_thread()

crates/sdk-core/src/core_tests/activity_tasks.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use crate::{
22
ActivityHeartbeat, CompleteActivityError, Worker, advance_fut, job_assert, prost_dur,
3+
replay::{TestHistoryBuilder, canned_histories},
34
test_help::{
45
FakeWfResponses, MockPollCfg, MockWorkerInputs, MocksHolder, QueueResponse, WorkerExt,
56
WorkflowCachingPolicy, build_fake_worker, build_mock_pollers, build_multihist_mock_sg,
67
fanout_tasks, gen_assert_and_reply, mock_manual_poller, mock_poller, mock_worker,
7-
poll_and_reply, single_hist_mock_sg, test_worker_cfg,
8+
poll_and_reply, single_hist_mock_sg, start_timer_cmd, test_worker_cfg,
89
},
910
worker::{
1011
PollerBehavior,
@@ -26,7 +27,6 @@ use std::{
2627
};
2728
use temporalio_common::{
2829
protos::{
29-
TestHistoryBuilder, canned_histories,
3030
coresdk::{
3131
ActivityTaskCompletion,
3232
activity_result::{
@@ -52,7 +52,6 @@ use temporalio_common::{
5252
RespondActivityTaskFailedResponse, RespondWorkflowTaskCompletedResponse,
5353
},
5454
},
55-
test_utils::start_timer_cmd,
5655
},
5756
worker::WorkerTaskTypes,
5857
};

crates/sdk-core/src/core_tests/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod workflow_tasks;
88

99
use crate::{
1010
PollError, Worker,
11+
replay::{TestHistoryBuilder, canned_histories},
1112
test_help::{
1213
MockPollCfg, build_mock_pollers, mock_worker, single_hist_mock_sg, test_worker_cfg,
1314
},
@@ -19,7 +20,6 @@ use crate::{
1920
use futures_util::FutureExt;
2021
use std::{sync::LazyLock, time::Duration};
2122
use temporalio_common::protos::{
22-
TestHistoryBuilder, canned_histories,
2323
coresdk::{
2424
workflow_activation::{WorkflowActivationJob, workflow_activation_job},
2525
workflow_completion::WorkflowActivationCompletion,

crates/sdk-core/src/core_tests/queries.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use crate::{
2+
replay::{TestHistoryBuilder, canned_histories},
23
test_help::{
34
MockPollCfg, MocksHolder, ResponseType, WorkerExt, WorkerTestHelpers, build_mock_pollers,
4-
hist_to_poll_resp, mock_worker, single_hist_mock_sg,
5+
hist_to_poll_resp, mock_worker, query_ok, schedule_activity_cmd, single_hist_mock_sg,
6+
start_timer_cmd,
57
},
68
worker::{
79
LEGACY_QUERY_ID, WorkerVersioningStrategy,
@@ -19,7 +21,6 @@ use std::{
1921
};
2022
use temporalio_client::MESSAGE_TOO_LARGE_KEY;
2123
use temporalio_common::protos::{
22-
TestHistoryBuilder, canned_histories,
2324
coresdk::{
2425
workflow_activation::{
2526
WorkflowActivationJob, remove_from_cache::EvictionReason, workflow_activation_job,
@@ -40,7 +41,6 @@ use temporalio_common::protos::{
4041
GetWorkflowExecutionHistoryResponse, RespondWorkflowTaskCompletedResponse,
4142
},
4243
},
43-
test_utils::{query_ok, schedule_activity_cmd, start_timer_cmd},
4444
};
4545

4646
#[rstest::rstest]

crates/sdk-core/src/core_tests/replay_flag.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
use crate::{
2-
test_help::{MockPollCfg, ResponseType, build_mock_pollers, hist_to_poll_resp, mock_worker},
2+
replay::{TestHistoryBuilder, canned_histories},
3+
test_help::{
4+
MockPollCfg, ResponseType, build_mock_pollers, hist_to_poll_resp, mock_worker, query_ok,
5+
start_timer_cmd,
6+
},
37
worker::{LEGACY_QUERY_ID, client::mocks::mock_worker_client},
48
};
59
use std::{collections::VecDeque, time::Duration};
610
use temporalio_common::protos::{
7-
TestHistoryBuilder, canned_histories,
811
coresdk::{
912
workflow_activation::{WorkflowActivationJob, workflow_activation_job},
1013
workflow_completion::WorkflowActivationCompletion,
1114
},
1215
temporal::api::{enums::v1::EventType, query::v1::WorkflowQuery},
13-
test_utils::{query_ok, start_timer_cmd},
1416
};
1517

1618
#[tokio::test]

crates/sdk-core/src/core_tests/updates.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::{
22
prost_dur,
3+
replay::{DEFAULT_ACTIVITY_TYPE, TestHistoryBuilder},
34
test_help::{
45
MockPollCfg, PollWFTRespExt, ResponseType, WorkerTestHelpers, build_mock_pollers,
56
hist_to_poll_resp, mock_worker,
67
},
78
worker::client::mocks::mock_worker_client,
89
};
910
use temporalio_common::protos::{
10-
DEFAULT_ACTIVITY_TYPE, TestHistoryBuilder,
1111
coresdk::{
1212
workflow_activation::{WorkflowActivationJob, workflow_activation_job},
1313
workflow_commands::{

0 commit comments

Comments
 (0)