Skip to content

Commit 1064b19

Browse files
committed
Add Stand Alone Callbacks (rebase)
1 parent 8e0453c commit 1064b19

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";
@@ -3544,3 +3545,142 @@ message DeleteNexusOperationExecutionRequest {
35443545

35453546
message DeleteNexusOperationExecutionResponse {
35463547
}
3548+
3549+
message StartCallbackExecutionRequest {
3550+
string namespace = 1;
3551+
// The identity of the client who initiated this request.
3552+
string identity = 2;
3553+
// A unique identifier for this start request. Typically UUIDv4.
3554+
string request_id = 3;
3555+
// Identifier for this callback. Required. Must be unique among callbacks in the same namespace.
3556+
// If a callback with this ID already exists, the request will fail with CallbackExecutionAlreadyStarted.
3557+
string callback_id = 4;
3558+
// Information on how this callback should be invoked (e.g. its URL and type).
3559+
temporal.api.common.v1.Callback callback = 5;
3560+
// Schedule-to-close timeout for this callback.
3561+
// (-- api-linter: core::0140::prepositions=disabled
3562+
// aip.dev/not-precedent: "to" is used to indicate interval. --)
3563+
google.protobuf.Duration schedule_to_close_timeout = 6;
3564+
// Search attributes for indexing.
3565+
temporal.api.common.v1.SearchAttributes search_attributes = 7;
3566+
// The input data to deliver to the callback URL.
3567+
oneof input {
3568+
// The Nexus completion data to deliver to the callback URL.
3569+
// Contains either a successful result payload or a failure.
3570+
temporal.api.callback.v1.CallbackExecutionCompletion completion = 8;
3571+
}
3572+
}
3573+
3574+
message StartCallbackExecutionResponse {
3575+
// The run ID of the callback that was started.
3576+
string run_id = 1;
3577+
}
3578+
3579+
message DescribeCallbackExecutionRequest {
3580+
string namespace = 1;
3581+
// Identifier for the callback
3582+
string callback_id = 2;
3583+
// Run ID of the callback execution to describe. If empty, the latest run will be described.
3584+
string run_id = 3;
3585+
// Include the input field in the response.
3586+
bool include_input = 4;
3587+
// Include the outcome (result/failure) in the response if the callback has completed.
3588+
bool include_outcome = 5;
3589+
// Token from a previous DescribeCallbackExecutionResponse. If present, long-poll until callback
3590+
// state changes from the state encoded in this token. If absent, return current state immediately.
3591+
// Note that callback state may change multiple times between requests, therefore it is not
3592+
// guaranteed that a client making a sequence of long-poll requests will see a complete
3593+
// sequence of state changes.
3594+
bytes long_poll_token = 6;
3595+
}
3596+
3597+
message DescribeCallbackExecutionResponse {
3598+
// Information about the callback execution.
3599+
temporal.api.callback.v1.CallbackExecutionInfo info = 1;
3600+
// Only set if the callback is completed and include_outcome was true in the request.
3601+
temporal.api.callback.v1.CallbackExecutionOutcome outcome = 2;
3602+
// Token for follow-on long-poll requests. Absent only if the callback is complete.
3603+
bytes long_poll_token = 3;
3604+
}
3605+
3606+
message PollCallbackExecutionRequest {
3607+
string namespace = 1;
3608+
// Identifier for the callback
3609+
string callback_id = 2;
3610+
// Run ID of the callback execution to poll. If empty, the latest run will be polled.
3611+
string run_id = 3;
3612+
}
3613+
3614+
message PollCallbackExecutionResponse {
3615+
// The run ID of the callback, useful when run_id was not specified in the request.
3616+
string run_id = 1;
3617+
temporal.api.callback.v1.CallbackExecutionOutcome outcome = 2;
3618+
}
3619+
3620+
message ListCallbackExecutionsRequest {
3621+
string namespace = 1;
3622+
// Max number of executions to return per page.
3623+
int32 page_size = 2;
3624+
// Token returned in ListCallbackExecutionsResponse.
3625+
bytes next_page_token = 3;
3626+
// Visibility query, see https://docs.temporal.io/list-filter for the syntax.
3627+
string query = 4;
3628+
}
3629+
3630+
message ListCallbackExecutionsResponse {
3631+
repeated temporal.api.callback.v1.CallbackExecutionListInfo executions = 1;
3632+
// Token to use to fetch the next page. If empty, there is no next page.
3633+
bytes next_page_token = 2;
3634+
}
3635+
3636+
message CountCallbackExecutionsRequest {
3637+
string namespace = 1;
3638+
// Visibility query, see https://docs.temporal.io/list-filter for the syntax.
3639+
string query = 2;
3640+
}
3641+
3642+
message CountCallbackExecutionsResponse {
3643+
// If `query` is not grouping by any field, the count is an approximate number
3644+
// of callbacks that match the query.
3645+
// If `query` is grouping by a field, the count is simply the sum of the counts
3646+
// of the groups returned in the response. This number can be smaller than the
3647+
// total number of callbacks matching the query.
3648+
int64 count = 1;
3649+
3650+
// Contains the groups if the request is grouping by a field.
3651+
// The list might not be complete, and the counts of each group is approximate.
3652+
repeated AggregationGroup groups = 2;
3653+
3654+
message AggregationGroup {
3655+
repeated temporal.api.common.v1.Payload group_values = 1;
3656+
int64 count = 2;
3657+
}
3658+
}
3659+
3660+
message TerminateCallbackExecutionRequest {
3661+
string namespace = 1;
3662+
// Identifier for the callback
3663+
string callback_id = 2;
3664+
// Run ID of the callback execution to terminate. If empty, the latest run will be terminated.
3665+
string run_id = 3;
3666+
// The identity of the worker/client.
3667+
string identity = 4;
3668+
// Used to de-dupe termination requests.
3669+
string request_id = 5;
3670+
// Reason for requesting the termination.
3671+
string reason = 6;
3672+
}
3673+
3674+
message TerminateCallbackExecutionResponse {
3675+
}
3676+
3677+
message DeleteCallbackExecutionRequest {
3678+
string namespace = 1;
3679+
// Identifier for the callback
3680+
string callback_id = 2;
3681+
// Run ID of the callback execution to delete. If empty, the latest run will be deleted.
3682+
string run_id = 3;
3683+
}
3684+
3685+
message DeleteCallbackExecutionResponse {
3686+
}

0 commit comments

Comments
 (0)