Skip to content

Commit f66d869

Browse files
pdoernerbergundy
andauthored
Use Temporal failures in Nexus APIs (#682)
**What changed?** Use Temporal failures for sending Nexus response errors. **Why?** Consistency with other Temporal APIs and compatibility with encryption proxies. **Breaking changes** Not explicitly, but server and SDK will need to be able to handle both error formats based on `capabilities` field. **Server PR** temporalio/temporal#8799 --------- Co-authored-by: Roey Berman <roey.berman@gmail.com>
1 parent e966760 commit f66d869

6 files changed

Lines changed: 26 additions & 5 deletions

File tree

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ grpc-install:
8181
@go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
8282
@go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest
8383
@go install github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc@latest
84-
@go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
84+
# v2.27.8 errors with --openapiv2_out: can't resolve OpenAPI name from ".temporal.api.protocol.v1.Message"
85+
@go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.27.7
8586
@go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest
8687
@go install github.com/mikefarah/yq/v4@latest
8788

openapi/openapiv2.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13658,7 +13658,8 @@
1365813658
"type": "string",
1365913659
"description": "Operation token - may be empty if the operation completed synchronously."
1366013660
}
13661-
}
13661+
},
13662+
"description": "Representation of the Temporal SDK NexusOperationError object that is returned to workflow callers."
1366213663
},
1366313664
"v1NexusOperationScheduledEventAttributes": {
1366413665
"type": "object",

openapi/openapiv3.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10705,6 +10705,7 @@ components:
1070510705
operationToken:
1070610706
type: string
1070710707
description: Operation token - may be empty if the operation completed synchronously.
10708+
description: Representation of the Temporal SDK NexusOperationError object that is returned to workflow callers.
1070810709
NexusOperationScheduledEventAttributes:
1070910710
type: object
1071010711
properties:

temporal/api/failure/v1/message.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ message ChildWorkflowExecutionFailureInfo {
6666
temporal.api.enums.v1.RetryState retry_state = 6;
6767
}
6868

69+
// Representation of the Temporal SDK NexusOperationError object that is returned to workflow callers.
6970
message NexusOperationFailureInfo {
7071
// The NexusOperationScheduled event ID.
7172
int64 scheduled_event_id = 1;

temporal/api/nexus/v1/message.proto

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ option csharp_namespace = "Temporalio.Api.Nexus.V1";
1212
import "google/protobuf/timestamp.proto";
1313
import "temporal/api/common/v1/message.proto";
1414
import "temporal/api/enums/v1/nexus.proto";
15+
import "temporal/api/failure/v1/message.proto";
1516

1617
// A general purpose failure message.
1718
// See: https://github.com/nexus-rpc/api/blob/main/SPEC.md#failure
1819
message Failure {
1920
string message = 1;
21+
string stack_trace = 4;
2022
map<string, string> metadata = 2;
2123
// UTF-8 encoded JSON serializable details.
2224
bytes details = 3;
25+
Failure cause = 5;
2326
}
2427

2528
message HandlerError {
@@ -77,6 +80,12 @@ message CancelOperationRequest {
7780

7881
// A Nexus request.
7982
message Request {
83+
message Capabilities {
84+
// If set, handlers may use temporal.api.failure.v1.Failure instances to return failures to the server.
85+
// This also allows handler and operation errors to have their own messages and stack traces.
86+
bool temporal_failure_responses = 1;
87+
}
88+
8089
// Headers extracted from the original request in the Temporal frontend.
8190
// When using Nexus over HTTP, this includes the request's HTTP headers ignoring multiple values.
8291
map<string, string> header = 1;
@@ -86,6 +95,8 @@ message Request {
8695
// aip.dev/not-precedent: Not following linter rules. --)
8796
google.protobuf.Timestamp scheduled_time = 2;
8897

98+
Capabilities capabilities = 100;
99+
89100
oneof variant {
90101
StartOperationRequest start_operation = 3;
91102
CancelOperationRequest cancel_operation = 4;
@@ -117,7 +128,11 @@ message StartOperationResponse {
117128
Sync sync_success = 1;
118129
Async async_success = 2;
119130
// The operation completed unsuccessfully (failed or canceled).
120-
UnsuccessfulOperationError operation_error = 3;
131+
// Deprecated. Use the failure variant instead.
132+
UnsuccessfulOperationError operation_error = 3 [deprecated = true];
133+
// The operation completed unsuccessfully (failed or canceled).
134+
// Failure object must contain an ApplicationFailureInfo or CanceledFailureInfo object.
135+
temporal.api.failure.v1.Failure failure = 4;
121136
}
122137
}
123138

temporal/api/workflowservice/v1/request_response.proto

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,8 +1885,10 @@ message RespondNexusTaskFailedRequest {
18851885
string identity = 2;
18861886
// A unique identifier for this task.
18871887
bytes task_token = 3;
1888-
// The error the handler failed with.
1889-
temporal.api.nexus.v1.HandlerError error = 4;
1888+
// Deprecated. Use the failure field instead.
1889+
temporal.api.nexus.v1.HandlerError error = 4 [deprecated = true];
1890+
// The error the handler failed with. Must contain a NexusHandlerFailureInfo object.
1891+
temporal.api.failure.v1.Failure failure = 5;
18901892
}
18911893

18921894
message RespondNexusTaskFailedResponse {

0 commit comments

Comments
 (0)