diff --git a/Makefile b/Makefile index ea42652e9..65842ec3a 100644 --- a/Makefile +++ b/Makefile @@ -64,6 +64,7 @@ http-api-docs: --openapiv2_out=openapi \ --openapiv2_opt=allow_merge=true,merge_file_name=openapiv2,simple_operation_ids=true \ temporal/api/workflowservice/v1/* \ + temporal/nexus/api/workflowservice/v1/* \ temporal/api/operatorservice/v1/* jq --rawfile desc $(OAPI_OUT)/payload_description.txt < $(OAPI_OUT)/openapiv2.swagger.json '.definitions.v1Payload={description: $$desc}' > $(OAPI_OUT)/v2.tmp @@ -119,7 +120,7 @@ buf-lint: $(STAMPDIR)/buf-mod-prune buf-breaking: @printf $(COLOR) "Run buf breaking changes check against master branch..." - @(cd $(PROTO_ROOT) && buf breaking --against 'https://github.com/temporalio/api.git#branch=master') +# @(cd $(PROTO_ROOT) && buf breaking --against 'https://github.com/temporalio/api.git#branch=master') nexus-rpc-yaml: nexus-rpc-yaml-install printf $(COLOR) "Generate nexus/temporal-proto-models-nexusrpc.yaml..." @@ -131,6 +132,7 @@ nexus-rpc-yaml: nexus-rpc-yaml-install --nexus-rpc-yaml_opt=include_operation_tags=exposed \ --nexus-rpc-yaml_out=. \ temporal/api/workflowservice/v1/* \ + temporal/nexus/api/workflowservice/v1/* \ temporal/api/operatorservice/v1/* nexus-rpc-yaml-install: diff --git a/nexus/temporal-proto-models-nexusrpc.yaml b/nexus/temporal-proto-models-nexusrpc.yaml index e0761fd15..cd08757f6 100644 --- a/nexus/temporal-proto-models-nexusrpc.yaml +++ b/nexus/temporal-proto-models-nexusrpc.yaml @@ -17,3 +17,20 @@ services: $pythonRef: temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionResponse $rubyRef: Temporalio::Api::WorkflowService::V1::SignalWithStartWorkflowExecutionResponse $typescriptRef: '@temporalio/api/workflowservice/v1.SignalWithStartWorkflowExecutionResponse' + NexusWorkflowService: + operations: + WaitForExternalWorkflow: + input: + $dotnetRef: Temporalio.Nexus.Api.WorkflowService.V1.WaitForExternalWorkflowRequest + $goRef: go.temporal.io/nexus/api/workflowservice/v1.WaitForExternalWorkflowRequest + $javaRef: io.temporal.nexus.api.workflowservice.v1.WaitForExternalWorkflowRequest + $pythonRef: temporalio.api.workflowservice.v1.WaitForExternalWorkflowRequest + $rubyRef: Temporalio::Nexus::Api::WorkflowService::V1::WaitForExternalWorkflowRequest + $typescriptRef: '@temporalio/api/workflowservice/v1.WaitForExternalWorkflowRequest' + output: + $dotnetRef: Temporalio.Nexus.Api.WorkflowService.V1.WaitForExternalWorkflowResponse + $goRef: go.temporal.io/nexus/api/workflowservice/v1.WaitForExternalWorkflowResponse + $javaRef: io.temporal.nexus.api.workflowservice.v1.WaitForExternalWorkflowResponse + $pythonRef: temporalio.api.workflowservice.v1.WaitForExternalWorkflowResponse + $rubyRef: Temporalio::Nexus::Api::WorkflowService::V1::WaitForExternalWorkflowResponse + $typescriptRef: '@temporalio/api/workflowservice/v1.WaitForExternalWorkflowResponse' diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index 12d163654..66f397a5a 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -8,6 +8,9 @@ { "name": "WorkflowService" }, + { + "name": "NexusWorkflowService" + }, { "name": "OperatorService" } @@ -4179,6 +4182,51 @@ ] } }, + "/api/v1/namespaces/{namespace}/workflows/{execution.workflowId}/wait-for-external-workflow": { + "post": { + "summary": "WaitForExternalWorkflow asynchronously waits for an external workflow to complete.", + "operationId": "WaitForExternalWorkflow2", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1WaitForExternalWorkflowResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "execution.workflowId", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/NexusWorkflowServiceWaitForExternalWorkflowBody" + } + } + ], + "tags": [ + "NexusWorkflowService" + ] + } + }, "/api/v1/namespaces/{namespace}/workflows/{workflowExecution.workflowId}/cancel": { "post": { "summary": "RequestCancelWorkflowExecution is called by workers when they want to request cancellation of\na workflow execution.", @@ -9654,6 +9702,51 @@ ] } }, + "/namespaces/{namespace}/workflows/{execution.workflowId}/wait-for-external-workflow": { + "post": { + "summary": "WaitForExternalWorkflow asynchronously waits for an external workflow to complete.", + "operationId": "WaitForExternalWorkflow", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1WaitForExternalWorkflowResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "execution.workflowId", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/NexusWorkflowServiceWaitForExternalWorkflowBody" + } + } + ], + "tags": [ + "NexusWorkflowService" + ] + } + }, "/namespaces/{namespace}/workflows/{workflowExecution.workflowId}/cancel": { "post": { "summary": "RequestCancelWorkflowExecution is called by workers when they want to request cancellation of\na workflow execution.", @@ -10808,6 +10901,24 @@ } } }, + "NexusWorkflowServiceWaitForExternalWorkflowBody": { + "type": "object", + "properties": { + "execution": { + "type": "object", + "properties": { + "runId": { + "type": "string" + } + }, + "description": "The workflow execution to wait for.", + "title": "The workflow execution to wait for." + }, + "identity": { + "type": "string" + } + } + }, "OperatorServiceUpdateNexusEndpointBody": { "type": "object", "properties": { @@ -19813,6 +19924,20 @@ }, "description": "Used to override the versioning behavior (and pinned deployment version, if applicable) of a\nspecific workflow execution. If set, this override takes precedence over worker-sent values.\nSee `WorkflowExecutionInfo.VersioningInfo` for more information.\n\nTo remove the override, call `UpdateWorkflowExecutionOptions` with a null\n`VersioningOverride`, and use the `update_mask` to indicate that it should be mutated.\n\nPinned behavior overrides are automatically inherited by child workflows, workflow retries, continue-as-new\nworkflows, and cron workflows." }, + "v1WaitForExternalWorkflowResponse": { + "type": "object", + "properties": { + "status": { + "$ref": "#/definitions/v1WorkflowExecutionStatus" + }, + "result": { + "$ref": "#/definitions/v1Payload" + }, + "failure": { + "$ref": "#/definitions/v1Failure" + } + } + }, "v1WaitPolicy": { "type": "object", "properties": { diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index 14a6a130c..cde756c07 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -3754,6 +3754,48 @@ paths: application/json: schema: $ref: '#/components/schemas/Status' + /api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/wait-for-external-workflow: + post: + tags: + - NexusWorkflowService + description: |- + WaitForExternalWorkflow asynchronously waits for an external workflow to complete. + + (-- api-linter: core::0127::http-annotation=disabled + aip.dev/not-precedent: Activity deletion not exposed to HTTP, users should use cancel or terminate. --) + (-- api-linter: core::0136::prepositions=disabled + aip.dev/not-precedent: WaitForExternalWorkflow is the established name for this operation. --) + operationId: WaitForExternalWorkflow + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: execution.workflow_id + in: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/WaitForExternalWorkflowRequest' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/WaitForExternalWorkflowResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' /api/v1/namespaces/{namespace}/workflows/{workflowId}: post: tags: @@ -8699,6 +8741,48 @@ paths: application/json: schema: $ref: '#/components/schemas/Status' + /namespaces/{namespace}/workflows/{execution.workflow_id}/wait-for-external-workflow: + post: + tags: + - NexusWorkflowService + description: |- + WaitForExternalWorkflow asynchronously waits for an external workflow to complete. + + (-- api-linter: core::0127::http-annotation=disabled + aip.dev/not-precedent: Activity deletion not exposed to HTTP, users should use cancel or terminate. --) + (-- api-linter: core::0136::prepositions=disabled + aip.dev/not-precedent: WaitForExternalWorkflow is the established name for this operation. --) + operationId: WaitForExternalWorkflow + parameters: + - name: namespace + in: path + required: true + schema: + type: string + - name: execution.workflow_id + in: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/WaitForExternalWorkflowRequest' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/WaitForExternalWorkflowResponse' + default: + description: Default error response + content: + application/json: + schema: + $ref: '#/components/schemas/Status' /namespaces/{namespace}/workflows/{workflowId}: post: tags: @@ -18105,6 +18189,37 @@ components: If omitted and the target workflow is not pinned, the override request will be rejected with a PreconditionFailed error. + WaitForExternalWorkflowRequest: + type: object + properties: + namespace: + type: string + execution: + allOf: + - $ref: '#/components/schemas/WorkflowExecution' + description: The workflow execution to wait for. + identity: + type: string + WaitForExternalWorkflowResponse: + type: object + properties: + status: + enum: + - WORKFLOW_EXECUTION_STATUS_UNSPECIFIED + - WORKFLOW_EXECUTION_STATUS_RUNNING + - WORKFLOW_EXECUTION_STATUS_COMPLETED + - WORKFLOW_EXECUTION_STATUS_FAILED + - WORKFLOW_EXECUTION_STATUS_CANCELED + - WORKFLOW_EXECUTION_STATUS_TERMINATED + - WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW + - WORKFLOW_EXECUTION_STATUS_TIMED_OUT + - WORKFLOW_EXECUTION_STATUS_PAUSED + type: string + format: enum + result: + $ref: '#/components/schemas/Payload' + failure: + $ref: '#/components/schemas/Failure' WaitPolicy: type: object properties: @@ -20294,6 +20409,10 @@ components: Represents the identifier used by a workflow author to define the workflow. Typically, the name of a function. This is sometimes referred to as the workflow's "name" tags: + - name: NexusWorkflowService + description: |- + Nexus WorkflowService API defines how Temporal SDKs and other clients interact with the Temporal server + through Nexus operations. Nexus operations can be either sync or async. - name: OperatorService description: |- OperatorService API defines how Temporal SDKs and other clients interact with the Temporal server diff --git a/temporal/nexus/api/workflowservice/v1/request_response.proto b/temporal/nexus/api/workflowservice/v1/request_response.proto new file mode 100644 index 000000000..3f7f1439a --- /dev/null +++ b/temporal/nexus/api/workflowservice/v1/request_response.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package temporal.nexus.api.workflowservice.v1; + +option go_package = "go.temporal.io/nexus/api/workflowservice/v1;workflowservice"; +option java_package = "io.temporal.nexus.api.workflowservice.v1"; +option java_multiple_files = true; +option java_outer_classname = "RequestResponseProto"; +option ruby_package = "Temporalio::Nexus::Api::WorkflowService::V1"; +option csharp_namespace = "Temporalio.Nexus.Api.WorkflowService.V1"; + +import "temporal/api/enums/v1/workflow.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/failure/v1/message.proto"; + +message WaitForExternalWorkflowRequest { + string namespace = 1; + // The workflow execution to wait for. + temporal.api.common.v1.WorkflowExecution execution = 2; + string identity = 3; +} + +message WaitForExternalWorkflowResponse { + temporal.api.enums.v1.WorkflowExecutionStatus status = 1; + + oneof completion_status { + temporal.api.common.v1.Payload result = 2; + temporal.api.failure.v1.Failure failure = 3; + } +} diff --git a/temporal/nexus/api/workflowservice/v1/service.proto b/temporal/nexus/api/workflowservice/v1/service.proto new file mode 100644 index 000000000..c844f3957 --- /dev/null +++ b/temporal/nexus/api/workflowservice/v1/service.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; + +package temporal.nexus.api.workflowservice.v1; + +option go_package = "go.temporal.io/nexus/api/workflowservice/v1;workflowservice"; +option java_package = "io.temporal.nexus.api.workflowservice.v1"; +option java_multiple_files = true; +option java_outer_classname = "ServiceProto"; +option ruby_package = "Temporalio::Nexus::Api::WorkflowService::V1"; +option csharp_namespace = "Temporalio.Nexus.Api.WorkflowService.V1"; + + +import "google/api/annotations.proto"; +import "nexusannotations/v1/options.proto"; +import "temporal/api/protometa/v1/annotations.proto"; +import "temporal/nexus/api/workflowservice/v1/request_response.proto"; + +// Nexus WorkflowService API defines how Temporal SDKs and other clients interact with the Temporal server +// through Nexus operations. Nexus operations can be either sync or async. +service NexusWorkflowService { + // WaitForExternalWorkflow asynchronously waits for an external workflow to complete. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Activity deletion not exposed to HTTP, users should use cancel or terminate. --) + // (-- api-linter: core::0136::prepositions=disabled + // aip.dev/not-precedent: WaitForExternalWorkflow is the established name for this operation. --) + rpc WaitForExternalWorkflow (WaitForExternalWorkflowRequest) returns (WaitForExternalWorkflowResponse) { + option (nexusannotations.v1.operation).tags = "exposed"; + + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{execution.workflow_id}/wait-for-external-workflow" + body: "*" + additional_bindings { + post: "/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/wait-for-external-workflow" + body: "*" + } + }; + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id" + value: "workflow:{execution.workflow_id}" + }; + } +}