diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index 388c769e..2f7ba2a9 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -6847,42 +6847,6 @@ }, "description": "UpdateWorkflowOptions represents updating workflow execution options after a workflow reset.\nKeep the parameters in sync with temporal.api.workflowservice.v1.UpdateWorkflowExecutionOptionsRequest." }, - "StartOperationResponseAsync": { - "type": "object", - "properties": { - "operationId": { - "type": "string", - "description": "Deprecated: Renamed to operation_token." - }, - "links": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/definitions/apinexusv1Link" - } - }, - "operationToken": { - "type": "string" - } - }, - "description": "The operation will complete asynchronously.\nThe returned ID can be used to reference this operation." - }, - "StartOperationResponseSync": { - "type": "object", - "properties": { - "payload": { - "$ref": "#/definitions/v1Payload" - }, - "links": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/definitions/apinexusv1Link" - } - } - }, - "description": "An operation completed successfully." - }, "UpdateWorkerBuildIdCompatibilityRequestAddNewCompatibleVersion": { "type": "object", "properties": { @@ -8294,6 +8258,12 @@ }, "cancelOperation": { "$ref": "#/definitions/v1CancelOperationRequest" + }, + "getOperationInfo": { + "$ref": "#/definitions/v1GetOperationInfoRequest" + }, + "getOperationResult": { + "$ref": "#/definitions/v1GetOperationResultRequest" } }, "description": "A Nexus request." @@ -8306,6 +8276,12 @@ }, "cancelOperation": { "$ref": "#/definitions/v1CancelOperationResponse" + }, + "getOperationInfo": { + "$ref": "#/definitions/v1GetOperationInfoResponse" + }, + "getOperationResult": { + "$ref": "#/definitions/v1GetOperationResultResponse" } }, "description": "A response indicating that the handler has successfully processed a request." @@ -9090,6 +9066,10 @@ ], "default": "CANCEL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_UNSPECIFIED" }, + "v1CancelNexusOperationResponse": { + "type": "object", + "description": "If this response is returned, the cancelation request was successfully processed by a Handler.\nThe operation may ignore the cancelation request and end up in any terminal state." + }, "v1CancelOperationRequest": { "type": "object", "properties": { @@ -10299,6 +10279,148 @@ } } }, + "v1GetNexusOperationInfoResponse": { + "type": "object", + "properties": { + "info": { + "$ref": "#/definitions/v1OperationInfo" + } + } + }, + "v1GetNexusOperationResultResponse": { + "type": "object", + "properties": { + "completeSuccess": { + "$ref": "#/definitions/v1GetNexusOperationResultResponseComplete" + }, + "operationError": { + "$ref": "#/definitions/v1UnsuccessfulOperationError", + "description": "The operation completed unsuccessfully (failed or canceled)." + }, + "stillRunning": { + "$ref": "#/definitions/v1GetNexusOperationResultResponseStillRunning", + "description": "The operation is still running, When waiting for completion, the caller may re-issue this request to start a\nnew long poll." + }, + "timeout": { + "$ref": "#/definitions/v1GetNexusOperationResultResponseTimeout", + "title": "The server gave up waiting for operation completion. The request may be retried by the caller.\nTODO: does the SDK need to return this or is this a server only result?" + } + } + }, + "v1GetNexusOperationResultResponseComplete": { + "type": "object", + "properties": { + "payload": { + "$ref": "#/definitions/v1Payload" + }, + "links": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apinexusv1Link" + } + } + }, + "description": "The operation completed successfully." + }, + "v1GetNexusOperationResultResponseStillRunning": { + "type": "object" + }, + "v1GetNexusOperationResultResponseTimeout": { + "type": "object" + }, + "v1GetOperationInfoRequest": { + "type": "object", + "properties": { + "service": { + "type": "string", + "description": "Service name." + }, + "operation": { + "type": "string", + "description": "Operation name." + }, + "operationToken": { + "type": "string", + "description": "Operation token as originally generated by a Handler." + } + }, + "description": "A request to cancel an operation.\n" + }, + "v1GetOperationInfoResponse": { + "type": "object", + "properties": { + "info": { + "$ref": "#/definitions/v1OperationInfo" + } + }, + "description": "Response variant for GetOperationInfoRequest." + }, + "v1GetOperationResultRequest": { + "type": "object", + "properties": { + "service": { + "type": "string", + "description": "Service name." + }, + "operation": { + "type": "string", + "description": "Operation name." + }, + "operationToken": { + "type": "string", + "description": "Operation token as originally generated by a Handler." + }, + "wait": { + "type": "string", + "description": "If set and non-zero, reflects the duration the caller has indicated that it wants to wait for operation\ncompletion, turning the request into a long poll." + } + }, + "description": "A request to cancel an operation.\n" + }, + "v1GetOperationResultResponse": { + "type": "object", + "properties": { + "completeSuccess": { + "$ref": "#/definitions/v1GetOperationResultResponseComplete" + }, + "operationError": { + "$ref": "#/definitions/v1UnsuccessfulOperationError", + "description": "The operation completed unsuccessfully (failed or canceled)." + }, + "stillRunning": { + "$ref": "#/definitions/v1GetOperationResultResponseStillRunning", + "description": "The operation is still running, When waiting for completion, the caller may re-issue this request to start a\nnew long poll." + }, + "timeout": { + "$ref": "#/definitions/v1GetOperationResultResponseTimeout", + "title": "The server gave up waiting for operation completion. The request may be retried by the caller.\nTODO: does the SDK need to return this or is this a server only result?" + } + }, + "description": "Response variant for GetOperationResultRequest." + }, + "v1GetOperationResultResponseComplete": { + "type": "object", + "properties": { + "payload": { + "$ref": "#/definitions/v1Payload" + }, + "links": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apinexusv1Link" + } + } + }, + "description": "The operation completed successfully." + }, + "v1GetOperationResultResponseStillRunning": { + "type": "object" + }, + "v1GetOperationResultResponseTimeout": { + "type": "object" + }, "v1GetSearchAttributesResponse": { "type": "object", "properties": { @@ -11635,6 +11757,19 @@ }, "description": "When StartWorkflowExecution uses the conflict policy WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING and\nthere is already an existing running workflow, OnConflictOptions defines actions to be taken on\nthe existing running workflow. In this case, it will create a WorkflowExecutionOptionsUpdatedEvent\nhistory event in the running workflow with the changes requested in this object." }, + "v1OperationInfo": { + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "Operation token as originally generated by a Handler." + }, + "state": { + "type": "string" + } + }, + "description": "See https://github.com/nexus-rpc/api/blob/main/SPEC.md#operationinfo." + }, "v1Outcome": { "type": "object", "properties": { @@ -13662,6 +13797,53 @@ } } }, + "v1StartNexusOperationResponse": { + "type": "object", + "properties": { + "syncSuccess": { + "$ref": "#/definitions/v1StartNexusOperationResponseSync" + }, + "asyncSuccess": { + "$ref": "#/definitions/v1StartNexusOperationResponseAsync" + }, + "operationError": { + "$ref": "#/definitions/v1UnsuccessfulOperationError", + "description": "The operation completed unsuccessfully (failed or canceled)." + } + } + }, + "v1StartNexusOperationResponseAsync": { + "type": "object", + "properties": { + "operationToken": { + "type": "string" + }, + "links": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apinexusv1Link" + } + } + }, + "description": "The operation will complete asynchronously.\nThe returned token can be used to reference this operation." + }, + "v1StartNexusOperationResponseSync": { + "type": "object", + "properties": { + "payload": { + "$ref": "#/definitions/v1Payload" + }, + "links": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apinexusv1Link" + } + } + }, + "description": "An operation completed successfully." + }, "v1StartOperationRequest": { "type": "object", "properties": { @@ -13707,10 +13889,10 @@ "type": "object", "properties": { "syncSuccess": { - "$ref": "#/definitions/StartOperationResponseSync" + "$ref": "#/definitions/v1StartOperationResponseSync" }, "asyncSuccess": { - "$ref": "#/definitions/StartOperationResponseAsync" + "$ref": "#/definitions/v1StartOperationResponseAsync" }, "operationError": { "$ref": "#/definitions/v1UnsuccessfulOperationError", @@ -13719,6 +13901,42 @@ }, "description": "Response variant for StartOperationRequest." }, + "v1StartOperationResponseAsync": { + "type": "object", + "properties": { + "operationId": { + "type": "string", + "description": "Deprecated: Renamed to operation_token." + }, + "links": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apinexusv1Link" + } + }, + "operationToken": { + "type": "string" + } + }, + "description": "The operation will complete asynchronously.\nThe returned token can be used to reference this operation." + }, + "v1StartOperationResponseSync": { + "type": "object", + "properties": { + "payload": { + "$ref": "#/definitions/v1Payload" + }, + "links": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apinexusv1Link" + } + } + }, + "description": "An operation completed successfully." + }, "v1StartTimeFilter": { "type": "object", "properties": { diff --git a/temporal/api/nexus/v1/message.proto b/temporal/api/nexus/v1/message.proto index 6a6eb564..23435ac0 100644 --- a/temporal/api/nexus/v1/message.proto +++ b/temporal/api/nexus/v1/message.proto @@ -10,6 +10,7 @@ option ruby_package = "Temporalio::Api::Nexus::V1"; option csharp_namespace = "Temporalio.Api.Nexus.V1"; import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; import "temporal/api/common/v1/message.proto"; import "temporal/api/enums/v1/nexus.proto"; @@ -42,6 +43,13 @@ message Link { string type = 2; } +// See https://github.com/nexus-rpc/api/blob/main/SPEC.md#operationinfo. +message OperationInfo { + // Operation token as originally generated by a Handler. + string token = 1; + string state = 2; +} + // A request to start an operation. message StartOperationRequest { // Name of service to start the operation in. @@ -75,6 +83,36 @@ message CancelOperationRequest { string operation_token = 4; } +// A request to cancel an operation. +// +// (-- api-linter: core::0131::request-name-required=disabled --) +// (-- api-linter: core::0131::request-unknown-fields=disabled --) +message GetOperationInfoRequest { + // Service name. + string service = 1; + // Operation name. + string operation = 2; + // Operation token as originally generated by a Handler. + string operation_token = 3; +} + +// A request to cancel an operation. +// +// (-- api-linter: core::0131::request-name-required=disabled --) +// (-- api-linter: core::0131::request-unknown-fields=disabled --) +message GetOperationResultRequest { + // Service name. + string service = 1; + // Operation name. + string operation = 2; + // Operation token as originally generated by a Handler. + string operation_token = 3; + + // If set and non-zero, reflects the duration the caller has indicated that it wants to wait for operation + // completion, turning the request into a long poll. + google.protobuf.Duration wait = 4; +} + // A Nexus request. message Request { // Headers extracted from the original request in the Temporal frontend. @@ -89,6 +127,8 @@ message Request { oneof variant { StartOperationRequest start_operation = 3; CancelOperationRequest cancel_operation = 4; + GetOperationInfoRequest get_operation_info = 5; + GetOperationResultRequest get_operation_result = 6; } } @@ -101,7 +141,7 @@ message StartOperationResponse { } // The operation will complete asynchronously. - // The returned ID can be used to reference this operation. + // The returned token can be used to reference this operation. message Async { // Deprecated: Renamed to operation_token. string operation_id = 1; @@ -121,12 +161,46 @@ message StartOperationResponse { message CancelOperationResponse { } +// Response variant for GetOperationInfoRequest. +message GetOperationInfoResponse { + OperationInfo info = 1; +} + +// Response variant for GetOperationResultRequest. +message GetOperationResultResponse { + // The operation completed successfully. + message Complete { + temporal.api.common.v1.Payload payload = 1; + repeated Link links = 2; + } + + message StillRunning { + } + + message Timeout { + } + + oneof variant { + Complete complete_success = 1; + // The operation completed unsuccessfully (failed or canceled). + UnsuccessfulOperationError operation_error = 2; + // The operation is still running, When waiting for completion, the caller may re-issue this request to start a + // new long poll. + StillRunning still_running = 3; + // The server gave up waiting for operation completion. The request may be retried by the caller. + // TODO: does the SDK need to return this or is this a server only result? + Timeout timeout = 4; + } +} + // A response indicating that the handler has successfully processed a request. message Response { // Variant must correlate to the corresponding Request's variant. oneof variant { StartOperationResponse start_operation = 1; CancelOperationResponse cancel_operation = 2; + GetOperationInfoResponse get_operation_info = 3; + GetOperationResultResponse get_operation_result = 4; } } diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index a0364f74..1d6eda65 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -2293,3 +2293,148 @@ message TriggerWorkflowRuleResponse { // True is the rule was applied, based on the rule conditions (predicate/visibility_query). bool applied = 1; } + +message StartNexusOperationRequest { + // The caller namespace. The endpoint below may point to a different namespace. + string namespace = 1; + // A registered endpoint. Mutually exclusive with task queue. + string endpoint = 2; + // Dispatch directly to a task queue on this namespace. + string task_queue = 3; + + // Request headers to forward to the Handler. + map header = 4; + + // Name of service to start the operation in. + string service = 5; + // Operation name. + string operation = 6; + // A request ID that can be used as an idempotentency key. + string request_id = 7; + // Callback URL to call upon completion if the started operation is async. + string callback = 8; + // Full request body from the incoming HTTP request. + temporal.api.common.v1.Payload payload = 9; + // Header that is expected to be attached to the callback request when the operation completes. + map callback_header = 10; + // Links contain caller information and can be attached to the operations started by the handler. + repeated temporal.api.nexus.v1.Link links = 11; +} + +message StartNexusOperationResponse { + // An operation completed successfully. + message Sync { + temporal.api.common.v1.Payload payload = 1; + repeated temporal.api.nexus.v1.Link links = 2; + } + + // The operation will complete asynchronously. + // The returned token can be used to reference this operation. + message Async { + string operation_token = 1; + repeated temporal.api.nexus.v1.Link links = 2; + } + + oneof variant { + Sync sync_success = 1; + Async async_success = 2; + // The operation completed unsuccessfully (failed or canceled). + temporal.api.nexus.v1.UnsuccessfulOperationError operation_error = 3; + } +} + +message CancelNexusOperationRequest { + // The caller namespace. The endpoint below may point to a different namespace. + string namespace = 1; + // A registered endpoint. Mutually exclusive with task queue. + string endpoint = 2; + // Dispatch directly to a task queue on this namespace. + string task_queue = 3; + + // Request headers to forward to the Handler. + map header = 4; + + // Service name. + string service = 5; + // Operation name. + string operation = 6; + // Operation token as originally generated by a Handler via an async StartOperation response. + string operation_token = 7; +} + +// If this response is returned, the cancelation request was successfully processed by a Handler. +// The operation may ignore the cancelation request and end up in any terminal state. +message CancelNexusOperationResponse { +} + +message GetNexusOperationInfoRequest { + // The caller namespace. The endpoint below may point to a different namespace. + string namespace = 1; + // A registered endpoint. Mutually exclusive with task queue. + string endpoint = 2; + // Dispatch directly to a task queue on this namespace. + string task_queue = 3; + + // Request headers to forward to the Handler. + map header = 4; + + // Service name. + string service = 5; + // Operation name. + string operation = 6; + // Operation token as originally generated by a Handler via an async StartOperation response. + string operation_token = 7; + +} +message GetNexusOperationInfoResponse { + temporal.api.nexus.v1.OperationInfo info = 1; +} + +message GetNexusOperationResultRequest { + // The caller namespace. The endpoint below may point to a different namespace. + string namespace = 1; + // A registered endpoint. Mutually exclusive with task queue. + string endpoint = 2; + // Dispatch directly to a task queue on this namespace. + string task_queue = 3; + + // Request headers to forward to the Handler. + map header = 4; + + // Service name. + string service = 5; + // Operation name. + string operation = 6; + // Operation token as originally generated by a Handler via an async StartOperation response. + string operation_token = 7; + + // If set and non-zero, reflects the duration the caller has indicated that it wants to wait for operation + // completion, turning the request into a long poll. + google.protobuf.Duration wait = 8; +} + +message GetNexusOperationResultResponse { + // The operation completed successfully. + message Complete { + temporal.api.common.v1.Payload payload = 1; + repeated temporal.api.nexus.v1.Link links = 2; + } + + message StillRunning { + } + + message Timeout { + } + + oneof variant { + Complete complete_success = 1; + // The operation completed unsuccessfully (failed or canceled). + temporal.api.nexus.v1.UnsuccessfulOperationError operation_error = 2; + // The operation is still running, When waiting for completion, the caller may re-issue this request to start a + // new long poll. + StillRunning still_running = 3; + // The server gave up waiting for operation completion. The request may be retried by the caller. + // TODO: does the SDK need to return this or is this a server only result? + Timeout timeout = 4; + } +} diff --git a/temporal/api/workflowservice/v1/service.proto b/temporal/api/workflowservice/v1/service.proto index 352d9e4e..06467683 100644 --- a/temporal/api/workflowservice/v1/service.proto +++ b/temporal/api/workflowservice/v1/service.proto @@ -1173,4 +1173,34 @@ service WorkflowService { }; } + // Start an arbitrary length operation. The response of the operation may be delivered synchronously (inline), or + // asynchronously, via a provided callback or the GetNexusOperationResult method. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Nexus has a separately defined HTTP API. --) + rpc StartNexusOperation (StartNexusOperationRequest) returns (StartNexusOperationResponse) { + } + + // Request to cancel an operation. The operation may later complete as canceled or any other outcome. Handlers + // should ignore multiple cancelations of the same operation and return successfully if cancelation was already + // requested. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Nexus has a separately defined HTTP API. --) + rpc CancelNexusOperation (CancelNexusOperationRequest) returns (CancelNexusOperationResponse) { + } + + // Retrieve operation result. Optionally specify a wait period to turn this request into a long poll. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Nexus has a separately defined HTTP API. --) + rpc GetNexusOperationInfo (GetNexusOperationInfoRequest) returns (GetNexusOperationInfoResponse) { + } + + // Retrieve operation details. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Nexus has a separately defined HTTP API. --) + rpc GetNexusOperationResult (GetNexusOperationResultRequest) returns (GetNexusOperationResultResponse) { + } }