From 332acbe88c404d0ce5e4cd88a1c098cc7d2f74b7 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Sat, 28 Mar 2026 14:20:50 -0700 Subject: [PATCH 1/4] Add Stand Alone Callbacks --- temporal/api/callback/v1/message.proto | 99 ++++++++++++- temporal/api/common/v1/message.proto | 2 + temporal/api/enums/v1/common.proto | 4 + temporal/api/errordetails/v1/message.proto | 6 + temporal/api/nexus/v1/message.proto | 2 + .../workflowservice/v1/request_response.proto | 135 ++++++++++++++++++ temporal/api/workflowservice/v1/service.proto | 81 +++++++++++ 7 files changed, 328 insertions(+), 1 deletion(-) diff --git a/temporal/api/callback/v1/message.proto b/temporal/api/callback/v1/message.proto index f881a4eef..961f11a04 100644 --- a/temporal/api/callback/v1/message.proto +++ b/temporal/api/callback/v1/message.proto @@ -9,6 +9,8 @@ option java_outer_classname = "MessageProto"; option ruby_package = "Temporalio::Api::Callback::V1"; option csharp_namespace = "Temporalio.Api.Callback.V1"; +import "google/protobuf/duration.proto"; +import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; import "temporal/api/common/v1/message.proto"; @@ -34,4 +36,99 @@ message CallbackInfo { google.protobuf.Timestamp next_attempt_schedule_time = 7; // If the state is BLOCKED, blocked reason provides additional information. string blocked_reason = 8; -} \ No newline at end of file +} + +// The outcome of a completed callback execution: either success or a failure. +message CallbackExecutionOutcome { + oneof value { + // The callback completed successfully. + google.protobuf.Empty success = 1; + // The failure if the callback completed unsuccessfully. + temporal.api.failure.v1.Failure failure = 2; + } +} + +// The Nexus completion data that a standalone callback execution will deliver to its target URL. +// Exactly one of success or failure should be set. +message CallbackExecutionCompletion { + oneof result { + // Deliver a successful Nexus operation completion with this result payload. + // If set, the callback delivers a successful completion to the target URL. + temporal.api.common.v1.Payload success = 1; + // Deliver a failed Nexus operation completion with this failure. + // If set, the callback delivers a failed completion to the target URL. + temporal.api.failure.v1.Failure failure = 2; + } +} + +// Information about a standalone callback execution. +message CallbackExecutionInfo { + // Unique identifier of this callback within its namespace. + string callback_id = 1; + + // Run ID of the callback execution. + string run_id = 2; + + // Information on how this callback should be invoked (e.g. its URL and type). + temporal.api.common.v1.Callback callback = 3; + + // Current state of the callback. + temporal.api.enums.v1.CallbackState state = 4; + + // The number of attempts made to deliver the callback. + // This number represents a minimum bound since the attempt is incremented after the callback request completes. + int32 attempt = 5; + + // The time when the callback was created/scheduled. + google.protobuf.Timestamp create_time = 6; + + // The time when the last attempt completed. + google.protobuf.Timestamp last_attempt_complete_time = 7; + + // The last attempt's failure, if any. + temporal.api.failure.v1.Failure last_attempt_failure = 8; + + // The time when the next attempt is scheduled. + google.protobuf.Timestamp next_attempt_schedule_time = 9; + + // If the state is BLOCKED, provides additional information. + string blocked_reason = 10; + + // Time when the callback transitioned to a terminal state. + google.protobuf.Timestamp close_time = 11; + + // Search attributes for indexing. + temporal.api.common.v1.SearchAttributes search_attributes = 12; + + // Schedule-to-close timeout for this callback. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 13; + + // Incremented each time the callback's state is mutated in persistence. + int64 state_transition_count = 14; +} + +// Limited callback information returned in the list response. +message CallbackExecutionListInfo { + // Unique identifier of this callback within its namespace. + string callback_id = 1; + + // Run ID of the callback execution. + string run_id = 2; + + // Current state of the callback. + temporal.api.enums.v1.CallbackState state = 3; + + // The time when the callback was created/scheduled. + google.protobuf.Timestamp create_time = 4; + + // Time when the callback transitioned to a terminal state. + google.protobuf.Timestamp close_time = 5; + + // Search attributes from the start request. + temporal.api.common.v1.SearchAttributes search_attributes = 6; + + // Incremented each time the callback's state is mutated. + int64 state_transition_count = 7; +} diff --git a/temporal/api/common/v1/message.proto b/temporal/api/common/v1/message.proto index d112124f3..c63ae8ec6 100644 --- a/temporal/api/common/v1/message.proto +++ b/temporal/api/common/v1/message.proto @@ -181,6 +181,8 @@ message Callback { string url = 1; // Header to attach to callback request. map header = 2; + // Standard token to use for completion. + string token = 3; } // Callbacks to be delivered internally within the system. diff --git a/temporal/api/enums/v1/common.proto b/temporal/api/enums/v1/common.proto index 192c1d75b..7f5d76382 100644 --- a/temporal/api/enums/v1/common.proto +++ b/temporal/api/enums/v1/common.proto @@ -49,6 +49,10 @@ enum CallbackState { CALLBACK_STATE_SUCCEEDED = 5; // Callback is blocked (eg: by circuit breaker). CALLBACK_STATE_BLOCKED = 6; + // Callback was canceled via RequestCancelCallbackExecution. + CALLBACK_STATE_CANCELED = 7; + // Callback was terminated via TerminateCallbackExecution. + CALLBACK_STATE_TERMINATED = 8; } // State of a pending Nexus operation. diff --git a/temporal/api/errordetails/v1/message.proto b/temporal/api/errordetails/v1/message.proto index c01e90e2c..a0f42a7e2 100644 --- a/temporal/api/errordetails/v1/message.proto +++ b/temporal/api/errordetails/v1/message.proto @@ -129,3 +129,9 @@ message ActivityExecutionAlreadyStartedFailure { string start_request_id = 1; string run_id = 2; } + +// An error indicating that a callback execution failed to start because a callback with the given +// callback ID already exists in this namespace. +message CallbackExecutionAlreadyStartedFailure { + string start_request_id = 1; +} diff --git a/temporal/api/nexus/v1/message.proto b/temporal/api/nexus/v1/message.proto index 552b75c26..4a688c23e 100644 --- a/temporal/api/nexus/v1/message.proto +++ b/temporal/api/nexus/v1/message.proto @@ -61,6 +61,8 @@ message StartOperationRequest { map callback_header = 6; // Links contain caller information and can be attached to the operations started by the handler. repeated Link links = 7; + // Callback token + string callback_token = 8; } // A request to cancel an operation. diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index 61d8e84a3..5b4f3a87b 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -21,6 +21,7 @@ import "temporal/api/enums/v1/deployment.proto"; import "temporal/api/enums/v1/update.proto"; import "temporal/api/enums/v1/activity.proto"; import "temporal/api/activity/v1/message.proto"; +import "temporal/api/callback/v1/message.proto"; import "temporal/api/common/v1/message.proto"; import "temporal/api/history/v1/message.proto"; import "temporal/api/workflow/v1/message.proto"; @@ -3093,3 +3094,137 @@ message DeleteActivityExecutionRequest { message DeleteActivityExecutionResponse { } + +message StartCallbackExecutionRequest { + string namespace = 1; + // The identity of the client who initiated this request. + string identity = 2; + // A unique identifier for this start request. Typically UUIDv4. + string request_id = 3; + // Identifier for this callback. Required. Must be unique among callbacks in the same namespace. + // If a callback with this ID already exists, the request will fail with CallbackExecutionAlreadyStarted. + string callback_id = 4; + // Callback execution run ID, targets the latest run if run_id is empty. + string run_id = 5; + // Information on how this callback should be invoked (e.g. its URL and type). + temporal.api.common.v1.Callback callback = 6; + // Schedule-to-close timeout for this callback. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 7; + // Search attributes for indexing. + temporal.api.common.v1.SearchAttributes search_attributes = 8; + // The Nexus completion data to deliver to the callback URL. + // Required. Contains either a successful result payload or a failure. + temporal.api.callback.v1.CallbackExecutionCompletion completion = 9; +} + +message StartCallbackExecutionResponse { + // The run ID of the callback that was started. + string run_id = 1; +} + +message DescribeCallbackExecutionRequest { + string namespace = 1; + // Identifier for the callback + string callback_id = 2; + // Run ID of the callback execution to describe. If empty, the latest run will be described. + string run_id = 3; + // Include the outcome (result/failure) in the response if the callback has completed. + bool include_outcome = 4; + // Token from a previous DescribeCallbackExecutionResponse. If present, long-poll until callback + // state changes from the state encoded in this token. If absent, return current state immediately. + // Note that callback state may change multiple times between requests, therefore it is not + // guaranteed that a client making a sequence of long-poll requests will see a complete + // sequence of state changes. + bytes long_poll_token = 5; +} + +message DescribeCallbackExecutionResponse { + // Information about the callback execution. + temporal.api.callback.v1.CallbackExecutionInfo info = 1; + // Only set if the callback is completed and include_outcome was true in the request. + temporal.api.callback.v1.CallbackExecutionOutcome outcome = 2; + // Token for follow-on long-poll requests. Absent only if the callback is complete. + bytes long_poll_token = 3; +} + +message PollCallbackExecutionRequest { + string namespace = 1; + // Identifier for the callback + string callback_id = 2; + // Run ID of the callback execution to poll. If empty, the latest run will be polled. + string run_id = 3; +} + +message PollCallbackExecutionResponse { + temporal.api.callback.v1.CallbackExecutionOutcome outcome = 1; +} + +message ListCallbackExecutionsRequest { + string namespace = 1; + // Max number of executions to return per page. + int32 page_size = 2; + // Token returned in ListCallbackExecutionsResponse. + bytes next_page_token = 3; + // Visibility query, see https://docs.temporal.io/list-filter for the syntax. + string query = 4; +} + +message ListCallbackExecutionsResponse { + repeated temporal.api.callback.v1.CallbackExecutionListInfo executions = 1; + // Token to use to fetch the next page. If empty, there is no next page. + bytes next_page_token = 2; +} + +message CountCallbackExecutionsRequest { + string namespace = 1; + // Visibility query, see https://docs.temporal.io/list-filter for the syntax. + string query = 2; +} + +message CountCallbackExecutionsResponse { + // If `query` is not grouping by any field, the count is an approximate number + // of callbacks that match the query. + // If `query` is grouping by a field, the count is simply the sum of the counts + // of the groups returned in the response. This number can be smaller than the + // total number of callbacks matching the query. + int64 count = 1; + + // Contains the groups if the request is grouping by a field. + // The list might not be complete, and the counts of each group is approximate. + repeated AggregationGroup groups = 2; + + message AggregationGroup { + repeated temporal.api.common.v1.Payload group_values = 1; + int64 count = 2; + } +} + +message TerminateCallbackExecutionRequest { + string namespace = 1; + // Identifier for the callback + string callback_id = 2; + // Run ID of the callback execution to terminate. If empty, the latest run will be terminated. + string run_id = 3; + // The identity of the worker/client. + string identity = 4; + // Used to de-dupe termination requests. + string request_id = 5; + // Reason for requesting the termination. + string reason = 6; +} + +message TerminateCallbackExecutionResponse { +} + +message DeleteCallbackExecutionRequest { + string namespace = 1; + // Identifier for the callback + string callback_id = 2; + // Run ID of the callback execution to delete. If empty, the latest run will be deleted. + string run_id = 3; +} + +message DeleteCallbackExecutionResponse { +} diff --git a/temporal/api/workflowservice/v1/service.proto b/temporal/api/workflowservice/v1/service.proto index 5c1e900a3..104950bfb 100644 --- a/temporal/api/workflowservice/v1/service.proto +++ b/temporal/api/workflowservice/v1/service.proto @@ -1760,4 +1760,85 @@ service WorkflowService { // (-- api-linter: core::0127::http-annotation=disabled // aip.dev/not-precedent: Activity deletion not exposed to HTTP, users should use cancel or terminate. --) rpc DeleteActivityExecution (DeleteActivityExecutionRequest) returns (DeleteActivityExecutionResponse) {} + + // StartCallbackExecution starts a new standalone callback execution. + // + // Returns a `CallbackExecutionAlreadyStarted` error if a callback already exists with the same + // callback ID in this namespace. + rpc StartCallbackExecution (StartCallbackExecutionRequest) returns (StartCallbackExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/callbacks/{callback_id}" + body: "*" + additional_bindings { + post: "/api/v1/namespaces/{namespace}/callbacks/{callback_id}" + body: "*" + } + }; + } + + // DescribeCallbackExecution returns information about a callback execution. + // It can be used to: + // - Get current callback info without waiting + // - Long-poll for next state change and return new callback info + // Response can optionally include the outcome (if the callback has completed). + rpc DescribeCallbackExecution (DescribeCallbackExecutionRequest) returns (DescribeCallbackExecutionResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/callbacks/{callback_id}" + additional_bindings { + get: "/api/v1/namespaces/{namespace}/callbacks/{callback_id}" + } + }; + } + + // PollCallbackExecution long-polls for a callback execution to complete and returns the outcome. + rpc PollCallbackExecution (PollCallbackExecutionRequest) returns (PollCallbackExecutionResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/callbacks/{callback_id}/outcome" + additional_bindings { + get: "/api/v1/namespaces/{namespace}/callbacks/{callback_id}/outcome" + } + }; + } + + // ListCallbackExecutions is a visibility API to list callback executions in a specific namespace. + rpc ListCallbackExecutions (ListCallbackExecutionsRequest) returns (ListCallbackExecutionsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/callbacks" + additional_bindings { + get: "/api/v1/namespaces/{namespace}/callbacks" + } + }; + } + + // CountCallbackExecutions is a visibility API to count callback executions in a specific namespace. + rpc CountCallbackExecutions (CountCallbackExecutionsRequest) returns (CountCallbackExecutionsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/callback-count" + additional_bindings { + get: "/api/v1/namespaces/{namespace}/callback-count" + } + }; + } + + // TerminateCallbackExecution terminates an existing callback execution immediately. + // + // Termination happens immediately. A terminated callback will have its state set to + // CALLBACK_STATE_TERMINATED. + rpc TerminateCallbackExecution (TerminateCallbackExecutionRequest) returns (TerminateCallbackExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/callbacks/{callback_id}/terminate" + body: "*" + additional_bindings { + post: "/api/v1/namespaces/{namespace}/callbacks/{callback_id}/terminate" + body: "*" + } + }; + } + + // DeleteCallbackExecution asynchronously deletes a callback execution. If the callback is + // running, it will be terminated before deletion. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Callback deletion not exposed to HTTP, users should use cancel or terminate. --) + rpc DeleteCallbackExecution (DeleteCallbackExecutionRequest) returns (DeleteCallbackExecutionResponse) {} } From 3ea1dec9075e51b51a7da753b24b924e7ae15d27 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 3 Apr 2026 11:15:14 -0700 Subject: [PATCH 2/4] Respond to PR comments --- openapi/openapiv2.json | 932 +++++++++++++++++- openapi/openapiv3.yaml | 837 +++++++++++++++- temporal/api/callback/v1/message.proto | 9 +- temporal/api/enums/v1/common.proto | 18 +- temporal/api/errordetails/v1/message.proto | 1 + .../workflowservice/v1/request_response.proto | 23 +- temporal/api/workflowservice/v1/service.proto | 2 +- 7 files changed, 1742 insertions(+), 80 deletions(-) diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index 02e2d1436..55434d7f1 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -1237,6 +1237,302 @@ ] } }, + "/api/v1/namespaces/{namespace}/callback-count": { + "get": { + "summary": "CountCallbackExecutions is a visibility API to count callback executions in a specific namespace.", + "operationId": "CountCallbackExecutions2", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1CountCallbackExecutionsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "query", + "description": "Visibility query, see https://docs.temporal.io/list-filter for the syntax.", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "WorkflowService" + ] + } + }, + "/api/v1/namespaces/{namespace}/callbacks": { + "get": { + "summary": "ListCallbackExecutions is a visibility API to list callback executions in a specific namespace.", + "operationId": "ListCallbackExecutions2", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ListCallbackExecutionsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "pageSize", + "description": "Max number of executions to return per page.", + "in": "query", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "name": "nextPageToken", + "description": "Token returned in ListCallbackExecutionsResponse.", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + }, + { + "name": "query", + "description": "Visibility query, see https://docs.temporal.io/list-filter for the syntax.", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "WorkflowService" + ] + } + }, + "/api/v1/namespaces/{namespace}/callbacks/{callbackId}": { + "get": { + "summary": "DescribeCallbackExecution returns information about a callback execution.\nIt can be used to:\n- Get current callback info without waiting\n- Long-poll for next state change and return new callback info\nResponse can optionally include the outcome (if the callback has completed).", + "operationId": "DescribeCallbackExecution2", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1DescribeCallbackExecutionResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "callbackId", + "description": "Identifier for the callback", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "runId", + "description": "Run ID of the callback execution to describe. If empty, the latest run will be described.", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "includeInput", + "description": "Include the input field in the response.", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "includeOutcome", + "description": "Include the outcome (result/failure) in the response if the callback has completed.", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "longPollToken", + "description": "Token from a previous DescribeCallbackExecutionResponse. If present, long-poll until callback\nstate changes from the state encoded in this token. If absent, return current state immediately.\nNote that callback state may change multiple times between requests, therefore it is not\nguaranteed that a client making a sequence of long-poll requests will see a complete\nsequence of state changes.", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + } + ], + "tags": [ + "WorkflowService" + ] + }, + "post": { + "summary": "StartCallbackExecution starts a new standalone callback execution.", + "description": "Returns a `CallbackExecutionAlreadyStarted` error if a callback already exists with the same\ncallback ID in this namespace, either in running or terminal states.", + "operationId": "StartCallbackExecution2", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1StartCallbackExecutionResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "callbackId", + "description": "Identifier for this callback. Required. Must be unique among callbacks in the same namespace.\nIf a callback with this ID already exists, the request will fail with CallbackExecutionAlreadyStarted.", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/WorkflowServiceStartCallbackExecutionBody" + } + } + ], + "tags": [ + "WorkflowService" + ] + } + }, + "/api/v1/namespaces/{namespace}/callbacks/{callbackId}/outcome": { + "get": { + "summary": "PollCallbackExecution long-polls for a callback execution to complete and returns the outcome.", + "operationId": "PollCallbackExecution2", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1PollCallbackExecutionResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "callbackId", + "description": "Identifier for the callback", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "runId", + "description": "Run ID of the callback execution to poll. If empty, the latest run will be polled.", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "WorkflowService" + ] + } + }, + "/api/v1/namespaces/{namespace}/callbacks/{callbackId}/terminate": { + "post": { + "summary": "TerminateCallbackExecution terminates an existing callback execution immediately.", + "description": "Termination happens immediately. A terminated callback will have its state set to\nCALLBACK_STATE_TERMINATED.", + "operationId": "TerminateCallbackExecution2", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1TerminateCallbackExecutionResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "callbackId", + "description": "Identifier for the callback", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/WorkflowServiceTerminateCallbackExecutionBody" + } + } + ], + "tags": [ + "WorkflowService" + ] + } + }, "/api/v1/namespaces/{namespace}/current-deployment/{deployment.seriesName}": { "post": { "summary": "Sets a deployment as the current deployment for its deployment series. Can optionally update\nthe metadata of the deployment as well.\nExperimental. This API might significantly change or be removed in a future release.\nDeprecated. Replaced by `SetWorkerDeploymentCurrentVersion`.", @@ -5906,21 +6202,319 @@ "description": "Batch job id", "in": "path", "required": true, - "type": "string" + "type": "string" + } + ], + "tags": [ + "WorkflowService" + ] + }, + "post": { + "summary": "StartBatchOperation starts a new batch operation", + "operationId": "StartBatchOperation", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1StartBatchOperationResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "description": "Namespace that contains the batch operation", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "jobId", + "description": "Job ID defines the unique ID for the batch job", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/WorkflowServiceStartBatchOperationBody" + } + } + ], + "tags": [ + "WorkflowService" + ] + } + }, + "/namespaces/{namespace}/batch-operations/{jobId}/stop": { + "post": { + "summary": "StopBatchOperation stops a batch operation", + "operationId": "StopBatchOperation", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1StopBatchOperationResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "description": "Namespace that contains the batch operation", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "jobId", + "description": "Batch job id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/WorkflowServiceStopBatchOperationBody" + } + } + ], + "tags": [ + "WorkflowService" + ] + } + }, + "/namespaces/{namespace}/callback-count": { + "get": { + "summary": "CountCallbackExecutions is a visibility API to count callback executions in a specific namespace.", + "operationId": "CountCallbackExecutions", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1CountCallbackExecutionsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "query", + "description": "Visibility query, see https://docs.temporal.io/list-filter for the syntax.", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "WorkflowService" + ] + } + }, + "/namespaces/{namespace}/callbacks": { + "get": { + "summary": "ListCallbackExecutions is a visibility API to list callback executions in a specific namespace.", + "operationId": "ListCallbackExecutions", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ListCallbackExecutionsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "pageSize", + "description": "Max number of executions to return per page.", + "in": "query", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "name": "nextPageToken", + "description": "Token returned in ListCallbackExecutionsResponse.", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + }, + { + "name": "query", + "description": "Visibility query, see https://docs.temporal.io/list-filter for the syntax.", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "WorkflowService" + ] + } + }, + "/namespaces/{namespace}/callbacks/{callbackId}": { + "get": { + "summary": "DescribeCallbackExecution returns information about a callback execution.\nIt can be used to:\n- Get current callback info without waiting\n- Long-poll for next state change and return new callback info\nResponse can optionally include the outcome (if the callback has completed).", + "operationId": "DescribeCallbackExecution", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1DescribeCallbackExecutionResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "callbackId", + "description": "Identifier for the callback", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "runId", + "description": "Run ID of the callback execution to describe. If empty, the latest run will be described.", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "includeInput", + "description": "Include the input field in the response.", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "includeOutcome", + "description": "Include the outcome (result/failure) in the response if the callback has completed.", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "longPollToken", + "description": "Token from a previous DescribeCallbackExecutionResponse. If present, long-poll until callback\nstate changes from the state encoded in this token. If absent, return current state immediately.\nNote that callback state may change multiple times between requests, therefore it is not\nguaranteed that a client making a sequence of long-poll requests will see a complete\nsequence of state changes.", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + } + ], + "tags": [ + "WorkflowService" + ] + }, + "post": { + "summary": "StartCallbackExecution starts a new standalone callback execution.", + "description": "Returns a `CallbackExecutionAlreadyStarted` error if a callback already exists with the same\ncallback ID in this namespace, either in running or terminal states.", + "operationId": "StartCallbackExecution", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1StartCallbackExecutionResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "callbackId", + "description": "Identifier for this callback. Required. Must be unique among callbacks in the same namespace.\nIf a callback with this ID already exists, the request will fail with CallbackExecutionAlreadyStarted.", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/WorkflowServiceStartCallbackExecutionBody" + } } ], "tags": [ "WorkflowService" ] - }, - "post": { - "summary": "StartBatchOperation starts a new batch operation", - "operationId": "StartBatchOperation", + } + }, + "/namespaces/{namespace}/callbacks/{callbackId}/outcome": { + "get": { + "summary": "PollCallbackExecution long-polls for a callback execution to complete and returns the outcome.", + "operationId": "PollCallbackExecution", "responses": { "200": { "description": "A successful response.", "schema": { - "$ref": "#/definitions/v1StartBatchOperationResponse" + "$ref": "#/definitions/v1PollCallbackExecutionResponse" } }, "default": { @@ -5933,25 +6527,23 @@ "parameters": [ { "name": "namespace", - "description": "Namespace that contains the batch operation", "in": "path", "required": true, "type": "string" }, { - "name": "jobId", - "description": "Job ID defines the unique ID for the batch job", + "name": "callbackId", + "description": "Identifier for the callback", "in": "path", "required": true, "type": "string" }, { - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/WorkflowServiceStartBatchOperationBody" - } + "name": "runId", + "description": "Run ID of the callback execution to poll. If empty, the latest run will be polled.", + "in": "query", + "required": false, + "type": "string" } ], "tags": [ @@ -5959,15 +6551,16 @@ ] } }, - "/namespaces/{namespace}/batch-operations/{jobId}/stop": { + "/namespaces/{namespace}/callbacks/{callbackId}/terminate": { "post": { - "summary": "StopBatchOperation stops a batch operation", - "operationId": "StopBatchOperation", + "summary": "TerminateCallbackExecution terminates an existing callback execution immediately.", + "description": "Termination happens immediately. A terminated callback will have its state set to\nCALLBACK_STATE_TERMINATED.", + "operationId": "TerminateCallbackExecution", "responses": { "200": { "description": "A successful response.", "schema": { - "$ref": "#/definitions/v1StopBatchOperationResponse" + "$ref": "#/definitions/v1TerminateCallbackExecutionResponse" } }, "default": { @@ -5980,14 +6573,13 @@ "parameters": [ { "name": "namespace", - "description": "Namespace that contains the batch operation", "in": "path", "required": true, "type": "string" }, { - "name": "jobId", - "description": "Batch job id", + "name": "callbackId", + "description": "Identifier for the callback", "in": "path", "required": true, "type": "string" @@ -5997,7 +6589,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/WorkflowServiceStopBatchOperationBody" + "$ref": "#/definitions/WorkflowServiceTerminateCallbackExecutionBody" } } ], @@ -9075,6 +9667,10 @@ "type": "string" }, "description": "Header to attach to callback request." + }, + "token": { + "type": "string", + "description": "Standard token to use for completion." } } }, @@ -10526,6 +11122,35 @@ } } }, + "WorkflowServiceStartCallbackExecutionBody": { + "type": "object", + "properties": { + "identity": { + "type": "string", + "description": "The identity of the client who initiated this request." + }, + "requestId": { + "type": "string", + "description": "A unique identifier for this start request. Typically UUIDv4." + }, + "callback": { + "$ref": "#/definitions/v1Callback", + "description": "Information on how this callback should be invoked (e.g. its URL and type)." + }, + "scheduleToCloseTimeout": { + "type": "string", + "description": "Schedule-to-close timeout for this callback." + }, + "searchAttributes": { + "$ref": "#/definitions/v1SearchAttributes", + "description": "Search attributes for indexing." + }, + "completion": { + "$ref": "#/definitions/v1CallbackExecutionCompletion", + "description": "The Nexus completion data to deliver to the callback URL.\nContains either a successful result payload or a failure." + } + } + }, "WorkflowServiceStartWorkflowExecutionBody": { "type": "object", "properties": { @@ -10675,6 +11300,27 @@ } } }, + "WorkflowServiceTerminateCallbackExecutionBody": { + "type": "object", + "properties": { + "runId": { + "type": "string", + "description": "Run ID of the callback execution to terminate. If empty, the latest run will be terminated." + }, + "identity": { + "type": "string", + "description": "The identity of the worker/client." + }, + "requestId": { + "type": "string", + "description": "Used to de-dupe termination requests." + }, + "reason": { + "type": "string", + "description": "Reason for requesting the termination." + } + } + }, "WorkflowServiceTerminateWorkflowExecutionBody": { "type": "object", "properties": { @@ -12286,6 +12932,152 @@ }, "description": "Callback to attach to various events in the system, e.g. workflow run completion." }, + "v1CallbackExecutionCompletion": { + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/v1Payload", + "description": "Deliver a successful Nexus operation completion with this result payload.\nIf set, the callback delivers a successful completion to the target URL." + }, + "failure": { + "$ref": "#/definitions/v1Failure", + "description": "Deliver a failed Nexus operation completion with this failure.\nIf set, the callback delivers a failed completion to the target URL.\nIf CanceledFailureInfo is set, the target operation is resolved is canceled instead of failed." + } + }, + "description": "The Nexus completion data that a standalone callback execution will deliver to its target URL.\nExactly one of success or failure should be set." + }, + "v1CallbackExecutionInfo": { + "type": "object", + "properties": { + "callbackId": { + "type": "string", + "description": "Unique identifier of this callback within its namespace." + }, + "runId": { + "type": "string", + "description": "Run ID of the callback execution." + }, + "callback": { + "$ref": "#/definitions/v1Callback", + "description": "Information on how this callback should be invoked (e.g. its URL and type)." + }, + "state": { + "$ref": "#/definitions/v1CallbackExecutionState", + "description": "Current state of the callback execution." + }, + "attempt": { + "type": "integer", + "format": "int32", + "description": "The number of attempts made to deliver the callback.\nThis number represents a minimum bound since the attempt is incremented after the callback request completes." + }, + "createTime": { + "type": "string", + "format": "date-time", + "description": "The time when the callback was created/scheduled." + }, + "lastAttemptCompleteTime": { + "type": "string", + "format": "date-time", + "description": "The time when the last attempt completed." + }, + "lastAttemptFailure": { + "$ref": "#/definitions/v1Failure", + "description": "The last attempt's failure, if any." + }, + "nextAttemptScheduleTime": { + "type": "string", + "format": "date-time", + "description": "The time when the next attempt is scheduled." + }, + "blockedReason": { + "type": "string", + "description": "If the state is BLOCKED, provides additional information." + }, + "closeTime": { + "type": "string", + "format": "date-time", + "description": "Time when the callback transitioned to a terminal state." + }, + "searchAttributes": { + "$ref": "#/definitions/v1SearchAttributes", + "description": "Search attributes for indexing." + }, + "scheduleToCloseTimeout": { + "type": "string", + "description": "Schedule-to-close timeout for this callback." + }, + "stateTransitionCount": { + "type": "string", + "format": "int64", + "description": "Incremented each time the callback's state is mutated in persistence." + } + }, + "description": "Information about a standalone callback execution." + }, + "v1CallbackExecutionListInfo": { + "type": "object", + "properties": { + "callbackId": { + "type": "string", + "description": "Unique identifier of this callback within its namespace." + }, + "runId": { + "type": "string", + "description": "Run ID of the callback execution." + }, + "state": { + "$ref": "#/definitions/v1CallbackExecutionState", + "description": "Current state of the callback execution." + }, + "createTime": { + "type": "string", + "format": "date-time", + "description": "The time when the callback was created/scheduled." + }, + "closeTime": { + "type": "string", + "format": "date-time", + "description": "Time when the callback transitioned to a terminal state." + }, + "searchAttributes": { + "$ref": "#/definitions/v1SearchAttributes", + "description": "Search attributes from the start request." + }, + "stateTransitionCount": { + "type": "string", + "format": "int64", + "description": "Incremented each time the callback's state is mutated." + } + }, + "description": "Limited callback information returned in the list response." + }, + "v1CallbackExecutionOutcome": { + "type": "object", + "properties": { + "success": { + "type": "object", + "properties": {}, + "description": "The callback completed successfully." + }, + "failure": { + "$ref": "#/definitions/v1Failure", + "description": "The failure if the callback completed unsuccessfully." + } + }, + "description": "The outcome of a completed callback execution: either success or a failure." + }, + "v1CallbackExecutionState": { + "type": "string", + "enum": [ + "CALLBACK_EXECUTION_STATE_UNSPECIFIED", + "CALLBACK_EXECUTION_STATE_RUNNING", + "CALLBACK_EXECUTION_STATE_SUCCEEDED", + "CALLBACK_EXECUTION_STATE_FAILED", + "CALLBACK_EXECUTION_STATE_TERMINATED" + ], + "default": "CALLBACK_EXECUTION_STATE_UNSPECIFIED", + "description": "Terminal status of a standalone callback execution.\n\n - CALLBACK_EXECUTION_STATE_UNSPECIFIED: Default value, unspecified status.\n - CALLBACK_EXECUTION_STATE_RUNNING: Callback execution is running.\n - CALLBACK_EXECUTION_STATE_SUCCEEDED: Callback has succeeded.\n - CALLBACK_EXECUTION_STATE_FAILED: Callback has failed.\n - CALLBACK_EXECUTION_STATE_TERMINATED: Callback was terminated via TerminateCallbackExecution." + }, "v1CallbackState": { "type": "string", "enum": [ @@ -12295,10 +13087,11 @@ "CALLBACK_STATE_BACKING_OFF", "CALLBACK_STATE_FAILED", "CALLBACK_STATE_SUCCEEDED", - "CALLBACK_STATE_BLOCKED" + "CALLBACK_STATE_BLOCKED", + "CALLBACK_STATE_TERMINATED" ], "default": "CALLBACK_STATE_UNSPECIFIED", - "description": "State of a callback.\n\n - CALLBACK_STATE_UNSPECIFIED: Default value, unspecified state.\n - CALLBACK_STATE_STANDBY: Callback is standing by, waiting to be triggered.\n - CALLBACK_STATE_SCHEDULED: Callback is in the queue waiting to be executed or is currently executing.\n - CALLBACK_STATE_BACKING_OFF: Callback has failed with a retryable error and is backing off before the next attempt.\n - CALLBACK_STATE_FAILED: Callback has failed.\n - CALLBACK_STATE_SUCCEEDED: Callback has succeeded.\n - CALLBACK_STATE_BLOCKED: Callback is blocked (eg: by circuit breaker)." + "description": "State of a callback.\n\n - CALLBACK_STATE_UNSPECIFIED: Default value, unspecified state.\n - CALLBACK_STATE_STANDBY: Callback is standing by, waiting to be triggered.\n - CALLBACK_STATE_SCHEDULED: Callback is in the queue waiting to be executed or is currently executing.\n - CALLBACK_STATE_BACKING_OFF: Callback has failed with a retryable error and is backing off before the next attempt.\n - CALLBACK_STATE_FAILED: Callback has failed.\n - CALLBACK_STATE_SUCCEEDED: Callback has succeeded.\n - CALLBACK_STATE_BLOCKED: Callback is blocked (eg: by circuit breaker).\n - CALLBACK_STATE_TERMINATED: Callback was terminated via TerminateCallbackExecution. Only possible for standalone callbacks." }, "v1CancelExternalWorkflowExecutionFailedCause": { "type": "string", @@ -12737,6 +13530,40 @@ } } }, + "v1CountCallbackExecutionsResponse": { + "type": "object", + "properties": { + "count": { + "type": "string", + "format": "int64", + "description": "If `query` is not grouping by any field, the count is an approximate number\nof callbacks that match the query.\nIf `query` is grouping by a field, the count is simply the sum of the counts\nof the groups returned in the response. This number can be smaller than the\ntotal number of callbacks matching the query." + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1CountCallbackExecutionsResponseAggregationGroup" + }, + "description": "Contains the groups if the request is grouping by a field.\nThe list might not be complete, and the counts of each group is approximate." + } + } + }, + "v1CountCallbackExecutionsResponseAggregationGroup": { + "type": "object", + "properties": { + "groupValues": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Payload" + } + }, + "count": { + "type": "string", + "format": "int64" + } + } + }, "v1CountSchedulesResponse": { "type": "object", "properties": { @@ -13075,6 +13902,24 @@ } } }, + "v1DescribeCallbackExecutionResponse": { + "type": "object", + "properties": { + "info": { + "$ref": "#/definitions/v1CallbackExecutionInfo", + "description": "Information about the callback execution." + }, + "outcome": { + "$ref": "#/definitions/v1CallbackExecutionOutcome", + "description": "Only set if the callback is completed and include_outcome was true in the request." + }, + "longPollToken": { + "type": "string", + "format": "byte", + "description": "Token for follow-on long-poll requests. Absent only if the callback is complete." + } + } + }, "v1DescribeDeploymentResponse": { "type": "object", "properties": { @@ -14166,6 +15011,23 @@ } } }, + "v1ListCallbackExecutionsResponse": { + "type": "object", + "properties": { + "executions": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1CallbackExecutionListInfo" + } + }, + "nextPageToken": { + "type": "string", + "format": "byte", + "description": "Token to use to fetch the next page. If empty, there is no next page." + } + } + }, "v1ListDeploymentsResponse": { "type": "object", "properties": { @@ -15300,6 +16162,14 @@ } } }, + "v1PollCallbackExecutionResponse": { + "type": "object", + "properties": { + "outcome": { + "$ref": "#/definitions/v1CallbackExecutionOutcome" + } + } + }, "v1PollWorkflowTaskQueueResponse": { "type": "object", "properties": { @@ -16604,6 +17474,15 @@ "v1StartBatchOperationResponse": { "type": "object" }, + "v1StartCallbackExecutionResponse": { + "type": "object", + "properties": { + "runId": { + "type": "string", + "description": "The run ID of the callback that was started." + } + } + }, "v1StartChildWorkflowExecutionFailedCause": { "type": "string", "enum": [ @@ -17077,6 +17956,9 @@ "v1TerminateActivityExecutionResponse": { "type": "object" }, + "v1TerminateCallbackExecutionResponse": { + "type": "object" + }, "v1TerminateWorkflowExecutionResponse": { "type": "object" }, diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index 2ceca06b4..6123a57e2 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -1111,6 +1111,259 @@ paths: application/json: schema: $ref: '#/components/schemas/Status' + /api/v1/namespaces/{namespace}/callback-count: + get: + tags: + - WorkflowService + description: CountCallbackExecutions is a visibility API to count callback executions in a specific namespace. + operationId: CountCallbackExecutions + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: query + in: query + description: Visibility query, see https://docs.temporal.io/list-filter for the syntax. + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CountCallbackExecutionsResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + /api/v1/namespaces/{namespace}/callbacks: + get: + tags: + - WorkflowService + description: ListCallbackExecutions is a visibility API to list callback executions in a specific namespace. + operationId: ListCallbackExecutions + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: pageSize + in: query + description: Max number of executions to return per page. + schema: + type: integer + format: int32 + - name: nextPageToken + in: query + description: Token returned in ListCallbackExecutionsResponse. + schema: + type: string + format: bytes + - name: query + in: query + description: Visibility query, see https://docs.temporal.io/list-filter for the syntax. + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ListCallbackExecutionsResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + /api/v1/namespaces/{namespace}/callbacks/{callbackId}: + get: + tags: + - WorkflowService + description: |- + DescribeCallbackExecution returns information about a callback execution. + It can be used to: + - Get current callback info without waiting + - Long-poll for next state change and return new callback info + Response can optionally include the outcome (if the callback has completed). + operationId: DescribeCallbackExecution + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: callbackId + in: path + description: Identifier for the callback + required: true + schema: + type: string + - name: runId + in: query + description: Run ID of the callback execution to describe. If empty, the latest run will be described. + schema: + type: string + - name: includeInput + in: query + description: Include the input field in the response. + schema: + type: boolean + - name: includeOutcome + in: query + description: Include the outcome (result/failure) in the response if the callback has completed. + schema: + type: boolean + - name: longPollToken + in: query + description: |- + Token from a previous DescribeCallbackExecutionResponse. If present, long-poll until callback + state changes from the state encoded in this token. If absent, return current state immediately. + Note that callback state may change multiple times between requests, therefore it is not + guaranteed that a client making a sequence of long-poll requests will see a complete + sequence of state changes. + schema: + type: string + format: bytes + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/DescribeCallbackExecutionResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + post: + tags: + - WorkflowService + description: |- + StartCallbackExecution starts a new standalone callback execution. + + Returns a `CallbackExecutionAlreadyStarted` error if a callback already exists with the same + callback ID in this namespace, either in running or terminal states. + operationId: StartCallbackExecution + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: callbackId + in: path + description: |- + Identifier for this callback. Required. Must be unique among callbacks in the same namespace. + If a callback with this ID already exists, the request will fail with CallbackExecutionAlreadyStarted. + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/StartCallbackExecutionRequest' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/StartCallbackExecutionResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + /api/v1/namespaces/{namespace}/callbacks/{callbackId}/outcome: + get: + tags: + - WorkflowService + description: PollCallbackExecution long-polls for a callback execution to complete and returns the outcome. + operationId: PollCallbackExecution + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: callbackId + in: path + description: Identifier for the callback + required: true + schema: + type: string + - name: runId + in: query + description: Run ID of the callback execution to poll. If empty, the latest run will be polled. + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PollCallbackExecutionResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + /api/v1/namespaces/{namespace}/callbacks/{callbackId}/terminate: + post: + tags: + - WorkflowService + description: |- + TerminateCallbackExecution terminates an existing callback execution immediately. + + Termination happens immediately. A terminated callback will have its state set to + CALLBACK_STATE_TERMINATED. + operationId: TerminateCallbackExecution + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: callbackId + in: path + description: Identifier for the callback + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TerminateCallbackExecutionRequest' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/TerminateCallbackExecutionResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' /api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}: post: tags: @@ -5235,19 +5488,260 @@ paths: parameters: - name: namespace in: path - description: Namespace that contains the batch operation + description: Namespace that contains the batch operation + required: true + schema: + type: string + - name: pageSize + in: query + description: List page size + schema: + type: integer + format: int32 + - name: nextPageToken + in: query + description: Next page token + schema: + type: string + format: bytes + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ListBatchOperationsResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + /namespaces/{namespace}/batch-operations/{jobId}: + get: + tags: + - WorkflowService + description: DescribeBatchOperation returns the information about a batch operation + operationId: DescribeBatchOperation + parameters: + - name: namespace + in: path + description: Namespace that contains the batch operation + required: true + schema: + type: string + - name: jobId + in: path + description: Batch job id + required: true + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/DescribeBatchOperationResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + post: + tags: + - WorkflowService + description: StartBatchOperation starts a new batch operation + operationId: StartBatchOperation + parameters: + - name: namespace + in: path + description: Namespace that contains the batch operation + required: true + schema: + type: string + - name: jobId + in: path + description: Job ID defines the unique ID for the batch job + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/StartBatchOperationRequest' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/StartBatchOperationResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + /namespaces/{namespace}/batch-operations/{jobId}/stop: + post: + tags: + - WorkflowService + description: StopBatchOperation stops a batch operation + operationId: StopBatchOperation + parameters: + - name: namespace + in: path + description: Namespace that contains the batch operation + required: true + schema: + type: string + - name: jobId + in: path + description: Batch job id + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/StopBatchOperationRequest' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/StopBatchOperationResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + /namespaces/{namespace}/callback-count: + get: + tags: + - WorkflowService + description: CountCallbackExecutions is a visibility API to count callback executions in a specific namespace. + operationId: CountCallbackExecutions + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: query + in: query + description: Visibility query, see https://docs.temporal.io/list-filter for the syntax. + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CountCallbackExecutionsResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + /namespaces/{namespace}/callbacks: + get: + tags: + - WorkflowService + description: ListCallbackExecutions is a visibility API to list callback executions in a specific namespace. + operationId: ListCallbackExecutions + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: pageSize + in: query + description: Max number of executions to return per page. + schema: + type: integer + format: int32 + - name: nextPageToken + in: query + description: Token returned in ListCallbackExecutionsResponse. + schema: + type: string + format: bytes + - name: query + in: query + description: Visibility query, see https://docs.temporal.io/list-filter for the syntax. + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ListCallbackExecutionsResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + /namespaces/{namespace}/callbacks/{callbackId}: + get: + tags: + - WorkflowService + description: |- + DescribeCallbackExecution returns information about a callback execution. + It can be used to: + - Get current callback info without waiting + - Long-poll for next state change and return new callback info + Response can optionally include the outcome (if the callback has completed). + operationId: DescribeCallbackExecution + parameters: + - name: namespace + in: path required: true schema: type: string - - name: pageSize + - name: callbackId + in: path + description: Identifier for the callback + required: true + schema: + type: string + - name: runId in: query - description: List page size + description: Run ID of the callback execution to describe. If empty, the latest run will be described. schema: - type: integer - format: int32 - - name: nextPageToken + type: string + - name: includeInput in: query - description: Next page token + description: Include the input field in the response. + schema: + type: boolean + - name: includeOutcome + in: query + description: Include the outcome (result/failure) in the response if the callback has completed. + schema: + type: boolean + - name: longPollToken + in: query + description: |- + Token from a previous DescribeCallbackExecutionResponse. If present, long-poll until callback + state changes from the state encoded in this token. If absent, return current state immediately. + Note that callback state may change multiple times between requests, therefore it is not + guaranteed that a client making a sequence of long-poll requests will see a complete + sequence of state changes. schema: type: string format: bytes @@ -5257,98 +5751,110 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListBatchOperationsResponse' + $ref: '#/components/schemas/DescribeCallbackExecutionResponse' default: description: Default error response content: application/json: schema: $ref: '#/components/schemas/Status' - /namespaces/{namespace}/batch-operations/{jobId}: - get: + post: tags: - WorkflowService - description: DescribeBatchOperation returns the information about a batch operation - operationId: DescribeBatchOperation + description: |- + StartCallbackExecution starts a new standalone callback execution. + + Returns a `CallbackExecutionAlreadyStarted` error if a callback already exists with the same + callback ID in this namespace, either in running or terminal states. + operationId: StartCallbackExecution parameters: - name: namespace in: path - description: Namespace that contains the batch operation required: true schema: type: string - - name: jobId + - name: callbackId in: path - description: Batch job id + description: |- + Identifier for this callback. Required. Must be unique among callbacks in the same namespace. + If a callback with this ID already exists, the request will fail with CallbackExecutionAlreadyStarted. required: true schema: type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/StartCallbackExecutionRequest' + required: true responses: "200": description: OK content: application/json: schema: - $ref: '#/components/schemas/DescribeBatchOperationResponse' + $ref: '#/components/schemas/StartCallbackExecutionResponse' default: description: Default error response content: application/json: schema: $ref: '#/components/schemas/Status' - post: + /namespaces/{namespace}/callbacks/{callbackId}/outcome: + get: tags: - WorkflowService - description: StartBatchOperation starts a new batch operation - operationId: StartBatchOperation + description: PollCallbackExecution long-polls for a callback execution to complete and returns the outcome. + operationId: PollCallbackExecution parameters: - name: namespace in: path - description: Namespace that contains the batch operation required: true schema: type: string - - name: jobId + - name: callbackId in: path - description: Job ID defines the unique ID for the batch job + description: Identifier for the callback required: true schema: type: string - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/StartBatchOperationRequest' - required: true + - name: runId + in: query + description: Run ID of the callback execution to poll. If empty, the latest run will be polled. + schema: + type: string responses: "200": description: OK content: application/json: schema: - $ref: '#/components/schemas/StartBatchOperationResponse' + $ref: '#/components/schemas/PollCallbackExecutionResponse' default: description: Default error response content: application/json: schema: $ref: '#/components/schemas/Status' - /namespaces/{namespace}/batch-operations/{jobId}/stop: + /namespaces/{namespace}/callbacks/{callbackId}/terminate: post: tags: - WorkflowService - description: StopBatchOperation stops a batch operation - operationId: StopBatchOperation + description: |- + TerminateCallbackExecution terminates an existing callback execution immediately. + + Termination happens immediately. A terminated callback will have its state set to + CALLBACK_STATE_TERMINATED. + operationId: TerminateCallbackExecution parameters: - name: namespace in: path - description: Namespace that contains the batch operation required: true schema: type: string - - name: jobId + - name: callbackId in: path - description: Batch job id + description: Identifier for the callback required: true schema: type: string @@ -5356,7 +5862,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/StopBatchOperationRequest' + $ref: '#/components/schemas/TerminateCallbackExecutionRequest' required: true responses: "200": @@ -5364,7 +5870,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/StopBatchOperationResponse' + $ref: '#/components/schemas/TerminateCallbackExecutionResponse' default: description: Default error response content: @@ -9066,6 +9572,135 @@ components: Links associated with the callback. It can be used to link to underlying resources of the callback. description: Callback to attach to various events in the system, e.g. workflow run completion. + CallbackExecutionCompletion: + type: object + properties: + success: + allOf: + - $ref: '#/components/schemas/Payload' + description: |- + Deliver a successful Nexus operation completion with this result payload. + If set, the callback delivers a successful completion to the target URL. + failure: + allOf: + - $ref: '#/components/schemas/Failure' + description: |- + Deliver a failed Nexus operation completion with this failure. + If set, the callback delivers a failed completion to the target URL. + If CanceledFailureInfo is set, the target operation is resolved is canceled instead of failed. + description: |- + The Nexus completion data that a standalone callback execution will deliver to its target URL. + Exactly one of success or failure should be set. + CallbackExecutionInfo: + type: object + properties: + callbackId: + type: string + description: Unique identifier of this callback within its namespace. + runId: + type: string + description: Run ID of the callback execution. + callback: + allOf: + - $ref: '#/components/schemas/Callback' + description: Information on how this callback should be invoked (e.g. its URL and type). + state: + enum: + - CALLBACK_EXECUTION_STATE_UNSPECIFIED + - CALLBACK_EXECUTION_STATE_RUNNING + - CALLBACK_EXECUTION_STATE_SUCCEEDED + - CALLBACK_EXECUTION_STATE_FAILED + - CALLBACK_EXECUTION_STATE_TERMINATED + type: string + description: Current state of the callback execution. + format: enum + attempt: + type: integer + description: |- + The number of attempts made to deliver the callback. + This number represents a minimum bound since the attempt is incremented after the callback request completes. + format: int32 + createTime: + type: string + description: The time when the callback was created/scheduled. + format: date-time + lastAttemptCompleteTime: + type: string + description: The time when the last attempt completed. + format: date-time + lastAttemptFailure: + allOf: + - $ref: '#/components/schemas/Failure' + description: The last attempt's failure, if any. + nextAttemptScheduleTime: + type: string + description: The time when the next attempt is scheduled. + format: date-time + blockedReason: + type: string + description: If the state is BLOCKED, provides additional information. + closeTime: + type: string + description: Time when the callback transitioned to a terminal state. + format: date-time + searchAttributes: + allOf: + - $ref: '#/components/schemas/SearchAttributes' + description: Search attributes for indexing. + scheduleToCloseTimeout: + pattern: ^-?(?:0|[1-9][0-9]{0,11})(?:\.[0-9]{1,9})?s$ + type: string + description: |- + Schedule-to-close timeout for this callback. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + stateTransitionCount: + type: string + description: Incremented each time the callback's state is mutated in persistence. + description: Information about a standalone callback execution. + CallbackExecutionListInfo: + type: object + properties: + callbackId: + type: string + description: Unique identifier of this callback within its namespace. + runId: + type: string + description: Run ID of the callback execution. + state: + enum: + - CALLBACK_EXECUTION_STATE_UNSPECIFIED + - CALLBACK_EXECUTION_STATE_RUNNING + - CALLBACK_EXECUTION_STATE_SUCCEEDED + - CALLBACK_EXECUTION_STATE_FAILED + - CALLBACK_EXECUTION_STATE_TERMINATED + type: string + description: Current state of the callback execution. + format: enum + createTime: + type: string + description: The time when the callback was created/scheduled. + format: date-time + closeTime: + type: string + description: Time when the callback transitioned to a terminal state. + format: date-time + searchAttributes: + allOf: + - $ref: '#/components/schemas/SearchAttributes' + description: Search attributes from the start request. + stateTransitionCount: + type: string + description: Incremented each time the callback's state is mutated. + description: Limited callback information returned in the list response. + CallbackExecutionOutcome: + type: object + properties: + failure: + allOf: + - $ref: '#/components/schemas/Failure' + description: The failure if the callback completed unsuccessfully. + description: 'The outcome of a completed callback execution: either success or a failure.' CallbackInfo: type: object properties: @@ -9086,6 +9721,7 @@ components: - CALLBACK_STATE_FAILED - CALLBACK_STATE_SUCCEEDED - CALLBACK_STATE_BLOCKED + - CALLBACK_STATE_TERMINATED type: string description: The current state of the callback. format: enum @@ -9134,6 +9770,9 @@ components: additionalProperties: type: string description: Header to attach to callback request. + token: + type: string + description: Standard token to use for completion. CanceledFailureInfo: type: object properties: @@ -9544,6 +10183,33 @@ components: $ref: '#/components/schemas/Payload' count: type: string + CountCallbackExecutionsResponse: + type: object + properties: + count: + type: string + description: |- + If `query` is not grouping by any field, the count is an approximate number + of callbacks that match the query. + If `query` is grouping by a field, the count is simply the sum of the counts + of the groups returned in the response. This number can be smaller than the + total number of callbacks matching the query. + groups: + type: array + items: + $ref: '#/components/schemas/CountCallbackExecutionsResponse_AggregationGroup' + description: |- + Contains the groups if the request is grouping by a field. + The list might not be complete, and the counts of each group is approximate. + CountCallbackExecutionsResponse_AggregationGroup: + type: object + properties: + groupValues: + type: array + items: + $ref: '#/components/schemas/Payload' + count: + type: string CountSchedulesResponse: type: object properties: @@ -9965,6 +10631,21 @@ components: reason: type: string description: Reason indicates the reason to stop a operation + DescribeCallbackExecutionResponse: + type: object + properties: + info: + allOf: + - $ref: '#/components/schemas/CallbackExecutionInfo' + description: Information about the callback execution. + outcome: + allOf: + - $ref: '#/components/schemas/CallbackExecutionOutcome' + description: Only set if the callback is completed and include_outcome was true in the request. + longPollToken: + type: string + description: Token for follow-on long-poll requests. Absent only if the callback is complete. + format: bytes DescribeDeploymentResponse: type: object properties: @@ -11005,6 +11686,17 @@ components: nextPageToken: type: string format: bytes + ListCallbackExecutionsResponse: + type: object + properties: + executions: + type: array + items: + $ref: '#/components/schemas/CallbackExecutionListInfo' + nextPageToken: + type: string + description: Token to use to fetch the next page. If empty, there is no next page. + format: bytes ListDeploymentsResponse: type: object properties: @@ -12129,6 +12821,11 @@ components: description: The run ID of the activity, useful when run_id was not specified in the request. outcome: $ref: '#/components/schemas/ActivityExecutionOutcome' + PollCallbackExecutionResponse: + type: object + properties: + outcome: + $ref: '#/components/schemas/CallbackExecutionOutcome' PollWorkflowTaskQueueResponse: type: object properties: @@ -14409,6 +15106,49 @@ components: StartBatchOperationResponse: type: object properties: {} + StartCallbackExecutionRequest: + type: object + properties: + namespace: + type: string + identity: + type: string + description: The identity of the client who initiated this request. + requestId: + type: string + description: A unique identifier for this start request. Typically UUIDv4. + callbackId: + type: string + description: |- + Identifier for this callback. Required. Must be unique among callbacks in the same namespace. + If a callback with this ID already exists, the request will fail with CallbackExecutionAlreadyStarted. + callback: + allOf: + - $ref: '#/components/schemas/Callback' + description: Information on how this callback should be invoked (e.g. its URL and type). + scheduleToCloseTimeout: + pattern: ^-?(?:0|[1-9][0-9]{0,11})(?:\.[0-9]{1,9})?s$ + type: string + description: |- + Schedule-to-close timeout for this callback. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + searchAttributes: + allOf: + - $ref: '#/components/schemas/SearchAttributes' + description: Search attributes for indexing. + completion: + allOf: + - $ref: '#/components/schemas/CallbackExecutionCompletion' + description: |- + The Nexus completion data to deliver to the callback URL. + Contains either a successful result payload or a failure. + StartCallbackExecutionResponse: + type: object + properties: + runId: + type: string + description: The run ID of the callback that was started. StartChildWorkflowExecutionFailedEventAttributes: type: object properties: @@ -15028,6 +15768,29 @@ components: TerminateActivityExecutionResponse: type: object properties: {} + TerminateCallbackExecutionRequest: + type: object + properties: + namespace: + type: string + callbackId: + type: string + description: Identifier for the callback + runId: + type: string + description: Run ID of the callback execution to terminate. If empty, the latest run will be terminated. + identity: + type: string + description: The identity of the worker/client. + requestId: + type: string + description: Used to de-dupe termination requests. + reason: + type: string + description: Reason for requesting the termination. + TerminateCallbackExecutionResponse: + type: object + properties: {} TerminateWorkflowExecutionRequest: type: object properties: diff --git a/temporal/api/callback/v1/message.proto b/temporal/api/callback/v1/message.proto index 961f11a04..9abbd2697 100644 --- a/temporal/api/callback/v1/message.proto +++ b/temporal/api/callback/v1/message.proto @@ -57,6 +57,7 @@ message CallbackExecutionCompletion { temporal.api.common.v1.Payload success = 1; // Deliver a failed Nexus operation completion with this failure. // If set, the callback delivers a failed completion to the target URL. + // If CanceledFailureInfo is set, the target operation is resolved is canceled instead of failed. temporal.api.failure.v1.Failure failure = 2; } } @@ -72,8 +73,8 @@ message CallbackExecutionInfo { // Information on how this callback should be invoked (e.g. its URL and type). temporal.api.common.v1.Callback callback = 3; - // Current state of the callback. - temporal.api.enums.v1.CallbackState state = 4; + // Current state of the callback execution. + temporal.api.enums.v1.CallbackExecutionState state = 4; // The number of attempts made to deliver the callback. // This number represents a minimum bound since the attempt is incremented after the callback request completes. @@ -117,8 +118,8 @@ message CallbackExecutionListInfo { // Run ID of the callback execution. string run_id = 2; - // Current state of the callback. - temporal.api.enums.v1.CallbackState state = 3; + // Current state of the callback execution. + temporal.api.enums.v1.CallbackExecutionState state = 3; // The time when the callback was created/scheduled. google.protobuf.Timestamp create_time = 4; diff --git a/temporal/api/enums/v1/common.proto b/temporal/api/enums/v1/common.proto index 7f5d76382..ab2a7d366 100644 --- a/temporal/api/enums/v1/common.proto +++ b/temporal/api/enums/v1/common.proto @@ -49,10 +49,22 @@ enum CallbackState { CALLBACK_STATE_SUCCEEDED = 5; // Callback is blocked (eg: by circuit breaker). CALLBACK_STATE_BLOCKED = 6; - // Callback was canceled via RequestCancelCallbackExecution. - CALLBACK_STATE_CANCELED = 7; + // Callback was terminated via TerminateCallbackExecution. Only possible for standalone callbacks. + CALLBACK_STATE_TERMINATED = 7; +} + +// Terminal status of a standalone callback execution. +enum CallbackExecutionState { + // Default value, unspecified status. + CALLBACK_EXECUTION_STATE_UNSPECIFIED = 0; + // Callback execution is running. + CALLBACK_EXECUTION_STATE_RUNNING = 1; + // Callback has succeeded. + CALLBACK_EXECUTION_STATE_SUCCEEDED = 2; + // Callback has failed. + CALLBACK_EXECUTION_STATE_FAILED = 3; // Callback was terminated via TerminateCallbackExecution. - CALLBACK_STATE_TERMINATED = 8; + CALLBACK_EXECUTION_STATE_TERMINATED = 4; } // State of a pending Nexus operation. diff --git a/temporal/api/errordetails/v1/message.proto b/temporal/api/errordetails/v1/message.proto index a0f42a7e2..28acc809c 100644 --- a/temporal/api/errordetails/v1/message.proto +++ b/temporal/api/errordetails/v1/message.proto @@ -134,4 +134,5 @@ message ActivityExecutionAlreadyStartedFailure { // callback ID already exists in this namespace. message CallbackExecutionAlreadyStartedFailure { string start_request_id = 1; + string run_id = 2; } diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index 5b4f3a87b..6cbdcf10c 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -3104,19 +3104,20 @@ message StartCallbackExecutionRequest { // Identifier for this callback. Required. Must be unique among callbacks in the same namespace. // If a callback with this ID already exists, the request will fail with CallbackExecutionAlreadyStarted. string callback_id = 4; - // Callback execution run ID, targets the latest run if run_id is empty. - string run_id = 5; // Information on how this callback should be invoked (e.g. its URL and type). - temporal.api.common.v1.Callback callback = 6; + temporal.api.common.v1.Callback callback = 5; // Schedule-to-close timeout for this callback. // (-- api-linter: core::0140::prepositions=disabled // aip.dev/not-precedent: "to" is used to indicate interval. --) - google.protobuf.Duration schedule_to_close_timeout = 7; + google.protobuf.Duration schedule_to_close_timeout = 6; // Search attributes for indexing. - temporal.api.common.v1.SearchAttributes search_attributes = 8; - // The Nexus completion data to deliver to the callback URL. - // Required. Contains either a successful result payload or a failure. - temporal.api.callback.v1.CallbackExecutionCompletion completion = 9; + temporal.api.common.v1.SearchAttributes search_attributes = 7; + // The input data to deliver to the callback URL. + oneof input { + // The Nexus completion data to deliver to the callback URL. + // Contains either a successful result payload or a failure. + temporal.api.callback.v1.CallbackExecutionCompletion completion = 8; + } } message StartCallbackExecutionResponse { @@ -3130,14 +3131,16 @@ message DescribeCallbackExecutionRequest { string callback_id = 2; // Run ID of the callback execution to describe. If empty, the latest run will be described. string run_id = 3; + // Include the input field in the response. + bool include_input = 4; // Include the outcome (result/failure) in the response if the callback has completed. - bool include_outcome = 4; + bool include_outcome = 5; // Token from a previous DescribeCallbackExecutionResponse. If present, long-poll until callback // state changes from the state encoded in this token. If absent, return current state immediately. // Note that callback state may change multiple times between requests, therefore it is not // guaranteed that a client making a sequence of long-poll requests will see a complete // sequence of state changes. - bytes long_poll_token = 5; + bytes long_poll_token = 6; } message DescribeCallbackExecutionResponse { diff --git a/temporal/api/workflowservice/v1/service.proto b/temporal/api/workflowservice/v1/service.proto index 104950bfb..c1e6e543c 100644 --- a/temporal/api/workflowservice/v1/service.proto +++ b/temporal/api/workflowservice/v1/service.proto @@ -1764,7 +1764,7 @@ service WorkflowService { // StartCallbackExecution starts a new standalone callback execution. // // Returns a `CallbackExecutionAlreadyStarted` error if a callback already exists with the same - // callback ID in this namespace. + // callback ID in this namespace, either in running or terminal states. rpc StartCallbackExecution (StartCallbackExecutionRequest) returns (StartCallbackExecutionResponse) { option (google.api.http) = { post: "/namespaces/{namespace}/callbacks/{callback_id}" From 88b2801afa9b188885002ba3190ac3e752e3e729 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 3 Apr 2026 16:08:30 -0700 Subject: [PATCH 3/4] Respond to PR comments --- temporal/api/callback/v1/message.proto | 32 +++++++++++-------- temporal/api/enums/v1/common.proto | 18 +++++++---- .../workflowservice/v1/request_response.proto | 6 ++-- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/temporal/api/callback/v1/message.proto b/temporal/api/callback/v1/message.proto index 9abbd2697..3825b0a6b 100644 --- a/temporal/api/callback/v1/message.proto +++ b/temporal/api/callback/v1/message.proto @@ -73,41 +73,44 @@ message CallbackExecutionInfo { // Information on how this callback should be invoked (e.g. its URL and type). temporal.api.common.v1.Callback callback = 3; - // Current state of the callback execution. - temporal.api.enums.v1.CallbackExecutionState state = 4; + // A general status for this callback, indicates whether it is currently running or in one of the terminal statuses. + temporal.api.enums.v1.CallbackExecutionStatus status = 4; + + // The detailed state of this callback, provides more granular information than the general status. + temporal.api.enums.v1.CallbackState state = 5; // The number of attempts made to deliver the callback. // This number represents a minimum bound since the attempt is incremented after the callback request completes. - int32 attempt = 5; + int32 attempt = 6; // The time when the callback was created/scheduled. - google.protobuf.Timestamp create_time = 6; + google.protobuf.Timestamp create_time = 7; // The time when the last attempt completed. - google.protobuf.Timestamp last_attempt_complete_time = 7; + google.protobuf.Timestamp last_attempt_complete_time = 8; // The last attempt's failure, if any. - temporal.api.failure.v1.Failure last_attempt_failure = 8; + temporal.api.failure.v1.Failure last_attempt_failure = 9; // The time when the next attempt is scheduled. - google.protobuf.Timestamp next_attempt_schedule_time = 9; + google.protobuf.Timestamp next_attempt_schedule_time = 10; // If the state is BLOCKED, provides additional information. - string blocked_reason = 10; + string blocked_reason = 11; // Time when the callback transitioned to a terminal state. - google.protobuf.Timestamp close_time = 11; + google.protobuf.Timestamp close_time = 12; // Search attributes for indexing. - temporal.api.common.v1.SearchAttributes search_attributes = 12; + temporal.api.common.v1.SearchAttributes search_attributes = 13; // Schedule-to-close timeout for this callback. // (-- api-linter: core::0140::prepositions=disabled // aip.dev/not-precedent: "to" is used to indicate interval. --) - google.protobuf.Duration schedule_to_close_timeout = 13; + google.protobuf.Duration schedule_to_close_timeout = 14; // Incremented each time the callback's state is mutated in persistence. - int64 state_transition_count = 14; + int64 state_transition_count = 15; } // Limited callback information returned in the list response. @@ -118,8 +121,9 @@ message CallbackExecutionListInfo { // Run ID of the callback execution. string run_id = 2; - // Current state of the callback execution. - temporal.api.enums.v1.CallbackExecutionState state = 3; + // Only running and terminal statuses appear here. More detailed information in CallbackExecutionInfo but not + // available in the list response. + temporal.api.enums.v1.CallbackExecutionStatus status = 3; // The time when the callback was created/scheduled. google.protobuf.Timestamp create_time = 4; diff --git a/temporal/api/enums/v1/common.proto b/temporal/api/enums/v1/common.proto index ab2a7d366..c6d1e1779 100644 --- a/temporal/api/enums/v1/common.proto +++ b/temporal/api/enums/v1/common.proto @@ -53,18 +53,22 @@ enum CallbackState { CALLBACK_STATE_TERMINATED = 7; } -// Terminal status of a standalone callback execution. -enum CallbackExecutionState { +// Status of a callback execution. +// The status is updated once, when the callback is originally scheduled, and again when the callback reaches a terminal +// status. +// (-- api-linter: core::0216::synonyms=disabled +// aip.dev/not-precedent: To be consistent with other enums like ActivityExecutionStatus. --) +enum CallbackExecutionStatus { // Default value, unspecified status. - CALLBACK_EXECUTION_STATE_UNSPECIFIED = 0; + CALLBACK_EXECUTION_STATUS_UNSPECIFIED = 0; // Callback execution is running. - CALLBACK_EXECUTION_STATE_RUNNING = 1; + CALLBACK_EXECUTION_STATUS_RUNNING = 1; // Callback has succeeded. - CALLBACK_EXECUTION_STATE_SUCCEEDED = 2; + CALLBACK_EXECUTION_STATUS_SUCCEEDED = 2; // Callback has failed. - CALLBACK_EXECUTION_STATE_FAILED = 3; + CALLBACK_EXECUTION_STATUS_FAILED = 3; // Callback was terminated via TerminateCallbackExecution. - CALLBACK_EXECUTION_STATE_TERMINATED = 4; + CALLBACK_EXECUTION_STATUS_TERMINATED = 4; } // State of a pending Nexus operation. diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index 6cbdcf10c..77e5bf48a 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -3160,8 +3160,10 @@ message PollCallbackExecutionRequest { string run_id = 3; } -message PollCallbackExecutionResponse { - temporal.api.callback.v1.CallbackExecutionOutcome outcome = 1; +message PollCallbackExecutionResponse { + // The run ID of the callback, useful when run_id was not specified in the request. + string run_id = 1; + temporal.api.callback.v1.CallbackExecutionOutcome outcome = 2; } message ListCallbackExecutionsRequest { From 091259dc037ac1eb4099a92d40687f7f8736081b Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 3 Apr 2026 19:43:57 -0700 Subject: [PATCH 4/4] rebase and regen --- openapi/openapiv2.json | 34 +++++++++++++++++++------------- openapi/openapiv3.yaml | 44 +++++++++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index 55434d7f1..1aec7e021 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -12961,9 +12961,13 @@ "$ref": "#/definitions/v1Callback", "description": "Information on how this callback should be invoked (e.g. its URL and type)." }, + "status": { + "$ref": "#/definitions/v1CallbackExecutionStatus", + "description": "A general status for this callback, indicates whether it is currently running or in one of the terminal statuses." + }, "state": { - "$ref": "#/definitions/v1CallbackExecutionState", - "description": "Current state of the callback execution." + "$ref": "#/definitions/v1CallbackState", + "description": "The detailed state of this callback, provides more granular information than the general status." }, "attempt": { "type": "integer", @@ -13025,9 +13029,9 @@ "type": "string", "description": "Run ID of the callback execution." }, - "state": { - "$ref": "#/definitions/v1CallbackExecutionState", - "description": "Current state of the callback execution." + "status": { + "$ref": "#/definitions/v1CallbackExecutionStatus", + "description": "Only running and terminal statuses appear here. More detailed information in CallbackExecutionInfo but not\navailable in the list response." }, "createTime": { "type": "string", @@ -13066,17 +13070,17 @@ }, "description": "The outcome of a completed callback execution: either success or a failure." }, - "v1CallbackExecutionState": { + "v1CallbackExecutionStatus": { "type": "string", "enum": [ - "CALLBACK_EXECUTION_STATE_UNSPECIFIED", - "CALLBACK_EXECUTION_STATE_RUNNING", - "CALLBACK_EXECUTION_STATE_SUCCEEDED", - "CALLBACK_EXECUTION_STATE_FAILED", - "CALLBACK_EXECUTION_STATE_TERMINATED" + "CALLBACK_EXECUTION_STATUS_UNSPECIFIED", + "CALLBACK_EXECUTION_STATUS_RUNNING", + "CALLBACK_EXECUTION_STATUS_SUCCEEDED", + "CALLBACK_EXECUTION_STATUS_FAILED", + "CALLBACK_EXECUTION_STATUS_TERMINATED" ], - "default": "CALLBACK_EXECUTION_STATE_UNSPECIFIED", - "description": "Terminal status of a standalone callback execution.\n\n - CALLBACK_EXECUTION_STATE_UNSPECIFIED: Default value, unspecified status.\n - CALLBACK_EXECUTION_STATE_RUNNING: Callback execution is running.\n - CALLBACK_EXECUTION_STATE_SUCCEEDED: Callback has succeeded.\n - CALLBACK_EXECUTION_STATE_FAILED: Callback has failed.\n - CALLBACK_EXECUTION_STATE_TERMINATED: Callback was terminated via TerminateCallbackExecution." + "default": "CALLBACK_EXECUTION_STATUS_UNSPECIFIED", + "description": "Status of a callback execution.\nThe status is updated once, when the callback is originally scheduled, and again when the callback reaches a terminal\nstatus.\n\n - CALLBACK_EXECUTION_STATUS_UNSPECIFIED: Default value, unspecified status.\n - CALLBACK_EXECUTION_STATUS_RUNNING: Callback execution is running.\n - CALLBACK_EXECUTION_STATUS_SUCCEEDED: Callback has succeeded.\n - CALLBACK_EXECUTION_STATUS_FAILED: Callback has failed.\n - CALLBACK_EXECUTION_STATUS_TERMINATED: Callback was terminated via TerminateCallbackExecution." }, "v1CallbackState": { "type": "string", @@ -16165,6 +16169,10 @@ "v1PollCallbackExecutionResponse": { "type": "object", "properties": { + "runId": { + "type": "string", + "description": "The run ID of the callback, useful when run_id was not specified in the request." + }, "outcome": { "$ref": "#/definitions/v1CallbackExecutionOutcome" } diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index 6123a57e2..4e06b206e 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -9604,15 +9604,28 @@ components: allOf: - $ref: '#/components/schemas/Callback' description: Information on how this callback should be invoked (e.g. its URL and type). + status: + enum: + - CALLBACK_EXECUTION_STATUS_UNSPECIFIED + - CALLBACK_EXECUTION_STATUS_RUNNING + - CALLBACK_EXECUTION_STATUS_SUCCEEDED + - CALLBACK_EXECUTION_STATUS_FAILED + - CALLBACK_EXECUTION_STATUS_TERMINATED + type: string + description: A general status for this callback, indicates whether it is currently running or in one of the terminal statuses. + format: enum state: enum: - - CALLBACK_EXECUTION_STATE_UNSPECIFIED - - CALLBACK_EXECUTION_STATE_RUNNING - - CALLBACK_EXECUTION_STATE_SUCCEEDED - - CALLBACK_EXECUTION_STATE_FAILED - - CALLBACK_EXECUTION_STATE_TERMINATED + - CALLBACK_STATE_UNSPECIFIED + - CALLBACK_STATE_STANDBY + - CALLBACK_STATE_SCHEDULED + - CALLBACK_STATE_BACKING_OFF + - CALLBACK_STATE_FAILED + - CALLBACK_STATE_SUCCEEDED + - CALLBACK_STATE_BLOCKED + - CALLBACK_STATE_TERMINATED type: string - description: Current state of the callback execution. + description: The detailed state of this callback, provides more granular information than the general status. format: enum attempt: type: integer @@ -9667,15 +9680,17 @@ components: runId: type: string description: Run ID of the callback execution. - state: + status: enum: - - CALLBACK_EXECUTION_STATE_UNSPECIFIED - - CALLBACK_EXECUTION_STATE_RUNNING - - CALLBACK_EXECUTION_STATE_SUCCEEDED - - CALLBACK_EXECUTION_STATE_FAILED - - CALLBACK_EXECUTION_STATE_TERMINATED + - CALLBACK_EXECUTION_STATUS_UNSPECIFIED + - CALLBACK_EXECUTION_STATUS_RUNNING + - CALLBACK_EXECUTION_STATUS_SUCCEEDED + - CALLBACK_EXECUTION_STATUS_FAILED + - CALLBACK_EXECUTION_STATUS_TERMINATED type: string - description: Current state of the callback execution. + description: |- + Only running and terminal statuses appear here. More detailed information in CallbackExecutionInfo but not + available in the list response. format: enum createTime: type: string @@ -12824,6 +12839,9 @@ components: PollCallbackExecutionResponse: type: object properties: + runId: + type: string + description: The run ID of the callback, useful when run_id was not specified in the request. outcome: $ref: '#/components/schemas/CallbackExecutionOutcome' PollWorkflowTaskQueueResponse: