Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import "temporal/api/workflow/v1/message.proto";
import "temporal/sdk/core/child_workflow/child_workflow.proto";
import "temporal/sdk/core/nexus/nexus.proto";
import "temporal/sdk/core/common/common.proto";
import "temporal/sdk/streams/v1/message.proto";

message WorkflowCommand {
// User metadata that may or may not be persisted into history depending on the command type.
Expand Down Expand Up @@ -55,9 +56,33 @@ message WorkflowCommand {
UpdateResponse update_response = 20;
ScheduleNexusOperation schedule_nexus_operation = 21;
RequestCancelNexusOperation request_cancel_nexus_operation = 22;
WorkflowOutputStreamCommit workflow_output_stream_commit = 23;
}
}

// The stream records one activation published, sent with its completion.
//
// Core appends them to the Worker's stream store before it reports the completion to the
// server, so readers see them before the Workflow Task completes. Nothing about them goes to
// History. Lang sends no commit while it replays, and Core drops one it gets then, since the
// records are in the store already. Core takes at most one commit per completion.
message WorkflowOutputStreamCommit {
repeated OutputRecord records = 1;
}

// One record a Workflow published, in publish order across topics.
message OutputRecord {
string topic = 1;
// DATA or FINISH.
temporal.sdk.streams.v1.StreamRecordKind kind = 2;
// The value on DATA, after lang's payload codec. Absent on FINISH.
temporal.api.common.v1.Payload body = 3;
// The SHA-256 of the body as the payload converter made it, before the codec. Set on DATA.
// Core builds each topic's batch digest from these, so a repeat of a batch matches whatever
// the codec made of the bodies.
bytes content_hash = 4;
}

message StartTimer {
// Lang's incremental sequence number, used as the operation identifier
uint32 seq = 1;
Expand Down
10 changes: 10 additions & 0 deletions crates/protos/src/protos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1620,6 +1620,16 @@ pub mod coresdk {
}
}

impl Display for WorkflowOutputStreamCommit {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"WorkflowOutputStreamCommit({} record(s))",
self.records.len()
)
}
}

impl QueryResult {
/// Helper to construct the Temporal API query result types.
pub fn into_components(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,12 @@ impl WorkflowMachines {
annotations
);
}
WFCommandVariant::OutputStreamCommit(_) => {
return Err(fatal!(
"WorkflowOutputStreamCommit reached the state machines. The run takes it \
out when it processes the completion"
));
}
WFCommandVariant::NoCommandsFromLang => (),
}
}
Expand Down
5 changes: 5 additions & 0 deletions crates/sdk-core/src/worker/workflow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,8 @@ enum WFCommandVariant {
UpdateResponse(UpdateResponse),
ScheduleNexusOperation(ScheduleNexusOperation),
RequestCancelNexusOperation(RequestCancelNexusOperation),
/// The stream records lang published in this activation.
OutputStreamCommit(WorkflowOutputStreamCommit),
}

impl TryFrom<WorkflowCommand> for WFCommand {
Expand Down Expand Up @@ -1654,6 +1656,9 @@ impl TryFrom<WorkflowCommand> for WFCommand {
workflow_command::Variant::RequestCancelNexusOperation(s) => {
WFCommandVariant::RequestCancelNexusOperation(s)
}
workflow_command::Variant::WorkflowOutputStreamCommit(commit) => {
WFCommandVariant::OutputStreamCommit(commit)
}
};
Ok(Self {
variant,
Expand Down
Loading