From f4e6cf25897c8697cce8b2df5bf0af59df79933e Mon Sep 17 00:00:00 2001 From: sdk-sentinel-bot Date: Fri, 23 Oct 2026 21:46:24 +0000 Subject: [PATCH] Prevent replay shutdown from dropping nondeterminism results SDK-Sentinel-Request: temporalio/sdk-rust#1692/comment-6374405122 --- CHANGELOG.md | 2 ++ crates/sdk-core/CHANGELOG.md | 2 ++ crates/sdk-core/src/replay/mod.rs | 7 +++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 172358c20..36f9ebb21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,8 @@ relevant information. ### Fixed +* Batch workflow replay no longer reports a final nondeterministic history as successful when + shutdown races with delivery of its replay result. * Ephemeral server startup now enforces its elapsed-time deadline even when a connection stalls, and startup timeout messages include the last connection error when available. * Avoid scanning the workflow cache when no workflow tasks are waiting for a cache slot, reducing diff --git a/crates/sdk-core/CHANGELOG.md b/crates/sdk-core/CHANGELOG.md index 183eb4469..3637044a9 100644 --- a/crates/sdk-core/CHANGELOG.md +++ b/crates/sdk-core/CHANGELOG.md @@ -45,6 +45,8 @@ relevant information. nondeterminism while retaining compatibility with histories recorded before these checks. ### Fixed +* Replay workers now deliver a failed history's eviction before polling the next history, preventing + shutdown from dropping the final nondeterminism result. * Dev and test server startup now stops waiting at the configured deadline even if a readiness request stalls. Timeout messages include the last connection failure when available. * Workers with large workflow caches avoid unnecessary CPU usage when no workflow tasks are waiting diff --git a/crates/sdk-core/src/replay/mod.rs b/crates/sdk-core/src/replay/mod.rs index 6e4cadc50..6da1c17f4 100644 --- a/crates/sdk-core/src/replay/mod.rs +++ b/crates/sdk-core/src/replay/mod.rs @@ -32,6 +32,7 @@ use temporalio_common::{ coresdk::workflow_activation::remove_from_cache::EvictionReason, temporal::api::{ common::v1::WorkflowExecution, + enums::v1::WorkflowTaskFailedCause, history::v1::History, workflowservice::v1::{ DescribeNamespaceResponse, RespondWorkflowTaskCompletedResponse, @@ -136,8 +137,10 @@ where }); client .expect_fail_workflow_task() - .returning(move |_, _, _| { - hist_allow_tx.send("Failed".to_string()).unwrap(); + .returning(move |_, cause, _| { + if cause != WorkflowTaskFailedCause::NonDeterministicError { + hist_allow_tx.send("Failed".to_string()).unwrap(); + } async move { Ok(RespondWorkflowTaskFailedResponse::default()) }.boxed() }); let mut worker = Worker::new(self.config, None, Arc::new(client), None, None, None)?;