Skip to content
Open
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
8 changes: 8 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,19 @@ exclude = [
'temporalio/api',
'temporalio/bridge/proto',
'temporalio/nexus/system/workflow_service',
'temporalio/common/_streams/proto',
]

[[tool.mypy.overrides]]
module = "temporalio.nexus.system.workflow_service.*"
ignore_errors = true

[[tool.mypy.overrides]]
module = [
"temporalio.common._streams.proto.*",
]
ignore_errors = true

[tool.pydocstyle]
convention = "google"
# https://github.com/PyCQA/pydocstyle/issues/363#issuecomment-625563088
Expand Down Expand Up @@ -258,6 +265,7 @@ exclude = [
"temporalio/api",
"temporalio/bridge/proto",
"temporalio/bridge/_visitor.py",
"temporalio/common/_streams/proto",
"tests/worker/workflow_sandbox/testmodules/proto",
]

Expand Down
4 changes: 2 additions & 2 deletions scripts/_proto/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM python:3.10
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ENV PATH="$PATH:/root/.local/bin"
RUN uv tool install poethepoet
VOLUME ["/api_new", "/bridge_new"]
VOLUME ["/api_new", "/bridge_new", "/streams_new"]

COPY ./ ./

Expand All @@ -13,4 +13,4 @@ RUN uv add "protobuf<4"
RUN uv sync --all-extras
RUN uv run scripts/gen_protos.py

CMD ["sh", "-c", "cp -r ./temporalio/api/* /api_new && cp -r ./temporalio/bridge/proto/* /bridge_new"]
CMD ["sh", "-c", "cp -r ./temporalio/api/* /api_new && cp -r ./temporalio/bridge/proto/* /bridge_new && cp -r ./temporalio/common/_streams/proto/* /streams_new"]
88 changes: 88 additions & 0 deletions scripts/_proto/temporal/api/enums/v1/stream.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
syntax = "proto3";

package temporal.api.enums.v1;

option go_package = "go.temporal.io/api/enums/v1;enums";
option java_package = "io.temporal.api.enums.v1";
option java_multiple_files = true;
option java_outer_classname = "StreamProto";
option ruby_package = "Temporalio::Api::Enums::V1";
option csharp_namespace = "Temporalio.Api.Enums.V1";

// Experimental. Might change in the future.
enum StreamProducerKind {
STREAM_PRODUCER_KIND_UNSPECIFIED = 0;
STREAM_PRODUCER_KIND_WORKFLOW = 1;
STREAM_PRODUCER_KIND_LOCAL_ACTIVITY = 2;
STREAM_PRODUCER_KIND_ACTIVITY = 3;
STREAM_PRODUCER_KIND_CLIENT = 4;
STREAM_PRODUCER_KIND_STANDALONE_ACTIVITY = 5;
}

// Experimental. Might change in the future.
// How a Stream closed, so a reader tells a terminated or timed out owner from a failed one
// without parsing the failure.
// (-- api-linter: core::0216::synonyms=disabled
// aip.dev/not-precedent: Named consistently with WorkflowExecutionStatus. --)
enum StreamCloseStatus {
STREAM_CLOSE_STATUS_UNSPECIFIED = 0;
STREAM_CLOSE_STATUS_COMPLETED = 1;
STREAM_CLOSE_STATUS_FAILED = 2;
STREAM_CLOSE_STATUS_CANCELED = 3;
// TERMINATED and TIMED_OUT come only from the owner's end, never from a caller.
STREAM_CLOSE_STATUS_TERMINATED = 4;
STREAM_CLOSE_STATUS_TIMED_OUT = 5;
}

// Experimental. Might change in the future.
// (-- api-linter: core::0216::synonyms=disabled
// aip.dev/not-precedent: Named consistently with WorkflowExecutionStatus. --)
enum StreamStatus {
STREAM_STATUS_UNSPECIFIED = 0;
STREAM_STATUS_OPEN = 1;
STREAM_STATUS_CLOSED = 2;
STREAM_STATUS_EXPIRED = 3;
}

// Experimental. Might change in the future.
enum StreamReadStart {
STREAM_READ_START_UNSPECIFIED = 0;
STREAM_READ_START_BEGINNING = 1;
STREAM_READ_START_END = 2;
}

// Experimental. Might change in the future.
// Why a Stream call failed. Each reason has one gRPC status code.
enum StreamErrorReason {
STREAM_ERROR_REASON_UNSPECIFIED = 0;
// Nobody created the Stream, even after `create_wait`. NOT_FOUND.
STREAM_ERROR_REASON_NOT_FOUND = 1;
// The Stream's Retention or safety TTL passed. NOT_FOUND.
STREAM_ERROR_REASON_EXPIRED = 2;
// The Stream is closed. FAILED_PRECONDITION.
STREAM_ERROR_REASON_CLOSED = 3;
// The Producer's epoch is lower than the newest one, its Workflow Task was withdrawn, or a
// Workflow retry withdrew its run. FAILED_PRECONDITION.
STREAM_ERROR_REASON_FENCED = 4;
// The batch has a lower `sequence` than the last one of its epoch. FAILED_PRECONDITION.
STREAM_ERROR_REASON_SEQUENCE = 5;
// The batch has the `sequence` of the last one of its epoch, and other content.
// FAILED_PRECONDITION.
STREAM_ERROR_REASON_SEQ_DIVERGENT = 6;
// The Stream's owner doesn't allow this close or this Producer. FAILED_PRECONDITION.
STREAM_ERROR_REASON_NOT_OWNER = 7;
// A newer format version wrote the Stream. FAILED_PRECONDITION.
STREAM_ERROR_REASON_FORMAT_TOO_NEW = 8;
// The offset is below zero or past the newest offset + 1. INVALID_ARGUMENT.
STREAM_ERROR_REASON_OFFSET = 9;
// A Record or a batch is over the Store's limit. INVALID_ARGUMENT.
STREAM_ERROR_REASON_TOO_LARGE = 10;
// The request is malformed. INVALID_ARGUMENT.
STREAM_ERROR_REASON_INVALID = 11;
// The Store failed or did not answer. UNAVAILABLE.
STREAM_ERROR_REASON_STORAGE = 12;
// No writer has the id. The SDK's in-process writer only. NOT_FOUND.
STREAM_ERROR_REASON_UNKNOWN_WRITER = 13;
// The Store lacks a capability that the call needs. UNIMPLEMENTED.
STREAM_ERROR_REASON_UNSUPPORTED = 14;
}
127 changes: 127 additions & 0 deletions scripts/_proto/temporal/api/stream/v1/message.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
syntax = "proto3";

package temporal.api.stream.v1;

option go_package = "go.temporal.io/api/stream/v1;stream";
option java_package = "io.temporal.api.stream.v1";
option java_multiple_files = true;
option java_outer_classname = "MessageProto";
option ruby_package = "Temporalio::Api::Stream::V1";
option csharp_namespace = "Temporalio.Api.Stream.V1";

import "google/protobuf/timestamp.proto";

import "temporal/api/common/v1/message.proto";
import "temporal/api/enums/v1/stream.proto";
import "temporal/api/failure/v1/message.proto";

// Experimental. Might change in the future.
// Identifies one Stream. The id is opaque to callers.
message StreamRef {
string id = 1;
// Unset for a client's Stream. For a Workflow, business_id is the Workflow ID and run_id is
// the first execution run id of its run chain. For a Standalone Activity, business_id is the
// activity ID and run_id is its run id. A Store keys on id, and reads only a Workflow owner's
// business_id, to check that a close's ref names the owner's run chain.
temporal.api.common.v1.Execution owner = 2;
// The name of the backend that holds the Stream, as the Worker and client config register
// it, so every process routes a ref it receives. Empty is the default backend. The Store
// never reads it.
string backend = 3;
}

// Experimental. Might change in the future.
// The ordered attempt of a Producer. Compared in this order: task_started_event_id,
// task_attempt, task_started_time, attempt_scheduled_time, attempt. A field that a kind does
// not use is empty and compares as zero. A timestamp compares seconds, then nanos.
message ProducerEpoch {
// The Workflow Task of a Workflow, or the one that dispatched a Local Activity.
int64 task_started_event_id = 1;
int32 task_attempt = 2;
// Tells a reused started event id apart, for example after a dropped speculative task.
google.protobuf.Timestamp task_started_time = 5;
// When the server scheduled an Activity's attempt. A reset makes it later.
google.protobuf.Timestamp attempt_scheduled_time = 3;
// Activity, Local Activity and client attempt.
int32 attempt = 4;
}

// Experimental. Might change in the future.
message Producer {
temporal.api.enums.v1.StreamProducerKind kind = 1;
string id = 2;
ProducerEpoch epoch = 3;
// The run of the Producer, so nobody parses the id. Empty for a client.
string run_id = 4;
}

// Experimental. Might change in the future.
message WorkflowTaskEpoch {
int64 started_event_id = 1;
int32 attempt = 2;
google.protobuf.Timestamp started_time = 3;
}

// Experimental. Might change in the future.
message AppendRecord {
reserved 1;
reserved "topic";
temporal.api.common.v1.Payload body = 2;
}

// Experimental. Might change in the future.
message Supersession {
temporal.api.enums.v1.StreamProducerKind producer_kind = 1;
string producer_id = 2;
ProducerEpoch epoch = 3;
// Workflow only.
WorkflowTaskEpoch previous_completed_task = 4;
repeated int64 failed_tasks = 5;
// Workflow retry only. The previous run. Every Record whose Producer carries it is withdrawn.
string withdraw_run = 6;
// The run of the Producer, so nobody parses the id. Empty for a client.
string run_id = 7;
}

// Experimental. Might change in the future.
// One Record that a Producer appended.
message StreamData {
reserved 1;
reserved "topic";
Producer producer = 2;
temporal.api.common.v1.Payload body = 3;
}

// Experimental. Might change in the future.
// The close of a Stream. A Stream has at most one, and a read returns it last.
message StreamClose {
// The Producer that closed the Stream.
Producer producer = 1;
temporal.api.common.v1.Payload result = 2;
temporal.api.failure.v1.Failure failure = 3;
// The result or the failure stays next to it.
temporal.api.enums.v1.StreamCloseStatus status = 4;
}

// Experimental. Might change in the future.
// An offset is the Redis entry id packed as ms << 20 | seq. It is ordered and unique in one
// Stream, and it is sparse. Offsets have gaps, so they don't count Records. Zero is never an
// offset. A read names its Stream, so the read checks the offset against that Stream.
message StreamRecord {
int64 offset = 1;
// A read item is a Record, a Superseded item or the close.
oneof item {
StreamData data = 2;
// The first batch of a higher epoch carries it. It withdraws the earlier Records that its
// facts name, and a reader drops them.
Supersession superseded = 3;
StreamClose close = 4;
}
}

// Experimental. Might change in the future.
// The details of a failed Stream call, in the gRPC status details and in the details of the
// application failure of a Nexus operation.
message StreamErrorDetails {
temporal.api.enums.v1.StreamErrorReason reason = 1;
}
Loading
Loading