Skip to content

Commit cbd01a9

Browse files
committed
Add Stand Alone Callbacks (rebase)
1 parent c6aa19b commit cbd01a9

9 files changed

Lines changed: 2090 additions & 56 deletions

File tree

openapi/openapiv2.json

Lines changed: 912 additions & 20 deletions
Large diffs are not rendered by default.

openapi/openapiv3.yaml

Lines changed: 820 additions & 35 deletions
Large diffs are not rendered by default.

temporal/api/callback/v1/message.proto

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,115 @@ option java_outer_classname = "MessageProto";
99
option ruby_package = "Temporalio::Api::Callback::V1";
1010
option csharp_namespace = "Temporalio.Api.Callback.V1";
1111

12+
import "google/protobuf/duration.proto";
13+
import "google/protobuf/empty.proto";
1214
import "google/protobuf/timestamp.proto";
1315

1416
import "temporal/api/common/v1/message.proto";
1517
import "temporal/api/enums/v1/common.proto";
1618
import "temporal/api/failure/v1/message.proto";
1719

20+
// The outcome of a completed callback execution: either success or a failure.
21+
message CallbackExecutionOutcome {
22+
oneof value {
23+
// The callback completed successfully.
24+
google.protobuf.Empty success = 1;
25+
// The failure if the callback completed unsuccessfully.
26+
temporal.api.failure.v1.Failure failure = 2;
27+
}
28+
}
29+
30+
// The Nexus completion data that a standalone callback execution will deliver to its target URL.
31+
// Exactly one of success or failure should be set.
32+
message CallbackExecutionCompletion {
33+
oneof result {
34+
// Deliver a successful Nexus operation completion with this result payload.
35+
// If set, the callback delivers a successful completion to the target URL.
36+
temporal.api.common.v1.Payload success = 1;
37+
// Deliver a failed Nexus operation completion with this failure.
38+
// If set, the callback delivers a failed completion to the target URL.
39+
// If CanceledFailureInfo is set, the target operation is resolved is canceled instead of failed.
40+
temporal.api.failure.v1.Failure failure = 2;
41+
}
42+
}
43+
44+
// Information about a standalone callback execution.
45+
message CallbackExecutionInfo {
46+
// Unique identifier of this callback within its namespace.
47+
string callback_id = 1;
48+
49+
// Run ID of the callback execution.
50+
string run_id = 2;
51+
52+
// Information on how this callback should be invoked (e.g. its URL and type).
53+
temporal.api.common.v1.Callback callback = 3;
54+
55+
// A general status for this callback, indicates whether it is currently running or in one of the terminal statuses.
56+
temporal.api.enums.v1.CallbackExecutionStatus status = 4;
57+
58+
// The detailed state of this callback, provides more granular information than the general status.
59+
temporal.api.enums.v1.CallbackState state = 5;
60+
61+
// The number of attempts made to deliver the callback.
62+
// This number represents a minimum bound since the attempt is incremented after the callback request completes.
63+
int32 attempt = 6;
64+
65+
// The time when the callback was created/scheduled.
66+
google.protobuf.Timestamp create_time = 7;
67+
68+
// The time when the last attempt completed.
69+
google.protobuf.Timestamp last_attempt_complete_time = 8;
70+
71+
// The last attempt's failure, if any.
72+
temporal.api.failure.v1.Failure last_attempt_failure = 9;
73+
74+
// The time when the next attempt is scheduled.
75+
google.protobuf.Timestamp next_attempt_schedule_time = 10;
76+
77+
// If the state is BLOCKED, provides additional information.
78+
string blocked_reason = 11;
79+
80+
// Time when the callback transitioned to a terminal state.
81+
google.protobuf.Timestamp close_time = 12;
82+
83+
// Search attributes for indexing.
84+
temporal.api.common.v1.SearchAttributes search_attributes = 13;
85+
86+
// Schedule-to-close timeout for this callback.
87+
// (-- api-linter: core::0140::prepositions=disabled
88+
// aip.dev/not-precedent: "to" is used to indicate interval. --)
89+
google.protobuf.Duration schedule_to_close_timeout = 14;
90+
91+
// Incremented each time the callback's state is mutated in persistence.
92+
int64 state_transition_count = 15;
93+
}
94+
95+
// Limited callback information returned in the list response.
96+
message CallbackExecutionListInfo {
97+
// Unique identifier of this callback within its namespace.
98+
string callback_id = 1;
99+
100+
// Run ID of the callback execution.
101+
string run_id = 2;
102+
103+
// Only running and terminal statuses appear here. More detailed information in CallbackExecutionInfo but not
104+
// available in the list response.
105+
temporal.api.enums.v1.CallbackExecutionStatus status = 3;
106+
107+
// The time when the callback was created/scheduled.
108+
google.protobuf.Timestamp create_time = 4;
109+
110+
// Time when the callback transitioned to a terminal state.
111+
google.protobuf.Timestamp close_time = 5;
112+
113+
// Search attributes from the start request.
114+
temporal.api.common.v1.SearchAttributes search_attributes = 6;
115+
116+
// Incremented each time the callback's state is mutated.
117+
int64 state_transition_count = 7;
118+
}
119+
120+
18121
// Common callback information. Specific CallbackInfo messages should embed this and may include additional fields.
19122
message CallbackInfo {
20123
// Information on how this callback should be invoked (e.g. its URL and type).
@@ -34,4 +137,4 @@ message CallbackInfo {
34137
google.protobuf.Timestamp next_attempt_schedule_time = 7;
35138
// If the state is BLOCKED, blocked reason provides additional information.
36139
string blocked_reason = 8;
37-
}
140+
}

temporal/api/common/v1/message.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ message Callback {
181181
string url = 1;
182182
// Header to attach to callback request.
183183
map<string, string> header = 2;
184+
// Standard token to use for identifying the callback, used for completion.
185+
string token = 3;
184186
}
185187

186188
// Callbacks to be delivered internally within the system.

temporal/api/enums/v1/common.proto

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@ enum CallbackState {
4949
CALLBACK_STATE_SUCCEEDED = 5;
5050
// Callback is blocked (eg: by circuit breaker).
5151
CALLBACK_STATE_BLOCKED = 6;
52+
// Callback was terminated via TerminateCallbackExecution. Only possible for standalone callbacks.
53+
CALLBACK_STATE_TERMINATED = 7;
54+
}
55+
56+
// Status of a callback execution.
57+
// The status is only updated twice. First, when the callback is scheduled. And second, when the
58+
// callback reaches a terminal status.
59+
// (-- api-linter: core::0216::synonyms=disabled
60+
// aip.dev/not-precedent: To be consistent with other enums like ActivityExecutionStatus. --)
61+
enum CallbackExecutionStatus {
62+
// Default value, unspecified status.
63+
CALLBACK_EXECUTION_STATUS_UNSPECIFIED = 0;
64+
// Callback execution is running.
65+
CALLBACK_EXECUTION_STATUS_RUNNING = 1;
66+
// Callback has succeeded.
67+
CALLBACK_EXECUTION_STATUS_SUCCEEDED = 2;
68+
// Callback has failed.
69+
CALLBACK_EXECUTION_STATUS_FAILED = 3;
70+
// Callback was terminated via TerminateCallbackExecution.
71+
CALLBACK_EXECUTION_STATUS_TERMINATED = 4;
5272
}
5373

5474
// State of a pending Nexus operation.

temporal/api/errordetails/v1/message.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,13 @@ message ActivityExecutionAlreadyStartedFailure {
130130
string run_id = 2;
131131
}
132132

133+
// An error indicating that a callback execution failed to start because a callback with the given
134+
// callback ID already exists in this namespace.
135+
message CallbackExecutionAlreadyStartedFailure {
136+
string start_request_id = 1;
137+
string run_id = 2;
138+
}
139+
133140
// An error indicating that a Nexus operation failed to start. Returned when there is an existing operation with the
134141
// given operation ID, and the given ID reuse and conflict policies do not permit starting a new one or attaching to an
135142
// existing one.

temporal/api/nexus/v1/message.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ message StartOperationRequest {
6464
map<string, string> callback_header = 6;
6565
// Links contain caller information and can be attached to the operations started by the handler.
6666
repeated Link links = 7;
67+
// Callback token, to uniquely identify the callback as applicable.
68+
string callback_token = 8;
6769
}
6870

6971
// A request to cancel an operation.

temporal/api/workflowservice/v1/request_response.proto

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import "temporal/api/enums/v1/update.proto";
2222
import "temporal/api/enums/v1/activity.proto";
2323
import "temporal/api/enums/v1/nexus.proto";
2424
import "temporal/api/activity/v1/message.proto";
25+
import "temporal/api/callback/v1/message.proto";
2526
import "temporal/api/common/v1/message.proto";
2627
import "temporal/api/history/v1/message.proto";
2728
import "temporal/api/workflow/v1/message.proto";
@@ -3387,3 +3388,142 @@ message DeleteNexusOperationExecutionRequest {
33873388

33883389
message DeleteNexusOperationExecutionResponse {
33893390
}
3391+
3392+
message StartCallbackExecutionRequest {
3393+
string namespace = 1;
3394+
// The identity of the client who initiated this request.
3395+
string identity = 2;
3396+
// A unique identifier for this start request. Typically UUIDv4.
3397+
string request_id = 3;
3398+
// Identifier for this callback. Required. Must be unique among callbacks in the same namespace.
3399+
// If a callback with this ID already exists, the request will fail with CallbackExecutionAlreadyStarted.
3400+
string callback_id = 4;
3401+
// Information on how this callback should be invoked (e.g. its URL and type).
3402+
temporal.api.common.v1.Callback callback = 5;
3403+
// Schedule-to-close timeout for this callback.
3404+
// (-- api-linter: core::0140::prepositions=disabled
3405+
// aip.dev/not-precedent: "to" is used to indicate interval. --)
3406+
google.protobuf.Duration schedule_to_close_timeout = 6;
3407+
// Search attributes for indexing.
3408+
temporal.api.common.v1.SearchAttributes search_attributes = 7;
3409+
// The input data to deliver to the callback URL.
3410+
oneof input {
3411+
// The Nexus completion data to deliver to the callback URL.
3412+
// Contains either a successful result payload or a failure.
3413+
temporal.api.callback.v1.CallbackExecutionCompletion completion = 8;
3414+
}
3415+
}
3416+
3417+
message StartCallbackExecutionResponse {
3418+
// The run ID of the callback that was started.
3419+
string run_id = 1;
3420+
}
3421+
3422+
message DescribeCallbackExecutionRequest {
3423+
string namespace = 1;
3424+
// Identifier for the callback
3425+
string callback_id = 2;
3426+
// Run ID of the callback execution to describe. If empty, the latest run will be described.
3427+
string run_id = 3;
3428+
// Include the input field in the response.
3429+
bool include_input = 4;
3430+
// Include the outcome (result/failure) in the response if the callback has completed.
3431+
bool include_outcome = 5;
3432+
// Token from a previous DescribeCallbackExecutionResponse. If present, long-poll until callback
3433+
// state changes from the state encoded in this token. If absent, return current state immediately.
3434+
// Note that callback state may change multiple times between requests, therefore it is not
3435+
// guaranteed that a client making a sequence of long-poll requests will see a complete
3436+
// sequence of state changes.
3437+
bytes long_poll_token = 6;
3438+
}
3439+
3440+
message DescribeCallbackExecutionResponse {
3441+
// Information about the callback execution.
3442+
temporal.api.callback.v1.CallbackExecutionInfo info = 1;
3443+
// Only set if the callback is completed and include_outcome was true in the request.
3444+
temporal.api.callback.v1.CallbackExecutionOutcome outcome = 2;
3445+
// Token for follow-on long-poll requests. Absent only if the callback is complete.
3446+
bytes long_poll_token = 3;
3447+
}
3448+
3449+
message PollCallbackExecutionRequest {
3450+
string namespace = 1;
3451+
// Identifier for the callback
3452+
string callback_id = 2;
3453+
// Run ID of the callback execution to poll. If empty, the latest run will be polled.
3454+
string run_id = 3;
3455+
}
3456+
3457+
message PollCallbackExecutionResponse {
3458+
// The run ID of the callback, useful when run_id was not specified in the request.
3459+
string run_id = 1;
3460+
temporal.api.callback.v1.CallbackExecutionOutcome outcome = 2;
3461+
}
3462+
3463+
message ListCallbackExecutionsRequest {
3464+
string namespace = 1;
3465+
// Max number of executions to return per page.
3466+
int32 page_size = 2;
3467+
// Token returned in ListCallbackExecutionsResponse.
3468+
bytes next_page_token = 3;
3469+
// Visibility query, see https://docs.temporal.io/list-filter for the syntax.
3470+
string query = 4;
3471+
}
3472+
3473+
message ListCallbackExecutionsResponse {
3474+
repeated temporal.api.callback.v1.CallbackExecutionListInfo executions = 1;
3475+
// Token to use to fetch the next page. If empty, there is no next page.
3476+
bytes next_page_token = 2;
3477+
}
3478+
3479+
message CountCallbackExecutionsRequest {
3480+
string namespace = 1;
3481+
// Visibility query, see https://docs.temporal.io/list-filter for the syntax.
3482+
string query = 2;
3483+
}
3484+
3485+
message CountCallbackExecutionsResponse {
3486+
// If `query` is not grouping by any field, the count is an approximate number
3487+
// of callbacks that match the query.
3488+
// If `query` is grouping by a field, the count is simply the sum of the counts
3489+
// of the groups returned in the response. This number can be smaller than the
3490+
// total number of callbacks matching the query.
3491+
int64 count = 1;
3492+
3493+
// Contains the groups if the request is grouping by a field.
3494+
// The list might not be complete, and the counts of each group is approximate.
3495+
repeated AggregationGroup groups = 2;
3496+
3497+
message AggregationGroup {
3498+
repeated temporal.api.common.v1.Payload group_values = 1;
3499+
int64 count = 2;
3500+
}
3501+
}
3502+
3503+
message TerminateCallbackExecutionRequest {
3504+
string namespace = 1;
3505+
// Identifier for the callback
3506+
string callback_id = 2;
3507+
// Run ID of the callback execution to terminate. If empty, the latest run will be terminated.
3508+
string run_id = 3;
3509+
// The identity of the worker/client.
3510+
string identity = 4;
3511+
// Used to de-dupe termination requests.
3512+
string request_id = 5;
3513+
// Reason for requesting the termination.
3514+
string reason = 6;
3515+
}
3516+
3517+
message TerminateCallbackExecutionResponse {
3518+
}
3519+
3520+
message DeleteCallbackExecutionRequest {
3521+
string namespace = 1;
3522+
// Identifier for the callback
3523+
string callback_id = 2;
3524+
// Run ID of the callback execution to delete. If empty, the latest run will be deleted.
3525+
string run_id = 3;
3526+
}
3527+
3528+
message DeleteCallbackExecutionResponse {
3529+
}

0 commit comments

Comments
 (0)