From 49f41c14ab812a0131bc7b0aed8daa1e31ee079e Mon Sep 17 00:00:00 2001 From: James Watkins-Harvey Date: Mon, 1 Jun 2026 17:08:34 -0400 Subject: [PATCH] Add Event Groups --- openapi/openapiv2.json | 55 +++++++++++++++++ openapi/openapiv3.yaml | 59 ++++++++++++++++++ temporal/api/command/v1/message.proto | 5 ++ temporal/api/history/v1/message.proto | 3 + temporal/api/sdk/v1/event_group_marker.proto | 65 ++++++++++++++++++++ 5 files changed, 187 insertions(+) create mode 100644 temporal/api/sdk/v1/event_group_marker.proto diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index 2e047a214..877e25fe0 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -10715,6 +10715,35 @@ }, "description": "Target a worker polling on a Nexus task queue in a specific namespace." }, + "EventGroupMarkerInboundEventAttributes": { + "type": "object", + "properties": { + "inboundEventId": { + "type": "string", + "format": "int64" + } + }, + "title": "The event ID of an event in the present workflow that triggered implicit\ncreation of this group marker. The target event's type must be one of the\nfollowing:\n - `WORKFLOW_EXECUTION_STARTED`\n - `WORKFLOW_EXECUTION_SIGNALED`" + }, + "EventGroupMarkerInboundUpdateAttributes": { + "type": "object", + "properties": { + "inboundUpdateId": { + "type": "string" + } + }, + "description": "The workflow-unique identifier of an inbound Update whose handler triggered\nimplicit creation of this group marker.\n\nUsed in place of `inbound_event_id` for Updates because the event ID of the\nUpdateAccepted history event is not known until the Workflow Task is\ncompleted and recorded by the server, which may be too late." + }, + "EventGroupMarkerLabelAttributes": { + "type": "object", + "properties": { + "label": { + "$ref": "#/definitions/v1Payload", + "description": "This payload should be a \"json/plain\"-encoded payload that is a single\nJSON string for use in user interfaces. User interface formatting may not\napply to this text when used in \"label\" situations. The payload data\nsection is limited to 400 bytes by default.\n\nNote that it is valid to have distinct markers (i.e. distinct marker IDs)\nin a given workflow execution that carry the same label." + } + }, + "description": "A user-defined short-form string value to be used as the group's label." + }, "LinkActivity": { "type": "object", "properties": { @@ -15319,6 +15348,24 @@ }, "description": "Target to route requests to." }, + "v1EventGroupMarker": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Opaque identifier assigned by the SDK.\n\nConstruction of this ID follows strict rules to ensure history\nconsolidation is possible. See below." + }, + "labelAttributes": { + "$ref": "#/definitions/EventGroupMarkerLabelAttributes" + }, + "inboundEventAttributes": { + "$ref": "#/definitions/EventGroupMarkerInboundEventAttributes" + }, + "inboundUpdateAttributes": { + "$ref": "#/definitions/EventGroupMarkerInboundUpdateAttributes" + } + } + }, "v1EventType": { "type": "string", "enum": [ @@ -15811,6 +15858,14 @@ "$ref": "#/definitions/v1Principal", "description": "Server-computed authenticated caller identity associated with this event." }, + "eventGroupMarkers": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1EventGroupMarker" + }, + "description": "Event group markers attached to this event." + }, "workflowExecutionStartedEventAttributes": { "$ref": "#/definitions/v1WorkflowExecutionStartedEventAttributes" }, diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index bc79eb4fc..b3854a600 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -11840,6 +11840,60 @@ components: type: string description: Nexus task queue to route requests to. description: Target a worker polling on a Nexus task queue in a specific namespace. + EventGroupMarker: + type: object + properties: + id: + type: string + description: |- + Opaque identifier assigned by the SDK. + + Construction of this ID follows strict rules to ensure history + consolidation is possible. See below. + labelAttributes: + $ref: '#/components/schemas/EventGroupMarker_LabelAttributes' + inboundEventAttributes: + $ref: '#/components/schemas/EventGroupMarker_InboundEventAttributes' + inboundUpdateAttributes: + $ref: '#/components/schemas/EventGroupMarker_InboundUpdateAttributes' + EventGroupMarker_InboundEventAttributes: + type: object + properties: + inboundEventId: + type: string + description: |- + The event ID of an event in the present workflow that triggered implicit + creation of this group marker. The target event's type must be one of the + following: + - `WORKFLOW_EXECUTION_STARTED` + - `WORKFLOW_EXECUTION_SIGNALED` + EventGroupMarker_InboundUpdateAttributes: + type: object + properties: + inboundUpdateId: + type: string + description: |- + The workflow-unique identifier of an inbound Update whose handler triggered + implicit creation of this group marker. + + Used in place of `inbound_event_id` for Updates because the event ID of the + UpdateAccepted history event is not known until the Workflow Task is + completed and recorded by the server, which may be too late. + EventGroupMarker_LabelAttributes: + type: object + properties: + label: + allOf: + - $ref: '#/components/schemas/Payload' + description: |- + This payload should be a "json/plain"-encoded payload that is a single + JSON string for use in user interfaces. User interface formatting may not + apply to this text when used in "label" situations. The payload data + section is limited to 400 bytes by default. + + Note that it is valid to have distinct markers (i.e. distinct marker IDs) + in a given workflow execution that carry the same label. + description: A user-defined short-form string value to be used as the group's label. ExternalWorkflowExecutionCancelRequestedEventAttributes: type: object properties: @@ -12308,6 +12362,11 @@ components: allOf: - $ref: '#/components/schemas/Principal' description: Server-computed authenticated caller identity associated with this event. + eventGroupMarkers: + type: array + items: + $ref: '#/components/schemas/EventGroupMarker' + description: Event group markers attached to this event. workflowExecutionStartedEventAttributes: $ref: '#/components/schemas/WorkflowExecutionStartedEventAttributes' workflowExecutionCompletedEventAttributes: diff --git a/temporal/api/command/v1/message.proto b/temporal/api/command/v1/message.proto index 597f9c94d..2ce183aad 100644 --- a/temporal/api/command/v1/message.proto +++ b/temporal/api/command/v1/message.proto @@ -17,6 +17,7 @@ import "temporal/api/common/v1/message.proto"; import "temporal/api/failure/v1/message.proto"; import "temporal/api/taskqueue/v1/message.proto"; import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api/sdk/v1/event_group_marker.proto"; message ScheduleActivityTaskCommandAttributes { string activity_id = 1; @@ -294,6 +295,10 @@ message Command { // * start_timer_command_attributes - populates temporal.api.history.v1.HistoryEvent for timer // started where the summary is used to identify the timer. temporal.api.sdk.v1.UserMetadata user_metadata = 301; + + // Event Group Markers attached to the command by the workflow author. + repeated temporal.api.sdk.v1.EventGroupMarker event_group_markers = 302; + // The command details. The type must match that in `command_type`. oneof attributes { ScheduleActivityTaskCommandAttributes schedule_activity_task_command_attributes = 2; diff --git a/temporal/api/history/v1/message.proto b/temporal/api/history/v1/message.proto index 96a06ab85..32f4f83cc 100644 --- a/temporal/api/history/v1/message.proto +++ b/temporal/api/history/v1/message.proto @@ -24,6 +24,7 @@ import "temporal/api/update/v1/message.proto"; import "temporal/api/workflow/v1/message.proto"; import "temporal/api/sdk/v1/task_complete_metadata.proto"; import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api/sdk/v1/event_group_marker.proto"; // Always the first event in workflow history message WorkflowExecutionStartedEventAttributes { @@ -1193,6 +1194,8 @@ message HistoryEvent { repeated temporal.api.common.v1.Link links = 302; // Server-computed authenticated caller identity associated with this event. temporal.api.common.v1.Principal principal = 303; + // Event group markers attached to this event. + repeated temporal.api.sdk.v1.EventGroupMarker event_group_markers = 304; // The event details. The type must match that in `event_type`. oneof attributes { WorkflowExecutionStartedEventAttributes workflow_execution_started_event_attributes = 6; diff --git a/temporal/api/sdk/v1/event_group_marker.proto b/temporal/api/sdk/v1/event_group_marker.proto new file mode 100644 index 000000000..a1b0da204 --- /dev/null +++ b/temporal/api/sdk/v1/event_group_marker.proto @@ -0,0 +1,65 @@ +syntax = "proto3"; + +package temporal.api.sdk.v1; + +option go_package = "go.temporal.io/api/sdk/v1;sdk"; +option java_package = "io.temporal.api.sdk.v1"; +option java_multiple_files = true; +option java_outer_classname = "EventGroupMarkerProto"; +option ruby_package = "Temporalio::Api::Sdk::V1"; +option csharp_namespace = "Temporalio.Api.Sdk.V1"; + + +import "temporal/api/common/v1/message.proto"; + +message EventGroupMarker { + // Opaque identifier assigned by the SDK. + // + // Construction of this ID follows strict rules to ensure history + // consolidation is possible. See below. + string id = 1; + + // Attributes attached to the group marker. They only needs to be set once per + // marker ID; further references to an existing marker ID reuse existing + // attributes of the referenced marker. + // + // In the case where a later group marker does carry attributes, then those + // attributes override the previous attributes of the same marker ID for all + // events carrying that marker ID, including preceding events. + oneof attributes { + LabelAttributes label_attributes = 2; + InboundEventAttributes inbound_event_attributes = 3; + InboundUpdateAttributes inbound_update_attributes = 4; + } + + // A user-defined short-form string value to be used as the group's label. + message LabelAttributes { + // This payload should be a "json/plain"-encoded payload that is a single + // JSON string for use in user interfaces. User interface formatting may not + // apply to this text when used in "label" situations. The payload data + // section is limited to 400 bytes by default. + // + // Note that it is valid to have distinct markers (i.e. distinct marker IDs) + // in a given workflow execution that carry the same label. + temporal.api.common.v1.Payload label = 1; + } + + // The event ID of an event in the present workflow that triggered implicit + // creation of this group marker. The target event's type must be one of the + // following: + // - `WORKFLOW_EXECUTION_STARTED` + // - `WORKFLOW_EXECUTION_SIGNALED` + message InboundEventAttributes { + int64 inbound_event_id = 1; + } + + // The workflow-unique identifier of an inbound Update whose handler triggered + // implicit creation of this group marker. + // + // Used in place of `inbound_event_id` for Updates because the event ID of the + // UpdateAccepted history event is not known until the Workflow Task is + // completed and recorded by the server, which may be too late. + message InboundUpdateAttributes { + string inbound_update_id = 1; + } +} \ No newline at end of file