Skip to content

Commit 57362ae

Browse files
committed
Working - Before removal of divergences reporting
1 parent 64cb6ed commit 57362ae

23 files changed

Lines changed: 1809 additions & 268 deletions

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: 2 additions & 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,7 @@ prometheus = [
2524
]
2625
envconfig = ["dep:toml", "dep:dirs"]
2726
serde_serialize = []
28-
test-utilities = ["history_builders"]
27+
test-utilities = []
2928
core-based-sdk = [
3029
"prometheus",
3130
"envconfig",
@@ -41,6 +40,7 @@ bon = { workspace = true }
4140
crc32fast = "1"
4241
dirs = { version = "6.0", optional = true }
4342
derive_more = { workspace = true }
43+
enum-iterator = "2"
4444
erased-serde = "0.4"
4545
futures = { version = "0.3", default-features = false, features = ["alloc"] }
4646
futures-channel = { version = "0.3", default-features = false, features = [
@@ -74,7 +74,6 @@ prometheus = { version = "0.14", optional = true, default-features = false }
7474
prost = { workspace = true }
7575
prost-wkt = "0.7"
7676
prost-types = { workspace = true }
77-
rand = { version = "0.10", optional = true }
7877
ringbuf = { version = "0.4", optional = true }
7978
serde = { version = "1.0", features = ["derive"] }
8079
serde_json = { workspace = true }

crates/common/src/protos/mod.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,12 @@ 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;
1710
#[cfg(feature = "test-utilities")]
1811
pub mod test_utils;
1912

2013
use std::time::Duration;
2114

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;
2915
pub use task_token::TaskToken;
3016

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

crates/common/src/protos/test_utils.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
//! Only available when the test-utilities feature is enabled
33
44
use crate::protos::{
5-
DEFAULT_ACTIVITY_TYPE,
65
coresdk::workflow_commands::{
76
ActivityCancellationType, QueryResult, QuerySuccess, ScheduleActivity,
87
ScheduleLocalActivity, StartTimer, workflow_command,
@@ -11,6 +10,10 @@ use crate::protos::{
1110
};
1211
use std::time::Duration;
1312

13+
/// Default activity type used by these test command builders. Kept in sync by convention with
14+
/// the constant of the same name in `temporalio_sdk_core::replay::DEFAULT_ACTIVITY_TYPE`.
15+
const DEFAULT_ACTIVITY_TYPE: &str = "default_act_type";
16+
1417
/// Convenience macro for creating prost Duration from std::time::Duration
1518
#[macro_export]
1619
macro_rules! prost_dur {

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", "test-utilities"]
114114

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

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
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,
@@ -26,7 +27,6 @@ use std::{
2627
};
2728
use temporalio_common::{
2829
protos::{
29-
TestHistoryBuilder, canned_histories,
3030
coresdk::{
3131
ActivityTaskCompletion,
3232
activity_result::{

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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::{
2+
replay::{TestHistoryBuilder, canned_histories},
23
test_help::{
34
MockPollCfg, MocksHolder, ResponseType, WorkerExt, WorkerTestHelpers, build_mock_pollers,
45
hist_to_poll_resp, mock_worker, single_hist_mock_sg,
@@ -19,7 +20,6 @@ use std::{
1920
};
2021
use temporalio_client::MESSAGE_TOO_LARGE_KEY;
2122
use temporalio_common::protos::{
22-
TestHistoryBuilder, canned_histories,
2323
coresdk::{
2424
workflow_activation::{
2525
WorkflowActivationJob, remove_from_cache::EvictionReason, workflow_activation_job,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use crate::{
2+
replay::{TestHistoryBuilder, canned_histories},
23
test_help::{MockPollCfg, ResponseType, build_mock_pollers, hist_to_poll_resp, mock_worker},
34
worker::{LEGACY_QUERY_ID, client::mocks::mock_worker_client},
45
};
56
use std::{collections::VecDeque, time::Duration};
67
use temporalio_common::protos::{
7-
TestHistoryBuilder, canned_histories,
88
coresdk::{
99
workflow_activation::{WorkflowActivationJob, workflow_activation_job},
1010
workflow_completion::WorkflowActivationCompletion,

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)