From 345b0dc492f0f7cfcead9545518fda604f913404 Mon Sep 17 00:00:00 2001 From: Maruthi ChandraSekhar Vemuri Date: Mon, 17 Aug 2026 20:22:40 -0700 Subject: [PATCH 1/2] WIP/draft-apis: move temporal/api to temporal/api_next --- temporal/{api => api_next}/activity/v1/message.proto | 0 temporal/{api => api_next}/batch/v1/message.proto | 0 temporal/{api => api_next}/callback/v1/message.proto | 0 temporal/{api => api_next}/command/v1/message.proto | 0 temporal/{api => api_next}/common/v1/message.proto | 0 temporal/{api => api_next}/compute/v1/config.proto | 0 temporal/{api => api_next}/compute/v1/provider.proto | 0 temporal/{api => api_next}/compute/v1/scaler.proto | 0 temporal/{api => api_next}/deployment/v1/message.proto | 0 temporal/{api => api_next}/enums/v1/activity.proto | 0 temporal/{api => api_next}/enums/v1/batch_operation.proto | 0 temporal/{api => api_next}/enums/v1/command_type.proto | 0 temporal/{api => api_next}/enums/v1/common.proto | 0 temporal/{api => api_next}/enums/v1/deployment.proto | 0 temporal/{api => api_next}/enums/v1/event_type.proto | 0 temporal/{api => api_next}/enums/v1/failed_cause.proto | 0 temporal/{api => api_next}/enums/v1/namespace.proto | 0 temporal/{api => api_next}/enums/v1/nexus.proto | 0 temporal/{api => api_next}/enums/v1/query.proto | 0 temporal/{api => api_next}/enums/v1/reset.proto | 0 temporal/{api => api_next}/enums/v1/schedule.proto | 0 temporal/{api => api_next}/enums/v1/task_queue.proto | 0 temporal/{api => api_next}/enums/v1/time_skipping.proto | 0 temporal/{api => api_next}/enums/v1/update.proto | 0 temporal/{api => api_next}/enums/v1/workflow.proto | 0 temporal/{api => api_next}/errordetails/v1/message.proto | 0 temporal/{api => api_next}/export/v1/message.proto | 0 temporal/{api => api_next}/failure/v1/message.proto | 0 temporal/{api => api_next}/filter/v1/message.proto | 0 temporal/{api => api_next}/history/v1/message.proto | 0 temporal/{api => api_next}/namespace/v1/message.proto | 0 temporal/{api => api_next}/nexus/v1/message.proto | 0 .../nexusservices/workerservice/v1/request_response.proto | 0 .../{api => api_next}/operatorservice/v1/request_response.proto | 0 temporal/{api => api_next}/operatorservice/v1/service.proto | 0 temporal/{api => api_next}/protocol/v1/message.proto | 0 temporal/{api => api_next}/protometa/v1/annotations.proto | 0 temporal/{api => api_next}/query/v1/message.proto | 0 temporal/{api => api_next}/replication/v1/message.proto | 0 temporal/{api => api_next}/rules/v1/message.proto | 0 temporal/{api => api_next}/schedule/v1/message.proto | 0 temporal/{api => api_next}/sdk/v1/enhanced_stack_trace.proto | 0 temporal/{api => api_next}/sdk/v1/event_group_marker.proto | 0 temporal/{api => api_next}/sdk/v1/external_storage.proto | 0 temporal/{api => api_next}/sdk/v1/task_complete_metadata.proto | 0 temporal/{api => api_next}/sdk/v1/user_metadata.proto | 0 temporal/{api => api_next}/sdk/v1/worker_config.proto | 0 temporal/{api => api_next}/sdk/v1/workflow_metadata.proto | 0 temporal/{api => api_next}/taskqueue/v1/message.proto | 0 temporal/{api => api_next}/update/v1/message.proto | 0 temporal/{api => api_next}/version/v1/message.proto | 0 temporal/{api => api_next}/worker/v1/message.proto | 0 temporal/{api => api_next}/workflow/v1/message.proto | 0 .../{api => api_next}/workflowservice/v1/request_response.proto | 0 temporal/{api => api_next}/workflowservice/v1/service.proto | 0 55 files changed, 0 insertions(+), 0 deletions(-) rename temporal/{api => api_next}/activity/v1/message.proto (100%) rename temporal/{api => api_next}/batch/v1/message.proto (100%) rename temporal/{api => api_next}/callback/v1/message.proto (100%) rename temporal/{api => api_next}/command/v1/message.proto (100%) rename temporal/{api => api_next}/common/v1/message.proto (100%) rename temporal/{api => api_next}/compute/v1/config.proto (100%) rename temporal/{api => api_next}/compute/v1/provider.proto (100%) rename temporal/{api => api_next}/compute/v1/scaler.proto (100%) rename temporal/{api => api_next}/deployment/v1/message.proto (100%) rename temporal/{api => api_next}/enums/v1/activity.proto (100%) rename temporal/{api => api_next}/enums/v1/batch_operation.proto (100%) rename temporal/{api => api_next}/enums/v1/command_type.proto (100%) rename temporal/{api => api_next}/enums/v1/common.proto (100%) rename temporal/{api => api_next}/enums/v1/deployment.proto (100%) rename temporal/{api => api_next}/enums/v1/event_type.proto (100%) rename temporal/{api => api_next}/enums/v1/failed_cause.proto (100%) rename temporal/{api => api_next}/enums/v1/namespace.proto (100%) rename temporal/{api => api_next}/enums/v1/nexus.proto (100%) rename temporal/{api => api_next}/enums/v1/query.proto (100%) rename temporal/{api => api_next}/enums/v1/reset.proto (100%) rename temporal/{api => api_next}/enums/v1/schedule.proto (100%) rename temporal/{api => api_next}/enums/v1/task_queue.proto (100%) rename temporal/{api => api_next}/enums/v1/time_skipping.proto (100%) rename temporal/{api => api_next}/enums/v1/update.proto (100%) rename temporal/{api => api_next}/enums/v1/workflow.proto (100%) rename temporal/{api => api_next}/errordetails/v1/message.proto (100%) rename temporal/{api => api_next}/export/v1/message.proto (100%) rename temporal/{api => api_next}/failure/v1/message.proto (100%) rename temporal/{api => api_next}/filter/v1/message.proto (100%) rename temporal/{api => api_next}/history/v1/message.proto (100%) rename temporal/{api => api_next}/namespace/v1/message.proto (100%) rename temporal/{api => api_next}/nexus/v1/message.proto (100%) rename temporal/{api => api_next}/nexusservices/workerservice/v1/request_response.proto (100%) rename temporal/{api => api_next}/operatorservice/v1/request_response.proto (100%) rename temporal/{api => api_next}/operatorservice/v1/service.proto (100%) rename temporal/{api => api_next}/protocol/v1/message.proto (100%) rename temporal/{api => api_next}/protometa/v1/annotations.proto (100%) rename temporal/{api => api_next}/query/v1/message.proto (100%) rename temporal/{api => api_next}/replication/v1/message.proto (100%) rename temporal/{api => api_next}/rules/v1/message.proto (100%) rename temporal/{api => api_next}/schedule/v1/message.proto (100%) rename temporal/{api => api_next}/sdk/v1/enhanced_stack_trace.proto (100%) rename temporal/{api => api_next}/sdk/v1/event_group_marker.proto (100%) rename temporal/{api => api_next}/sdk/v1/external_storage.proto (100%) rename temporal/{api => api_next}/sdk/v1/task_complete_metadata.proto (100%) rename temporal/{api => api_next}/sdk/v1/user_metadata.proto (100%) rename temporal/{api => api_next}/sdk/v1/worker_config.proto (100%) rename temporal/{api => api_next}/sdk/v1/workflow_metadata.proto (100%) rename temporal/{api => api_next}/taskqueue/v1/message.proto (100%) rename temporal/{api => api_next}/update/v1/message.proto (100%) rename temporal/{api => api_next}/version/v1/message.proto (100%) rename temporal/{api => api_next}/worker/v1/message.proto (100%) rename temporal/{api => api_next}/workflow/v1/message.proto (100%) rename temporal/{api => api_next}/workflowservice/v1/request_response.proto (100%) rename temporal/{api => api_next}/workflowservice/v1/service.proto (100%) diff --git a/temporal/api/activity/v1/message.proto b/temporal/api_next/activity/v1/message.proto similarity index 100% rename from temporal/api/activity/v1/message.proto rename to temporal/api_next/activity/v1/message.proto diff --git a/temporal/api/batch/v1/message.proto b/temporal/api_next/batch/v1/message.proto similarity index 100% rename from temporal/api/batch/v1/message.proto rename to temporal/api_next/batch/v1/message.proto diff --git a/temporal/api/callback/v1/message.proto b/temporal/api_next/callback/v1/message.proto similarity index 100% rename from temporal/api/callback/v1/message.proto rename to temporal/api_next/callback/v1/message.proto diff --git a/temporal/api/command/v1/message.proto b/temporal/api_next/command/v1/message.proto similarity index 100% rename from temporal/api/command/v1/message.proto rename to temporal/api_next/command/v1/message.proto diff --git a/temporal/api/common/v1/message.proto b/temporal/api_next/common/v1/message.proto similarity index 100% rename from temporal/api/common/v1/message.proto rename to temporal/api_next/common/v1/message.proto diff --git a/temporal/api/compute/v1/config.proto b/temporal/api_next/compute/v1/config.proto similarity index 100% rename from temporal/api/compute/v1/config.proto rename to temporal/api_next/compute/v1/config.proto diff --git a/temporal/api/compute/v1/provider.proto b/temporal/api_next/compute/v1/provider.proto similarity index 100% rename from temporal/api/compute/v1/provider.proto rename to temporal/api_next/compute/v1/provider.proto diff --git a/temporal/api/compute/v1/scaler.proto b/temporal/api_next/compute/v1/scaler.proto similarity index 100% rename from temporal/api/compute/v1/scaler.proto rename to temporal/api_next/compute/v1/scaler.proto diff --git a/temporal/api/deployment/v1/message.proto b/temporal/api_next/deployment/v1/message.proto similarity index 100% rename from temporal/api/deployment/v1/message.proto rename to temporal/api_next/deployment/v1/message.proto diff --git a/temporal/api/enums/v1/activity.proto b/temporal/api_next/enums/v1/activity.proto similarity index 100% rename from temporal/api/enums/v1/activity.proto rename to temporal/api_next/enums/v1/activity.proto diff --git a/temporal/api/enums/v1/batch_operation.proto b/temporal/api_next/enums/v1/batch_operation.proto similarity index 100% rename from temporal/api/enums/v1/batch_operation.proto rename to temporal/api_next/enums/v1/batch_operation.proto diff --git a/temporal/api/enums/v1/command_type.proto b/temporal/api_next/enums/v1/command_type.proto similarity index 100% rename from temporal/api/enums/v1/command_type.proto rename to temporal/api_next/enums/v1/command_type.proto diff --git a/temporal/api/enums/v1/common.proto b/temporal/api_next/enums/v1/common.proto similarity index 100% rename from temporal/api/enums/v1/common.proto rename to temporal/api_next/enums/v1/common.proto diff --git a/temporal/api/enums/v1/deployment.proto b/temporal/api_next/enums/v1/deployment.proto similarity index 100% rename from temporal/api/enums/v1/deployment.proto rename to temporal/api_next/enums/v1/deployment.proto diff --git a/temporal/api/enums/v1/event_type.proto b/temporal/api_next/enums/v1/event_type.proto similarity index 100% rename from temporal/api/enums/v1/event_type.proto rename to temporal/api_next/enums/v1/event_type.proto diff --git a/temporal/api/enums/v1/failed_cause.proto b/temporal/api_next/enums/v1/failed_cause.proto similarity index 100% rename from temporal/api/enums/v1/failed_cause.proto rename to temporal/api_next/enums/v1/failed_cause.proto diff --git a/temporal/api/enums/v1/namespace.proto b/temporal/api_next/enums/v1/namespace.proto similarity index 100% rename from temporal/api/enums/v1/namespace.proto rename to temporal/api_next/enums/v1/namespace.proto diff --git a/temporal/api/enums/v1/nexus.proto b/temporal/api_next/enums/v1/nexus.proto similarity index 100% rename from temporal/api/enums/v1/nexus.proto rename to temporal/api_next/enums/v1/nexus.proto diff --git a/temporal/api/enums/v1/query.proto b/temporal/api_next/enums/v1/query.proto similarity index 100% rename from temporal/api/enums/v1/query.proto rename to temporal/api_next/enums/v1/query.proto diff --git a/temporal/api/enums/v1/reset.proto b/temporal/api_next/enums/v1/reset.proto similarity index 100% rename from temporal/api/enums/v1/reset.proto rename to temporal/api_next/enums/v1/reset.proto diff --git a/temporal/api/enums/v1/schedule.proto b/temporal/api_next/enums/v1/schedule.proto similarity index 100% rename from temporal/api/enums/v1/schedule.proto rename to temporal/api_next/enums/v1/schedule.proto diff --git a/temporal/api/enums/v1/task_queue.proto b/temporal/api_next/enums/v1/task_queue.proto similarity index 100% rename from temporal/api/enums/v1/task_queue.proto rename to temporal/api_next/enums/v1/task_queue.proto diff --git a/temporal/api/enums/v1/time_skipping.proto b/temporal/api_next/enums/v1/time_skipping.proto similarity index 100% rename from temporal/api/enums/v1/time_skipping.proto rename to temporal/api_next/enums/v1/time_skipping.proto diff --git a/temporal/api/enums/v1/update.proto b/temporal/api_next/enums/v1/update.proto similarity index 100% rename from temporal/api/enums/v1/update.proto rename to temporal/api_next/enums/v1/update.proto diff --git a/temporal/api/enums/v1/workflow.proto b/temporal/api_next/enums/v1/workflow.proto similarity index 100% rename from temporal/api/enums/v1/workflow.proto rename to temporal/api_next/enums/v1/workflow.proto diff --git a/temporal/api/errordetails/v1/message.proto b/temporal/api_next/errordetails/v1/message.proto similarity index 100% rename from temporal/api/errordetails/v1/message.proto rename to temporal/api_next/errordetails/v1/message.proto diff --git a/temporal/api/export/v1/message.proto b/temporal/api_next/export/v1/message.proto similarity index 100% rename from temporal/api/export/v1/message.proto rename to temporal/api_next/export/v1/message.proto diff --git a/temporal/api/failure/v1/message.proto b/temporal/api_next/failure/v1/message.proto similarity index 100% rename from temporal/api/failure/v1/message.proto rename to temporal/api_next/failure/v1/message.proto diff --git a/temporal/api/filter/v1/message.proto b/temporal/api_next/filter/v1/message.proto similarity index 100% rename from temporal/api/filter/v1/message.proto rename to temporal/api_next/filter/v1/message.proto diff --git a/temporal/api/history/v1/message.proto b/temporal/api_next/history/v1/message.proto similarity index 100% rename from temporal/api/history/v1/message.proto rename to temporal/api_next/history/v1/message.proto diff --git a/temporal/api/namespace/v1/message.proto b/temporal/api_next/namespace/v1/message.proto similarity index 100% rename from temporal/api/namespace/v1/message.proto rename to temporal/api_next/namespace/v1/message.proto diff --git a/temporal/api/nexus/v1/message.proto b/temporal/api_next/nexus/v1/message.proto similarity index 100% rename from temporal/api/nexus/v1/message.proto rename to temporal/api_next/nexus/v1/message.proto diff --git a/temporal/api/nexusservices/workerservice/v1/request_response.proto b/temporal/api_next/nexusservices/workerservice/v1/request_response.proto similarity index 100% rename from temporal/api/nexusservices/workerservice/v1/request_response.proto rename to temporal/api_next/nexusservices/workerservice/v1/request_response.proto diff --git a/temporal/api/operatorservice/v1/request_response.proto b/temporal/api_next/operatorservice/v1/request_response.proto similarity index 100% rename from temporal/api/operatorservice/v1/request_response.proto rename to temporal/api_next/operatorservice/v1/request_response.proto diff --git a/temporal/api/operatorservice/v1/service.proto b/temporal/api_next/operatorservice/v1/service.proto similarity index 100% rename from temporal/api/operatorservice/v1/service.proto rename to temporal/api_next/operatorservice/v1/service.proto diff --git a/temporal/api/protocol/v1/message.proto b/temporal/api_next/protocol/v1/message.proto similarity index 100% rename from temporal/api/protocol/v1/message.proto rename to temporal/api_next/protocol/v1/message.proto diff --git a/temporal/api/protometa/v1/annotations.proto b/temporal/api_next/protometa/v1/annotations.proto similarity index 100% rename from temporal/api/protometa/v1/annotations.proto rename to temporal/api_next/protometa/v1/annotations.proto diff --git a/temporal/api/query/v1/message.proto b/temporal/api_next/query/v1/message.proto similarity index 100% rename from temporal/api/query/v1/message.proto rename to temporal/api_next/query/v1/message.proto diff --git a/temporal/api/replication/v1/message.proto b/temporal/api_next/replication/v1/message.proto similarity index 100% rename from temporal/api/replication/v1/message.proto rename to temporal/api_next/replication/v1/message.proto diff --git a/temporal/api/rules/v1/message.proto b/temporal/api_next/rules/v1/message.proto similarity index 100% rename from temporal/api/rules/v1/message.proto rename to temporal/api_next/rules/v1/message.proto diff --git a/temporal/api/schedule/v1/message.proto b/temporal/api_next/schedule/v1/message.proto similarity index 100% rename from temporal/api/schedule/v1/message.proto rename to temporal/api_next/schedule/v1/message.proto diff --git a/temporal/api/sdk/v1/enhanced_stack_trace.proto b/temporal/api_next/sdk/v1/enhanced_stack_trace.proto similarity index 100% rename from temporal/api/sdk/v1/enhanced_stack_trace.proto rename to temporal/api_next/sdk/v1/enhanced_stack_trace.proto diff --git a/temporal/api/sdk/v1/event_group_marker.proto b/temporal/api_next/sdk/v1/event_group_marker.proto similarity index 100% rename from temporal/api/sdk/v1/event_group_marker.proto rename to temporal/api_next/sdk/v1/event_group_marker.proto diff --git a/temporal/api/sdk/v1/external_storage.proto b/temporal/api_next/sdk/v1/external_storage.proto similarity index 100% rename from temporal/api/sdk/v1/external_storage.proto rename to temporal/api_next/sdk/v1/external_storage.proto diff --git a/temporal/api/sdk/v1/task_complete_metadata.proto b/temporal/api_next/sdk/v1/task_complete_metadata.proto similarity index 100% rename from temporal/api/sdk/v1/task_complete_metadata.proto rename to temporal/api_next/sdk/v1/task_complete_metadata.proto diff --git a/temporal/api/sdk/v1/user_metadata.proto b/temporal/api_next/sdk/v1/user_metadata.proto similarity index 100% rename from temporal/api/sdk/v1/user_metadata.proto rename to temporal/api_next/sdk/v1/user_metadata.proto diff --git a/temporal/api/sdk/v1/worker_config.proto b/temporal/api_next/sdk/v1/worker_config.proto similarity index 100% rename from temporal/api/sdk/v1/worker_config.proto rename to temporal/api_next/sdk/v1/worker_config.proto diff --git a/temporal/api/sdk/v1/workflow_metadata.proto b/temporal/api_next/sdk/v1/workflow_metadata.proto similarity index 100% rename from temporal/api/sdk/v1/workflow_metadata.proto rename to temporal/api_next/sdk/v1/workflow_metadata.proto diff --git a/temporal/api/taskqueue/v1/message.proto b/temporal/api_next/taskqueue/v1/message.proto similarity index 100% rename from temporal/api/taskqueue/v1/message.proto rename to temporal/api_next/taskqueue/v1/message.proto diff --git a/temporal/api/update/v1/message.proto b/temporal/api_next/update/v1/message.proto similarity index 100% rename from temporal/api/update/v1/message.proto rename to temporal/api_next/update/v1/message.proto diff --git a/temporal/api/version/v1/message.proto b/temporal/api_next/version/v1/message.proto similarity index 100% rename from temporal/api/version/v1/message.proto rename to temporal/api_next/version/v1/message.proto diff --git a/temporal/api/worker/v1/message.proto b/temporal/api_next/worker/v1/message.proto similarity index 100% rename from temporal/api/worker/v1/message.proto rename to temporal/api_next/worker/v1/message.proto diff --git a/temporal/api/workflow/v1/message.proto b/temporal/api_next/workflow/v1/message.proto similarity index 100% rename from temporal/api/workflow/v1/message.proto rename to temporal/api_next/workflow/v1/message.proto diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api_next/workflowservice/v1/request_response.proto similarity index 100% rename from temporal/api/workflowservice/v1/request_response.proto rename to temporal/api_next/workflowservice/v1/request_response.proto diff --git a/temporal/api/workflowservice/v1/service.proto b/temporal/api_next/workflowservice/v1/service.proto similarity index 100% rename from temporal/api/workflowservice/v1/service.proto rename to temporal/api_next/workflowservice/v1/service.proto From 5c087320597da912d6b16ba00735d7ed1cdb177a Mon Sep 17 00:00:00 2001 From: Maruthi ChandraSekhar Vemuri Date: Mon, 17 Aug 2026 20:23:07 -0700 Subject: [PATCH 2/2] WIP/draft-apis: adding tooling for generating stable and next(bleeding) APIs --- .github/workflows/ci.yml | 25 + .gitignore | 1 + Makefile | 33 +- README.md | 2 +- api-linter.yaml | 7 + buf.next.yaml | 26 + buf.stable.gen.yaml | 5 + buf.yaml | 2 + cmd/generate-stable/README.md | 17 + cmd/generate-stable/catalog.go | 237 + cmd/generate-stable/catalog_test.go | 153 + cmd/generate-stable/go.mod | 8 + cmd/generate-stable/go.sum | 28 + cmd/generate-stable/golden_test.go | 603 +++ cmd/generate-stable/main.go | 101 + cmd/generate-stable/main_test.go | 217 + cmd/generate-stable/schema.go | 326 ++ cmd/generate-stable/sourceinfo.go | 234 + cmd/generate-stable/sourceinfo_test.go | 406 ++ temporal/api/activity/v1/message.proto | 281 ++ temporal/api/batch/v1/message.proto | 239 + temporal/api/callback/v1/message.proto | 45 + temporal/api/command/v1/message.proto | 405 ++ temporal/api/common/v1/message.proto | 544 +++ temporal/api/compute/v1/config.proto | 70 + temporal/api/compute/v1/provider.proto | 37 + temporal/api/compute/v1/scaler.proto | 30 + temporal/api/deployment/v1/message.proto | 393 ++ temporal/api/enums/v1/activity.proto | 92 + temporal/api/enums/v1/batch_operation.proto | 68 + temporal/api/enums/v1/command_type.proto | 51 + temporal/api/enums/v1/common.proto | 154 + temporal/api/enums/v1/deployment.proto | 115 + temporal/api/enums/v1/event_type.proto | 240 + temporal/api/enums/v1/failed_cause.proto | 206 + temporal/api/enums/v1/namespace.proto | 38 + temporal/api/enums/v1/nexus.proto | 99 + temporal/api/enums/v1/query.proto | 33 + temporal/api/enums/v1/reset.proto | 56 + temporal/api/enums/v1/schedule.proto | 45 + temporal/api/enums/v1/task_queue.proto | 143 + temporal/api/enums/v1/time_skipping.proto | 35 + temporal/api/enums/v1/update.proto | 51 + temporal/api/enums/v1/workflow.proto | 269 ++ temporal/api/errordetails/v1/message.proto | 159 + temporal/api/export/v1/message.proto | 24 + temporal/api/failure/v1/message.proto | 173 + temporal/api/filter/v1/message.proto | 35 + temporal/api/history/v1/message.proto | 1631 +++++++ temporal/api/namespace/v1/message.proto | 170 + temporal/api/nexus/v1/message.proto | 416 ++ .../workerservice/v1/request_response.proto | 29 + .../operatorservice/v1/request_response.proto | 195 + temporal/api/operatorservice/v1/service.proto | 119 + temporal/api/protocol/v1/message.proto | 38 + temporal/api/protometa/v1/annotations.proto | 39 + temporal/api/query/v1/message.proto | 53 + temporal/api/replication/v1/message.proto | 35 + temporal/api/rules/v1/message.proto | 90 + temporal/api/schedule/v1/message.proto | 434 ++ .../api/sdk/v1/enhanced_stack_trace.proto | 76 + temporal/api/sdk/v1/event_group_marker.proto | 67 + temporal/api/sdk/v1/external_storage.proto | 23 + .../api/sdk/v1/task_complete_metadata.proto | 56 + temporal/api/sdk/v1/user_metadata.proto | 28 + temporal/api/sdk/v1/worker_config.proto | 39 + temporal/api/sdk/v1/workflow_metadata.proto | 53 + temporal/api/taskqueue/v1/message.proto | 402 ++ temporal/api/update/v1/message.proto | 108 + temporal/api/version/v1/message.proto | 44 + temporal/api/worker/v1/message.proto | 395 ++ temporal/api/workflow/v1/message.proto | 860 ++++ .../workflowservice/v1/request_response.proto | 4285 +++++++++++++++++ temporal/api/workflowservice/v1/service.proto | 2158 +++++++++ temporal/api_next/activity/v1/message.proto | 16 +- temporal/api_next/batch/v1/message.proto | 12 +- temporal/api_next/callback/v1/message.proto | 6 +- temporal/api_next/command/v1/message.proto | 16 +- temporal/api_next/common/v1/message.proto | 6 +- temporal/api_next/compute/v1/config.proto | 6 +- temporal/api_next/compute/v1/provider.proto | 2 +- temporal/api_next/compute/v1/scaler.proto | 2 +- temporal/api_next/deployment/v1/message.proto | 10 +- .../api_next/errordetails/v1/message.proto | 8 +- temporal/api_next/export/v1/message.proto | 2 +- temporal/api_next/failure/v1/message.proto | 8 +- temporal/api_next/filter/v1/message.proto | 2 +- temporal/api_next/history/v1/message.proto | 26 +- temporal/api_next/namespace/v1/message.proto | 2 +- temporal/api_next/nexus/v1/message.proto | 13 +- .../workerservice/v1/request_response.proto | 2 +- .../operatorservice/v1/request_response.proto | 4 +- .../api_next/operatorservice/v1/service.proto | 2 +- .../api_next/protometa/v1/annotations.proto | 2 +- .../api_next/protometa/v1/experimental.proto | 38 + temporal/api_next/query/v1/message.proto | 8 +- .../api_next/replication/v1/message.proto | 2 +- temporal/api_next/schedule/v1/message.proto | 8 +- .../api_next/sdk/v1/event_group_marker.proto | 2 +- temporal/api_next/sdk/v1/user_metadata.proto | 2 +- temporal/api_next/taskqueue/v1/message.proto | 6 +- temporal/api_next/update/v1/message.proto | 6 +- temporal/api_next/version/v1/message.proto | 2 +- temporal/api_next/worker/v1/message.proto | 4 +- temporal/api_next/workflow/v1/message.proto | 18 +- .../workflowservice/v1/request_response.proto | 74 +- .../api_next/workflowservice/v1/service.proto | 4 +- 107 files changed, 18579 insertions(+), 146 deletions(-) create mode 100644 buf.next.yaml create mode 100644 buf.stable.gen.yaml create mode 100644 cmd/generate-stable/README.md create mode 100644 cmd/generate-stable/catalog.go create mode 100644 cmd/generate-stable/catalog_test.go create mode 100644 cmd/generate-stable/go.mod create mode 100644 cmd/generate-stable/go.sum create mode 100644 cmd/generate-stable/golden_test.go create mode 100644 cmd/generate-stable/main.go create mode 100644 cmd/generate-stable/main_test.go create mode 100644 cmd/generate-stable/schema.go create mode 100644 cmd/generate-stable/sourceinfo.go create mode 100644 cmd/generate-stable/sourceinfo_test.go create mode 100644 temporal/api/activity/v1/message.proto create mode 100644 temporal/api/batch/v1/message.proto create mode 100644 temporal/api/callback/v1/message.proto create mode 100644 temporal/api/command/v1/message.proto create mode 100644 temporal/api/common/v1/message.proto create mode 100644 temporal/api/compute/v1/config.proto create mode 100644 temporal/api/compute/v1/provider.proto create mode 100644 temporal/api/compute/v1/scaler.proto create mode 100644 temporal/api/deployment/v1/message.proto create mode 100644 temporal/api/enums/v1/activity.proto create mode 100644 temporal/api/enums/v1/batch_operation.proto create mode 100644 temporal/api/enums/v1/command_type.proto create mode 100644 temporal/api/enums/v1/common.proto create mode 100644 temporal/api/enums/v1/deployment.proto create mode 100644 temporal/api/enums/v1/event_type.proto create mode 100644 temporal/api/enums/v1/failed_cause.proto create mode 100644 temporal/api/enums/v1/namespace.proto create mode 100644 temporal/api/enums/v1/nexus.proto create mode 100644 temporal/api/enums/v1/query.proto create mode 100644 temporal/api/enums/v1/reset.proto create mode 100644 temporal/api/enums/v1/schedule.proto create mode 100644 temporal/api/enums/v1/task_queue.proto create mode 100644 temporal/api/enums/v1/time_skipping.proto create mode 100644 temporal/api/enums/v1/update.proto create mode 100644 temporal/api/enums/v1/workflow.proto create mode 100644 temporal/api/errordetails/v1/message.proto create mode 100644 temporal/api/export/v1/message.proto create mode 100644 temporal/api/failure/v1/message.proto create mode 100644 temporal/api/filter/v1/message.proto create mode 100644 temporal/api/history/v1/message.proto create mode 100644 temporal/api/namespace/v1/message.proto create mode 100644 temporal/api/nexus/v1/message.proto create mode 100644 temporal/api/nexusservices/workerservice/v1/request_response.proto create mode 100644 temporal/api/operatorservice/v1/request_response.proto create mode 100644 temporal/api/operatorservice/v1/service.proto create mode 100644 temporal/api/protocol/v1/message.proto create mode 100644 temporal/api/protometa/v1/annotations.proto create mode 100644 temporal/api/query/v1/message.proto create mode 100644 temporal/api/replication/v1/message.proto create mode 100644 temporal/api/rules/v1/message.proto create mode 100644 temporal/api/schedule/v1/message.proto create mode 100644 temporal/api/sdk/v1/enhanced_stack_trace.proto create mode 100644 temporal/api/sdk/v1/event_group_marker.proto create mode 100644 temporal/api/sdk/v1/external_storage.proto create mode 100644 temporal/api/sdk/v1/task_complete_metadata.proto create mode 100644 temporal/api/sdk/v1/user_metadata.proto create mode 100644 temporal/api/sdk/v1/worker_config.proto create mode 100644 temporal/api/sdk/v1/workflow_metadata.proto create mode 100644 temporal/api/taskqueue/v1/message.proto create mode 100644 temporal/api/update/v1/message.proto create mode 100644 temporal/api/version/v1/message.proto create mode 100644 temporal/api/worker/v1/message.proto create mode 100644 temporal/api/workflow/v1/message.proto create mode 100644 temporal/api/workflowservice/v1/request_response.proto create mode 100644 temporal/api/workflowservice/v1/service.proto create mode 100644 temporal/api_next/protometa/v1/experimental.proto diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79b216936..69e321cc7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,3 +26,28 @@ jobs: fi - name: Check for OpenAPI path conflicts run: go run ./cmd/check-path-conflicts/main.go openapi/openapiv2.json + + stable-api-generated: + name: Verify stable-api is generated + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4.3.0 + with: + go-version: '^1.25' + - name: Install buf + run: make buf-install + - name: Test protoc-gen-stable-api + run: make stable-api-test + - name: Build protoc-gen-stable-api + run: make stable-api-plugin + - name: Regenerate temporal/api from temporal/api_next + run: make stable-api + - name: Fail if temporal/api is stale + run: | + if [[ -n $(git status --porcelain -- temporal/api) ]]; then + echo "temporal/api is out of date. Run 'make stable-api' and commit the result." + git status --porcelain -- temporal/api + git diff -- temporal/api + exit 1 + fi diff --git a/.gitignore b/.gitignore index efbf7b661..5fd9bd1b1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ *~ *.swp *.swo +bin/ diff --git a/Makefile b/Makefile index d43b05677..549672374 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,8 @@ $(VERBOSE).SILENT: ############################# Main targets ############################# ci-build: install proto http-api-docs +.PHONY: stable-api stable-api-plugin stable-api-test + # Install dependencies. install: grpc-install api-linter-install buf-install @@ -25,7 +27,9 @@ STAMPDIR := .stamp COLOR := "\e[1;36m%s\e[0m\n" PROTO_ROOT := . -PROTO_FILES = $(shell find temporal -name "*.proto") +# exclude api_next files for api-linter +PROTO_FILES = $(shell find temporal -name "*.proto" -not -path "temporal/api_next/*") +PROTO_FILES_NEXT = $(shell find temporal/api_next -name "*.proto") PROTO_DIRS = $(sort $(dir $(PROTO_FILES))) PROTO_OUT := .gen PROTO_IMPORTS = \ @@ -40,8 +44,20 @@ NEX_GEN ?= nex-gen $(PROTO_OUT): mkdir $(PROTO_OUT) +stable-api: stable-api-plugin + rm -rf temporal/api + buf generate --config buf.next.yaml --template buf.stable.gen.yaml + buf format -w temporal/api + +stable-api-plugin: + @cd cmd/generate-stable && go build -o $(GOBIN)/protoc-gen-stable-api . + +stable-api-test: + printf $(COLOR) "Run generate-stable tests..." + @cd cmd/generate-stable && go test ./... + ##### Compile proto files for go ##### -grpc: buf-lint api-linter buf-breaking clean go-grpc fix-path +grpc: stable-api buf-lint api-linter buf-breaking clean go-grpc fix-path go-grpc: clean $(PROTO_OUT) printf $(COLOR) "Compile for go-gRPC..." @@ -50,6 +66,7 @@ go-grpc: clean $(PROTO_OUT) --output=$(PROTO_OUT) \ --exclude=internal \ --exclude=proto/api/google \ + --exclude=temporal/api_next \ -I $(PROTO_ROOT) \ -p go-grpc_out=$(PROTO_PATHS) \ -p grpc-gateway_out=allow_patch_feature=false,$(PROTO_PATHS) \ @@ -105,9 +122,13 @@ sync-nexus-annotations: buf export buf.build/temporalio/nexus-annotations --output . ##### Linters ##### +API_LINTER_FMT = 'map(select(.problems != []) | . as $$file | .problems[] | {rule: .rule_doc_uri, location: "\($$file.file_path):\(.location.start_position.line_number)"}) | group_by(.rule) | .[] | .[0].rule + ":\n" + (map("\t" + .location) | join("\n"))' + api-linter: - printf $(COLOR) "Run api-linter..." - @api-linter --set-exit-status $(PROTO_IMPORTS) --config $(PROTO_ROOT)/api-linter.yaml --output-format json $(PROTO_FILES) | gojq -r 'map(select(.problems != []) | . as $$file | .problems[] | {rule: .rule_doc_uri, location: "\($$file.file_path):\(.location.start_position.line_number)"}) | group_by(.rule) | .[] | .[0].rule + ":\n" + (map("\t" + .location) | join("\n"))' + printf $(COLOR) "Run api-linter on temporal/api_next..." + @api-linter --set-exit-status $(PROTO_IMPORTS) --config $(PROTO_ROOT)/api-linter.yaml --output-format json $(PROTO_FILES_NEXT) | gojq -r $(API_LINTER_FMT) + printf $(COLOR) "Run api-linter on temporal/api..." + @api-linter --set-exit-status $(PROTO_IMPORTS) --config $(PROTO_ROOT)/api-linter.yaml --output-format json $(PROTO_FILES) | gojq -r $(API_LINTER_FMT) $(STAMPDIR): mkdir $@ @@ -122,8 +143,10 @@ buf-lint: $(STAMPDIR)/buf-mod-prune (cd $(PROTO_ROOT) && buf lint) buf-breaking: - @printf $(COLOR) "Run buf breaking changes check against main branch..." + @printf $(COLOR) "Run buf breaking changes check for stable API against main branch..." @(cd $(PROTO_ROOT) && buf breaking --against 'https://github.com/temporalio/api.git#branch=main') + @printf $(COLOR) "Run buf breaking changes check for api_next against main branch..." + @(cd $(PROTO_ROOT) && buf breaking --config buf.next.yaml --against 'https://github.com/temporalio/api.git#branch=main' --against-config buf.yaml) nexus-rpc-yaml: nexus-rpc-yaml-install printf $(COLOR) "Generate nexus/temporal-proto-models-nexusrpc.yaml..." diff --git a/README.md b/README.md index 34a75bd19..7042bc4d4 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Install as git submodule to the project. ## Contribution -Make your change to the temporal/proto files, and run `make` to update the openapi definitions. +Make your change to the temporal/api_next/proto files, and run `make` to update the openapi definitions. Rust is also required because `make` installs and runs `nex-gen` when regenerating system Nexus WIT files. ## Breaking changes diff --git a/api-linter.yaml b/api-linter.yaml index 290842854..c338ff99e 100644 --- a/api-linter.yaml +++ b/api-linter.yaml @@ -64,3 +64,10 @@ - "google/**/*.proto" disabled_rules: - "all" + +- included_paths: + - "temporal/api_next/**/*.proto" + disabled_rules: + # api_next files declare the `temporal.api.*` package they are projected + # into, so their directory deliberately does not match their package. + - "core::0191::proto-package" # https://linter.aip.dev/191/proto-package diff --git a/buf.next.yaml b/buf.next.yaml new file mode 100644 index 000000000..15ecb1cf0 --- /dev/null +++ b/buf.next.yaml @@ -0,0 +1,26 @@ +# buf config for generating api_next +version: v1 +name: buf.build/temporalio/api-next +deps: + - buf.build/grpc-ecosystem/grpc-gateway + - buf.build/googleapis/googleapis + - buf.build/temporalio/nexus-annotations +build: + excludes: + # Buf won't accept a local dependency on the google protos but we need them + # to run api-linter, so just tell buf it ignore it + - google + # Same for nexusannotations - local copy for api-linter, BSR dep for buf + - nexusannotations + - temporal/api +breaking: + use: + - WIRE_JSON + ignore: + - google +lint: + use: + - DEFAULT + ignore: + - google + - cmd diff --git a/buf.stable.gen.yaml b/buf.stable.gen.yaml new file mode 100644 index 000000000..593ba89a6 --- /dev/null +++ b/buf.stable.gen.yaml @@ -0,0 +1,5 @@ +version: v1 +plugins: + - plugin: stable-api + out: . + strategy: all diff --git a/buf.yaml b/buf.yaml index 2f2fa5389..ad136ab50 100644 --- a/buf.yaml +++ b/buf.yaml @@ -1,3 +1,4 @@ +# buf config for generating the stable proto definitions version: v1 name: buf.build/temporalio/api deps: @@ -11,6 +12,7 @@ build: - google # Same for nexusannotations - local copy for api-linter, BSR dep for buf - nexusannotations + - temporal/api_next breaking: use: - WIRE_JSON diff --git a/cmd/generate-stable/README.md b/cmd/generate-stable/README.md new file mode 100644 index 000000000..34edfaef0 --- /dev/null +++ b/cmd/generate-stable/README.md @@ -0,0 +1,17 @@ +# Stable API Plugin + +`protoc-gen-stable-api` generates the stable set of proto definitions from the +full `api_next` schema. It uses descriptors for filtering and `protoprint` to +emit the resulting `.proto` files. + +`api_next` is the source of truth. `api` is generated output and must not be +manually edited. + +Run the complete generation flow from the repository root: + +```bash +make stable-api +``` + +The Make target builds this plugin, runs it through Buf using +`buf.stable.gen.yaml`, and formats the generated stable tree. diff --git a/cmd/generate-stable/catalog.go b/cmd/generate-stable/catalog.go new file mode 100644 index 000000000..16a189127 --- /dev/null +++ b/cmd/generate-stable/catalog.go @@ -0,0 +1,237 @@ +package main + +import ( + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" +) + +// extensionKey identifies an extension by (extendee, number) rather than by +// name: numbers are unique only per extendee, not globally, and once an +// extension isn't Go-registered in this binary, raw wire bytes expose only +// its number — never its FQN — so a name-based key wouldn't be recoverable +// in the common case anyway. +type extensionKey struct { + extendee string + number int32 +} + +// catalog records where the source schema declares every type and extension. +// Selection never needs to mutate this index. +type catalog struct { + typeOwner map[string]string + extensionOwner map[extensionKey]string +} + +// catalog tracks the ownership of types +func newCatalog(input *descriptorpb.FileDescriptorSet) catalog { + catalog := catalog{ + typeOwner: make(map[string]string), + extensionOwner: make(map[extensionKey]string), + } + for _, file := range input.File { + for _, message := range file.MessageType { + catalog.indexMessage(file.GetName(), file.GetPackage(), "", message) + } + for _, enum := range file.EnumType { + catalog.indexEnum(file.GetName(), file.GetPackage(), "", enum) + } + for _, extension := range file.Extension { + catalog.indexExtension(file.GetName(), extension) + } + } + return catalog +} + +func (c catalog) indexMessage(file, packageName, prefix string, message *descriptorpb.DescriptorProto) { + name := joinProtoName(prefix, message.GetName()) + c.typeOwner[fullProtoName(packageName, name)] = file + for _, extension := range message.Extension { + c.indexExtension(file, extension) + } + for _, nested := range message.NestedType { + c.indexMessage(file, packageName, name, nested) + } + for _, enum := range message.EnumType { + c.indexEnum(file, packageName, name, enum) + } +} + +func (c catalog) indexEnum(file, packageName, prefix string, enum *descriptorpb.EnumDescriptorProto) { + c.typeOwner[fullProtoName(packageName, joinProtoName(prefix, enum.GetName()))] = file +} + +func (c catalog) indexExtension(file string, extension *descriptorpb.FieldDescriptorProto) { + if extension.GetExtendee() == "" { + return + } + c.extensionOwner[extensionKey{ + extendee: extension.GetExtendee(), + number: extension.GetNumber(), + }] = file +} + +func joinProtoName(prefix, name string) string { + if prefix == "" { + return name + } + return prefix + "." + name +} + +func fullProtoName(packageName, name string) string { + if packageName == "" { + return "." + name + } + return "." + packageName + "." + name +} + +type imports struct { + direct []string + public []int32 + weak []int32 +} + +func (c catalog) importsFor(file *descriptorpb.FileDescriptorProto) imports { + needed := make(map[string]bool) + c.collectFileImports(file, needed) + return retainImports(file, needed) +} + +func retainImports(file *descriptorpb.FileDescriptorProto, needed map[string]bool) imports { + publicOrWeak := make(map[int32]bool, len(file.PublicDependency)+len(file.WeakDependency)) + for _, dependency := range file.PublicDependency { + publicOrWeak[dependency] = true + } + for _, dependency := range file.WeakDependency { + publicOrWeak[dependency] = true + } + + oldToNew := make(map[int32]int32, len(file.Dependency)) + retained := imports{direct: make([]string, 0, len(file.Dependency))} + for oldIndex, dependency := range file.Dependency { + if !needed[dependency] && !publicOrWeak[int32(oldIndex)] { + continue + } + oldToNew[int32(oldIndex)] = int32(len(retained.direct)) + retained.direct = append(retained.direct, dependency) + } + retained.public = remapImportIndexes(file.PublicDependency, oldToNew) + retained.weak = remapImportIndexes(file.WeakDependency, oldToNew) + return retained +} + +func remapImportIndexes(indexes []int32, oldToNew map[int32]int32) []int32 { + mapped := make([]int32, 0, len(indexes)) + for _, oldIndex := range indexes { + if newIndex, ok := oldToNew[oldIndex]; ok { + mapped = append(mapped, newIndex) + } + } + return mapped +} + +func (c catalog) collectFileImports(file *descriptorpb.FileDescriptorProto, needed map[string]bool) { + c.collectOptionImports(file.GetOptions(), file.GetName(), needed) + for _, message := range file.MessageType { + c.collectMessageImports(message, file.GetName(), needed) + } + for _, enum := range file.EnumType { + c.collectEnumImports(enum, file.GetName(), needed) + } + for _, extension := range file.Extension { + c.collectFieldImports(extension, file.GetName(), needed) + } + for _, service := range file.Service { + c.collectServiceImports(service, file.GetName(), needed) + } +} + +func (c catalog) collectMessageImports(message *descriptorpb.DescriptorProto, file string, needed map[string]bool) { + c.collectOptionImports(message.GetOptions(), file, needed) + for _, field := range message.Field { + c.collectFieldImports(field, file, needed) + } + for _, extension := range message.Extension { + c.collectFieldImports(extension, file, needed) + } + for _, oneof := range message.OneofDecl { + c.collectOptionImports(oneof.GetOptions(), file, needed) + } + for _, nested := range message.NestedType { + c.collectMessageImports(nested, file, needed) + } + for _, enum := range message.EnumType { + c.collectEnumImports(enum, file, needed) + } +} + +func (c catalog) collectEnumImports(enum *descriptorpb.EnumDescriptorProto, file string, needed map[string]bool) { + c.collectOptionImports(enum.GetOptions(), file, needed) + for _, value := range enum.Value { + c.collectOptionImports(value.GetOptions(), file, needed) + } +} + +func (c catalog) collectFieldImports(field *descriptorpb.FieldDescriptorProto, file string, needed map[string]bool) { + c.collectOptionImports(field.GetOptions(), file, needed) + if field.GetTypeName() != "" { + c.markTypeImport(field.GetTypeName(), file, needed) + } + if field.GetExtendee() != "" { + c.markTypeImport(field.GetExtendee(), file, needed) + } +} + +func (c catalog) collectServiceImports(service *descriptorpb.ServiceDescriptorProto, file string, needed map[string]bool) { + c.collectOptionImports(service.GetOptions(), file, needed) + for _, method := range service.Method { + c.collectOptionImports(method.GetOptions(), file, needed) + c.markTypeImport(method.GetInputType(), file, needed) + c.markTypeImport(method.GetOutputType(), file, needed) + } +} + +func (c catalog) collectOptionImports(options proto.Message, file string, needed map[string]bool) { + if options == nil { + return + } + extendee := "." + string(options.ProtoReflect().Descriptor().FullName()) + options.ProtoReflect().Range(func(field protoreflect.FieldDescriptor, _ protoreflect.Value) bool { + if field.IsExtension() { + c.markExtensionImport(extendee, int32(field.Number()), file, needed) + } + return true + }) + + // now, consume the custom extensions + unknown := options.ProtoReflect().GetUnknown() + for len(unknown) > 0 { + number, wireType, tagLength := protowire.ConsumeTag(unknown) + if tagLength < 0 { + return + } + unknown = unknown[tagLength:] + c.markExtensionImport(extendee, int32(number), file, needed) + valueLength := protowire.ConsumeFieldValue(number, wireType, unknown) + if valueLength < 0 { + return + } + unknown = unknown[valueLength:] + } +} + +func (c catalog) markExtensionImport(extendee string, number int32, file string, needed map[string]bool) { + if dependency, ok := c.extensionOwner[extensionKey{extendee: extendee, number: number}]; ok && dependency != file { + needed[dependency] = true + } +} + +func (c catalog) markTypeImport(typeName, file string, needed map[string]bool) { + if typeName == "" { + return + } + if dependency, ok := c.typeOwner[typeName]; ok && dependency != file { + needed[dependency] = true + } +} diff --git a/cmd/generate-stable/catalog_test.go b/cmd/generate-stable/catalog_test.go new file mode 100644 index 000000000..f49037c40 --- /dev/null +++ b/cmd/generate-stable/catalog_test.go @@ -0,0 +1,153 @@ +package main + +import ( + "reflect" + "testing" + + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/descriptorpb" +) + +// TestCatalogImportsForDropsUnusedDependency: a file imports two files but +// only references a type from one of them - the unused import must be +// dropped from the regenerated Dependency list. +func TestCatalogImportsForDropsUnusedDependency(t *testing.T) { + aFile := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api/example/v1/a.proto"), + Package: proto.String("example.v1"), + MessageType: []*descriptorpb.DescriptorProto{{Name: proto.String("A")}}, + } + bFile := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api/example/v1/b.proto"), + Package: proto.String("example.v1"), + MessageType: []*descriptorpb.DescriptorProto{{Name: proto.String("B")}}, + } + mainFile := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api/example/v1/main.proto"), + Package: proto.String("example.v1"), + Dependency: []string{ + "temporal/api/example/v1/a.proto", + "temporal/api/example/v1/b.proto", + }, + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Request"), + Field: []*descriptorpb.FieldDescriptorProto{{ + Name: proto.String("a_ref"), + Number: proto.Int32(1), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.A"), + }}, + }}, + } + + cat := newCatalog(&descriptorpb.FileDescriptorSet{File: []*descriptorpb.FileDescriptorProto{aFile, bFile, mainFile}}) + got := cat.importsFor(mainFile) + + want := []string{"temporal/api/example/v1/a.proto"} + if !reflect.DeepEqual(got.direct, want) { + t.Fatalf("importsFor().direct = %v, want %v (b.proto is unused and must be dropped)", got.direct, want) + } +} + +// TestCatalogImportsForRetainsExtensionOnlyDependency: the request_header +// shape found during review - a dependency used only via a custom-option +// extension set on a method (detected by collectOptionImports walking +// unknown wire bytes, since this test process has no Go registration for +// the extension), never via a TypeName reference. Must be retained, not +// dropped as "unused". +func TestCatalogImportsForRetainsExtensionOnlyDependency(t *testing.T) { + const extNumber = 90010 + + optsFile := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api/example/v1/opts.proto"), + Package: proto.String("example.v1"), + Extension: []*descriptorpb.FieldDescriptorProto{{ + Name: proto.String("my_option"), + Number: proto.Int32(extNumber), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + Extendee: proto.String(".google.protobuf.MethodOptions"), + }}, + } + + methodOpts := &descriptorpb.MethodOptions{} + methodOpts.ProtoReflect().SetUnknown( + protowire.AppendString(protowire.AppendTag(nil, protowire.Number(extNumber), protowire.BytesType), "some-value"), + ) + svcFile := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api/example/v1/service.proto"), + Package: proto.String("example.v1"), + Dependency: []string{"temporal/api/example/v1/opts.proto"}, + Service: []*descriptorpb.ServiceDescriptorProto{{ + Name: proto.String("Example"), + Method: []*descriptorpb.MethodDescriptorProto{{ + Name: proto.String("DoThing"), + InputType: proto.String(".example.v1.Req"), + OutputType: proto.String(".example.v1.Resp"), + Options: methodOpts, + }}, + }}, + } + + cat := newCatalog(&descriptorpb.FileDescriptorSet{File: []*descriptorpb.FileDescriptorProto{optsFile, svcFile}}) + got := cat.importsFor(svcFile) + + want := []string{"temporal/api/example/v1/opts.proto"} + if !reflect.DeepEqual(got.direct, want) { + t.Fatalf("importsFor().direct = %v, want %v (opts.proto is used only via the my_option extension, must be retained)", got.direct, want) + } +} + +// TestCatalogImportsForRemapsPublicWeakIndexAfterDrop: a.proto (unused, +// dropped), b.proto (unused but marked public - retained anyway), c.proto +// (used - retained). b's PublicDependency index must shift from its old +// position (1) to its new one (0) once a.proto is dropped ahead of it, +// not silently point at whatever unrelated import now sits at index 1. +func TestCatalogImportsForRemapsPublicWeakIndexAfterDrop(t *testing.T) { + aFile := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api/example/v1/a.proto"), + Package: proto.String("example.v1"), + MessageType: []*descriptorpb.DescriptorProto{{Name: proto.String("A")}}, + } + bFile := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api/example/v1/b.proto"), + Package: proto.String("example.v1"), + MessageType: []*descriptorpb.DescriptorProto{{Name: proto.String("B")}}, + } + cFile := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api/example/v1/c.proto"), + Package: proto.String("example.v1"), + MessageType: []*descriptorpb.DescriptorProto{{Name: proto.String("C")}}, + } + mainFile := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api/example/v1/main.proto"), + Package: proto.String("example.v1"), + Dependency: []string{ + "temporal/api/example/v1/a.proto", // unused, not public - dropped + "temporal/api/example/v1/b.proto", // unused, public - retained anyway + "temporal/api/example/v1/c.proto", // used - retained + }, + PublicDependency: []int32{1}, // b.proto + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Request"), + Field: []*descriptorpb.FieldDescriptorProto{{ + Name: proto.String("c_ref"), + Number: proto.Int32(1), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.C"), + }}, + }}, + } + + cat := newCatalog(&descriptorpb.FileDescriptorSet{File: []*descriptorpb.FileDescriptorProto{aFile, bFile, cFile, mainFile}}) + got := cat.importsFor(mainFile) + + wantDirect := []string{"temporal/api/example/v1/b.proto", "temporal/api/example/v1/c.proto"} + if !reflect.DeepEqual(got.direct, wantDirect) { + t.Fatalf("importsFor().direct = %v, want %v", got.direct, wantDirect) + } + wantPublic := []int32{0} // b.proto, now at index 0 after a.proto was dropped + if !reflect.DeepEqual(got.public, wantPublic) { + t.Fatalf("importsFor().public = %v, want %v (b.proto's index must shift from 1 to 0, not point at c.proto)", got.public, wantPublic) + } +} diff --git a/cmd/generate-stable/go.mod b/cmd/generate-stable/go.mod new file mode 100644 index 000000000..42cce1b83 --- /dev/null +++ b/cmd/generate-stable/go.mod @@ -0,0 +1,8 @@ +module github.com/temporalio/api/cmd/generate-stable + +go 1.25.4 + +require ( + github.com/jhump/protoreflect/v2 v2.0.0-beta.2 + google.golang.org/protobuf v1.36.11 +) diff --git a/cmd/generate-stable/go.sum b/cmd/generate-stable/go.sum new file mode 100644 index 000000000..9fca40bc7 --- /dev/null +++ b/cmd/generate-stable/go.sum @@ -0,0 +1,28 @@ +github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= +github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/jhump/protoreflect/v2 v2.0.0-beta.2 h1:qZU+rEZUOYTz1Bnhi3xbwn+VxdXkLVeEpAeZzVXLY88= +github.com/jhump/protoreflect/v2 v2.0.0-beta.2/go.mod h1:4tnOYkB/mq7QTyS3YKtVtNrJv4Psqout8HA1U+hZtgM= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cmd/generate-stable/golden_test.go b/cmd/generate-stable/golden_test.go new file mode 100644 index 000000000..cfb505464 --- /dev/null +++ b/cmd/generate-stable/golden_test.go @@ -0,0 +1,603 @@ +package main + +import ( + "strings" + "testing" + + "github.com/jhump/protoreflect/v2/protoprint" + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protodesc" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" +) + +const ( + fileMessageTypeField = int32(4) // FileDescriptorProto.message_type + msgFieldField = int32(2) // DescriptorProto.field + msgNestedTypeField = int32(3) // DescriptorProto.nested_type + msgOneofDeclField = int32(8) // DescriptorProto.oneof_decl +) + +// experimentalOptions builds a Message/Field/Enum/EnumValue/Service/Method +// Options message carrying only the given experimental extension tag, using +// the unknown-field trick (same approach as main_test.go) since we don't +// depend on the generated extension types here. +func experimentalFieldOptions() *descriptorpb.FieldOptions { + opts := &descriptorpb.FieldOptions{} + opts.ProtoReflect().SetUnknown( + protowire.AppendString(protowire.AppendTag(nil, extExperimentalField, protowire.BytesType), ""), + ) + return opts +} + +func experimentalMessageOptions() *descriptorpb.MessageOptions { + opts := &descriptorpb.MessageOptions{} + opts.ProtoReflect().SetUnknown( + protowire.AppendString(protowire.AppendTag(nil, extExperimentalMessage, protowire.BytesType), ""), + ) + return opts +} + +// linkStandalone links a single dependency-free file (true of every fixture +// in this test file) so its declarations can be walked via protoreflect. +func linkStandalone(t *testing.T, file *descriptorpb.FileDescriptorProto) protoreflect.FileDescriptor { + t.Helper() + files, err := protodesc.NewFiles(&descriptorpb.FileDescriptorSet{File: []*descriptorpb.FileDescriptorProto{file}}) + if err != nil { + t.Fatalf("protodesc.NewFiles() error = %v", err) + } + fd, err := files.FindFileByPath(file.GetName()) + if err != nil { + t.Fatalf("FindFileByPath() error = %v", err) + } + return fd +} + +// stripLinkPrint runs the same sequence main.go does (T2): strip +// structurally, link once to get linked descriptors on both sides, rebuild +// SourceCodeInfo by FullName correlation, then link again (now with correct +// comments) and print. Returns the intermediate stripped proto and its final +// linked descriptor too, since some tests need to assert on those directly +// (field/oneof counts, ContainingOneof) rather than only on printed text. +func stripLinkPrint(t *testing.T, file *descriptorpb.FileDescriptorProto) (stripped *descriptorpb.FileDescriptorProto, fd protoreflect.FileDescriptor, content string) { + t.Helper() + originalFD := linkStandalone(t, file) + + stripped = stripFile(file) + prelim := linkStandalone(t, stripped) + stripped.SourceCodeInfo = rebuildSourceCodeInfo(file, originalFD, prelim) + + fd = linkStandalone(t, stripped) + printer := protoprint.Printer{} + c, err := printer.PrintProtoToString(fd) + if err != nil { + t.Fatalf("PrintProtoToString() error = %v", err) + } + content = c + return stripped, fd, content +} + +func TestGoldenCommentRetentionOnMiddleFieldStrip(t *testing.T) { + msgPath := []int32{fileMessageTypeField, 0} + + alpha := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("alpha"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + } + draftField := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("draft_field"), Number: proto.Int32(2), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + Options: experimentalFieldOptions(), + } + beta := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("beta"), Number: proto.Int32(3), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + } + gamma := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("gamma"), Number: proto.Int32(4), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + } + + locFor := func(fieldIdx int32, comment string) *descriptorpb.SourceCodeInfo_Location { + path := append(append([]int32{}, msgPath...), msgFieldField, fieldIdx) + return &descriptorpb.SourceCodeInfo_Location{ + Path: path, + // Span is required to be well-formed by protodesc, but goes stale + // after stripping regardless (worklist T2) - the value doesn't + // matter for this test, only that it's structurally valid. + Span: []int32{fieldIdx + 1, 0, 10}, + LeadingComments: proto.String(" " + comment + "\n"), + } + } + + file := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Syntax: proto.String("proto3"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Foo"), + Field: []*descriptorpb.FieldDescriptorProto{alpha, draftField, beta, gamma}, + }}, + SourceCodeInfo: &descriptorpb.SourceCodeInfo{ + Location: []*descriptorpb.SourceCodeInfo_Location{ + {Path: []int32{fileMessageTypeField, 0}, Span: []int32{0, 0, 1}, LeadingComments: proto.String(" Foo message\n")}, + locFor(0, "COMMENT FOR alpha"), + locFor(1, "COMMENT FOR draft_field"), + locFor(2, "COMMENT FOR beta"), + locFor(3, "COMMENT FOR gamma"), + }, + }, + } + + _, _, content := stripLinkPrint(t, file) + + if strings.Contains(content, "draft_field") { + t.Fatalf("output contains stripped field draft_field:\n%s", content) + } + if strings.Contains(content, "COMMENT FOR draft_field") { + t.Fatalf("output contains dropped comment COMMENT FOR draft_field - it must not survive on any sibling:\n%s", content) + } + + assertCommentPrecedesDecl(t, content, "COMMENT FOR alpha", "alpha") + assertCommentPrecedesDecl(t, content, "COMMENT FOR beta", "beta") + assertCommentPrecedesDecl(t, content, "COMMENT FOR gamma", "gamma") +} + +func TestGoldenOneofStripsOnlyTaggedVariant(t *testing.T) { + msgPath := []int32{fileMessageTypeField, 0} + + alpha := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("alpha"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + OneofIndex: proto.Int32(0), + } + draftVariant := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("draft_variant"), Number: proto.Int32(2), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + OneofIndex: proto.Int32(0), + Options: experimentalFieldOptions(), + } + beta := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("beta"), Number: proto.Int32(3), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + OneofIndex: proto.Int32(0), + } + + locFor := func(fieldIdx int32, comment string) *descriptorpb.SourceCodeInfo_Location { + path := append(append([]int32{}, msgPath...), msgFieldField, fieldIdx) + return &descriptorpb.SourceCodeInfo_Location{ + Path: path, + Span: []int32{fieldIdx + 1, 0, 10}, + LeadingComments: proto.String(" " + comment + "\n"), + } + } + + file := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Syntax: proto.String("proto3"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Foo"), + Field: []*descriptorpb.FieldDescriptorProto{alpha, draftVariant, beta}, + OneofDecl: []*descriptorpb.OneofDescriptorProto{{Name: proto.String("choice")}}, + }}, + SourceCodeInfo: &descriptorpb.SourceCodeInfo{ + Location: []*descriptorpb.SourceCodeInfo_Location{ + {Path: []int32{fileMessageTypeField, 0}, Span: []int32{0, 0, 1}, LeadingComments: proto.String(" Foo message\n")}, + locFor(0, "COMMENT FOR alpha"), + locFor(1, "COMMENT FOR draft_variant"), + locFor(2, "COMMENT FOR beta"), + }, + }, + } + + stripped, fd, content := stripLinkPrint(t, file) + + if got, want := len(stripped.MessageType[0].OneofDecl), 1; got != want { + t.Fatalf("OneofDecl count = %d, want %d (oneof survives - alpha/beta still reference it)", got, want) + } + + // The real correctness signal for OneofIndex re-pointing: a wrong index + // would either fail to link or put alpha/beta in different oneofs. + msg := fd.Messages().Get(0) + alphaFD := msg.Fields().ByName("alpha") + betaFD := msg.Fields().ByName("beta") + if alphaFD.ContainingOneof() == nil || betaFD.ContainingOneof() == nil { + t.Fatalf("alpha/beta lost their oneof") + } + if alphaFD.ContainingOneof() != betaFD.ContainingOneof() { + t.Fatalf("alpha and beta ended up in different oneofs after stripping") + } + + if strings.Contains(content, "draft_variant") { + t.Fatalf("output contains stripped variant draft_variant:\n%s", content) + } + if !strings.Contains(content, "oneof choice") { + t.Fatalf("output lost the oneof block entirely, want it to survive with alpha/beta:\n%s", content) + } + assertCommentPrecedesDecl(t, content, "COMMENT FOR alpha", "alpha") + assertCommentPrecedesDecl(t, content, "COMMENT FOR beta", "beta") +} + +func TestGoldenOneofDroppedWhenAllVariantsStripped(t *testing.T) { + draftA := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("draft_a"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + OneofIndex: proto.Int32(0), + Options: experimentalFieldOptions(), + } + draftB := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("draft_b"), Number: proto.Int32(2), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + OneofIndex: proto.Int32(0), + Options: experimentalFieldOptions(), + } + stable := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("stable"), Number: proto.Int32(3), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + } + + file := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Syntax: proto.String("proto3"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Foo"), + Field: []*descriptorpb.FieldDescriptorProto{draftA, draftB, stable}, + OneofDecl: []*descriptorpb.OneofDescriptorProto{{Name: proto.String("choice")}}, + }}, + } + + stripped, _, content := stripLinkPrint(t, file) + + if got := stripped.MessageType[0].OneofDecl; len(got) != 0 { + t.Fatalf("OneofDecl = %v, want empty (all variants stripped)", got) + } + if got, want := len(stripped.MessageType[0].Field), 1; got != want { + t.Fatalf("fields = %d, want %d (only 'stable')", got, want) + } + if strings.Contains(content, "oneof") { + t.Fatalf("output still contains an (empty) oneof block:\n%s", content) + } +} + +// TestGoldenNestedMessageRenumbering covers the case a hand-rolled index +// remap needs its own recursive tree structure for: a dropped nested message +// shifting the index of a kept sibling nested message, with a field inside +// the survivor keeping its own comment. Under the FullName-based design this +// falls out of the same rebuildSourceCodeInfo pass with no special-casing. +func TestGoldenNestedMessageRenumbering(t *testing.T) { + droppedNested := &descriptorpb.DescriptorProto{ + Name: proto.String("DraftInner"), + Options: experimentalMessageOptions(), + } + keptNested := &descriptorpb.DescriptorProto{ + Name: proto.String("Inner"), + Field: []*descriptorpb.FieldDescriptorProto{{ + Name: proto.String("value"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + }}, + } + + file := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Syntax: proto.String("proto3"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Outer"), + NestedType: []*descriptorpb.DescriptorProto{droppedNested, keptNested}, + }}, + SourceCodeInfo: &descriptorpb.SourceCodeInfo{ + Location: []*descriptorpb.SourceCodeInfo_Location{ + {Path: []int32{fileMessageTypeField, 0}, Span: []int32{0, 0, 1}, LeadingComments: proto.String(" Outer message\n")}, + {Path: []int32{fileMessageTypeField, 0, msgNestedTypeField, 0}, Span: []int32{1, 0, 1}, LeadingComments: proto.String(" DraftInner (dropped)\n")}, + {Path: []int32{fileMessageTypeField, 0, msgNestedTypeField, 1}, Span: []int32{2, 0, 1}, LeadingComments: proto.String(" Inner (kept, was index 1)\n")}, + {Path: []int32{fileMessageTypeField, 0, msgNestedTypeField, 1, msgFieldField, 0}, Span: []int32{3, 0, 1}, LeadingComments: proto.String(" COMMENT FOR value\n")}, + }, + }, + } + + stripped, _, content := stripLinkPrint(t, file) + + if got, want := len(stripped.MessageType[0].NestedType), 1; got != want { + t.Fatalf("NestedType count = %d, want %d", got, want) + } + if strings.Contains(content, "DraftInner") { + t.Fatalf("output contains stripped nested message DraftInner:\n%s", content) + } + if strings.Contains(content, "dropped") { + t.Fatalf("output contains a comment that belonged to the dropped nested message:\n%s", content) + } + assertCommentPrecedesDecl(t, content, "Inner (kept, was index 1)", "message Inner") + assertCommentPrecedesDecl(t, content, "COMMENT FOR value", "value") +} + +// TestGoldenDraftMapFieldDropsSyntheticEntry is T12 (worklist Aug 17): a +// draft-tagged map field's synthetic FooEntry message can't carry its own +// tag (protoc generates it, nobody authors it), so before this fix it always +// survived regardless of the field's tag - an orphaned, unused type left +// sitting in stable. V (the map's value type) is deliberately left stable +// here: this is the sub-case that produced no link error at all before the +// fix, just a silent leftover - the other sub-case (V also draft) is covered +// by TestGoldenDraftMapFieldAndValueTypeBothDropCleanly below. +func TestGoldenDraftMapFieldDropsSyntheticEntry(t *testing.T) { + v := &descriptorpb.DescriptorProto{ + Name: proto.String("V"), + Field: []*descriptorpb.FieldDescriptorProto{{ + Name: proto.String("value"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + }}, + } + fooEntry := &descriptorpb.DescriptorProto{ + Name: proto.String("FooEntry"), + Options: &descriptorpb.MessageOptions{MapEntry: proto.Bool(true)}, + Field: []*descriptorpb.FieldDescriptorProto{ + { + Name: proto.String("key"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + }, + { + Name: proto.String("value"), Number: proto.Int32(2), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.V"), + }, + }, + } + fooField := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("foo"), + Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_REPEATED.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.Bar.FooEntry"), + Options: experimentalFieldOptions(), + } + bar := &descriptorpb.DescriptorProto{ + Name: proto.String("Bar"), + Field: []*descriptorpb.FieldDescriptorProto{fooField}, + NestedType: []*descriptorpb.DescriptorProto{fooEntry}, + } + + file := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Syntax: proto.String("proto3"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{bar, v}, + } + + stripped, _, content := stripLinkPrint(t, file) + + if got, want := len(stripped.MessageType[0].Field), 0; got != want { + t.Fatalf("Bar fields = %d, want %d (foo stripped)", got, want) + } + if got, want := len(stripped.MessageType[0].NestedType), 0; got != want { + t.Fatalf("Bar nested types = %d, want %d (FooEntry must not survive as an orphan)", got, want) + } + if strings.Contains(content, "FooEntry") { + t.Fatalf("output contains orphaned FooEntry:\n%s", content) + } + if strings.Contains(content, "map<") || strings.Contains(content, "map_entry") { + t.Fatalf("output still contains map-entry trace:\n%s", content) + } + if !strings.Contains(content, "message V") { + t.Fatalf("output lost V - it's stable and unrelated, should survive:\n%s", content) + } +} + +// TestGoldenDraftMapFieldAndValueTypeBothDropCleanly is T12's other sub-case: +// the map field AND its value type are both draft. Before this fix, this +// case still "worked" only by accident - FooEntry.value pointed at a +// stripped type and failed at link time, a real but confusing backstop. With +// the fix, FooEntry is dropped directly alongside foo, so V never needs to +// be reached at all - no link failure required, nothing dangling. +func TestGoldenDraftMapFieldAndValueTypeBothDropCleanly(t *testing.T) { + v := &descriptorpb.DescriptorProto{ + Name: proto.String("V"), + Options: experimentalMessageOptions(), + Field: []*descriptorpb.FieldDescriptorProto{{ + Name: proto.String("value"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + }}, + } + fooEntry := &descriptorpb.DescriptorProto{ + Name: proto.String("FooEntry"), + Options: &descriptorpb.MessageOptions{MapEntry: proto.Bool(true)}, + Field: []*descriptorpb.FieldDescriptorProto{ + { + Name: proto.String("key"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + }, + { + Name: proto.String("value"), Number: proto.Int32(2), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.V"), + }, + }, + } + fooField := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("foo"), + Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_REPEATED.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.Bar.FooEntry"), + Options: experimentalFieldOptions(), + } + bar := &descriptorpb.DescriptorProto{ + Name: proto.String("Bar"), + Field: []*descriptorpb.FieldDescriptorProto{fooField}, + NestedType: []*descriptorpb.DescriptorProto{fooEntry}, + } + + file := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Syntax: proto.String("proto3"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{bar, v}, + } + + // stripLinkPrint itself would fatal on a link error - reaching content + // at all proves no dangling reference was ever created. + stripped, _, content := stripLinkPrint(t, file) + + if got, want := len(stripped.MessageType[0].NestedType), 0; got != want { + t.Fatalf("Bar nested types = %d, want %d (FooEntry must drop alongside foo)", got, want) + } + if strings.Contains(content, "FooEntry") || strings.Contains(content, "message V") { + t.Fatalf("output still contains dropped FooEntry or V:\n%s", content) + } +} + +// TestGoldenMapEntrySurvivalIgnoresUnrelatedSameNamedField is the regression +// case for T12's follow-up fix (worklist Aug 17): mapEntryFieldSurvives must +// match a map field by its owning nested type's FULL qualified name, not a +// bare-name suffix. decoyRef is a completely unrelated, stable field whose +// TypeName happens to end in ".FooEntry" too (it points at Elsewhere.FooEntry, +// a plain nested message with the same bare name, nothing to do with the +// map), declared BEFORE the real map field foo. Under the old +// suffix-matching implementation this decoy would have been matched first, +// and being stable, would have made Bar.FooEntry (the actual map entry) +// survive incorrectly even though foo is draft-tagged. +func TestGoldenMapEntrySurvivalIgnoresUnrelatedSameNamedField(t *testing.T) { + decoyEntry := &descriptorpb.DescriptorProto{ + Name: proto.String("FooEntry"), // same bare name, unrelated, not a map entry + Field: []*descriptorpb.FieldDescriptorProto{{ + Name: proto.String("value"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + }}, + } + elsewhere := &descriptorpb.DescriptorProto{ + Name: proto.String("Elsewhere"), + NestedType: []*descriptorpb.DescriptorProto{decoyEntry}, + } + + realFooEntry := &descriptorpb.DescriptorProto{ + Name: proto.String("FooEntry"), + Options: &descriptorpb.MessageOptions{MapEntry: proto.Bool(true)}, + Field: []*descriptorpb.FieldDescriptorProto{ + { + Name: proto.String("key"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + }, + { + Name: proto.String("value"), Number: proto.Int32(2), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.Elsewhere.FooEntry"), // reuses Elsewhere's string type for value, irrelevant to the point + }, + }, + } + + decoyRef := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("decoy_ref"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.Elsewhere.FooEntry"), // unrelated, stable, bare name coincidentally "FooEntry" + } + fooField := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("foo"), + Number: proto.Int32(2), + Label: descriptorpb.FieldDescriptorProto_LABEL_REPEATED.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.Bar.FooEntry"), // the real map field, draft-tagged + Options: experimentalFieldOptions(), + } + bar := &descriptorpb.DescriptorProto{ + Name: proto.String("Bar"), + Field: []*descriptorpb.FieldDescriptorProto{decoyRef, fooField}, // decoy declared first + NestedType: []*descriptorpb.DescriptorProto{realFooEntry}, + } + + file := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Syntax: proto.String("proto3"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{bar, elsewhere}, + } + + stripped, _, content := stripLinkPrint(t, file) + + barMsg := stripped.MessageType[0] + if got, want := len(barMsg.Field), 1; got != want || barMsg.Field[0].GetName() != "decoy_ref" { + t.Fatalf("Bar.Field = %v, want only decoy_ref (foo stripped)", barMsg.Field) + } + if got, want := len(barMsg.NestedType), 0; got != want { + t.Fatalf("Bar.NestedType count = %d, want %d - the real map entry must drop despite the decoy's same bare name", got, want) + } + if !strings.Contains(content, "message Elsewhere") || !strings.Contains(content, "message FooEntry") { + t.Fatalf("Elsewhere.FooEntry (the unrelated decoy) must survive untouched:\n%s", content) + } +} + +// assertCommentPrecedesDecl checks that commentText appears as a comment on +// the line(s) immediately preceding (allowing blank lines) the first line +// containing declText, and that no other field's comment intervenes. +func assertCommentPrecedesDecl(t *testing.T, content, commentText, declText string) { + t.Helper() + lines := strings.Split(content, "\n") + declLine := -1 + for i, line := range lines { + trimmed := strings.TrimSpace(line) + if strings.HasPrefix(trimmed, "//") { + continue // skip comment lines - declText (a field name) may be a substring of its own comment + } + if strings.Contains(line, declText) { + declLine = i + break + } + } + if declLine == -1 { + t.Fatalf("declaration for %q not found in output:\n%s", declText, content) + } + // Walk backwards over blank lines to find the nearest non-blank line. + j := declLine - 1 + for j >= 0 && strings.TrimSpace(lines[j]) == "" { + j-- + } + if j < 0 || !strings.Contains(lines[j], commentText) { + got := "" + if j >= 0 { + got = lines[j] + } + t.Fatalf("expected comment %q immediately before declaration %q, got line %q\nfull output:\n%s", commentText, declText, got, content) + } +} diff --git a/cmd/generate-stable/main.go b/cmd/generate-stable/main.go new file mode 100644 index 000000000..e51f7954d --- /dev/null +++ b/cmd/generate-stable/main.go @@ -0,0 +1,101 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/jhump/protoreflect/v2/protoprint" + "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/reflect/protodesc" + "google.golang.org/protobuf/reflect/protoregistry" + "google.golang.org/protobuf/types/descriptorpb" +) + +const ( + apiNextPrefix = "temporal/api_next/" + stableAPIPrefix = "temporal/api/" + + generatedHeader = "// Generated from api_next. DO NOT EDIT.\n\n" +) + +// isAPINextPath/isStableAPIPath name the apiNextPrefix/stableAPIPrefix checks +// scattered across this package (T15, worklist Aug 17) - purely cosmetic, one +// place to change if the prefix convention ever does. +func isAPINextPath(path string) bool { + return strings.HasPrefix(path, apiNextPrefix) +} + +func isStableAPIPath(path string) bool { + return strings.HasPrefix(path, stableAPIPrefix) +} + +var nextOnlyFiles = map[string]bool{ + apiNextPrefix + "protometa/v1/experimental.proto": true, +} + +// skip generating files for known experimental protos. +// Intended to be used only by the experimental annotations file itself, +// all others should just use the annotations instead +func isNextOnlyPath(path string) bool { + return nextOnlyFiles[path] +} + +func linkStrippedSet(output *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) { + files, err := protodesc.NewFiles(output) + if err != nil { + return nil, fmt.Errorf("link stripped descriptor set (check first whether a stable declaration references a type marked experimental): %w", err) + } + return files, nil +} + +func main() { + protogen.Options{}.Run(generate) +} + +func generate(plugin *protogen.Plugin) error { + input := &descriptorpb.FileDescriptorSet{File: plugin.Request.ProtoFile} + + // PHASE 1: Type Handling (Strip experimental nodes) + stableSet, err := stripExperimental(input) + if err != nil { + return err + } + + // PHASE 2: Import & Cyclical Cleanup + output := sanitizeImports(stableSet) + + // PHASE 3: SourceCodeInfo is still wrong at this point + // See fixSourceCodeInfo in sourceinfo.go + if err := fixSourceCodeInfo(plugin, output); err != nil { + return err + } + // PHASE 4: link the final stable descriptor set (now with correct + // SourceCodeInfo) and print it. + return writeGeneratedFiles(plugin, output) +} + +// writeGeneratedFiles prints each api_next file's stable projection from the +// final linked descriptor set and registers it as generated plugin output. +func writeGeneratedFiles(plugin *protogen.Plugin, output *descriptorpb.FileDescriptorSet) error { + files, err := linkStrippedSet(output) + if err != nil { + return err + } + printer := protoprint.Printer{} + // iterate over the files in plugin.Files to avoid generating protos for dependencies/non-api-next files + for _, file := range plugin.Files { + if !file.Generate || !isAPINextPath(file.Desc.Path()) || isNextOnlyPath(file.Desc.Path()) { + continue + } + stableFile, err := files.FindFileByPath(stablePath(file.Desc.Path())) + if err != nil { + return fmt.Errorf("find projected file %q: %w", file.Desc.Path(), err) + } + content, err := printer.PrintProtoToString(stableFile) + if err != nil { + return fmt.Errorf("print projected file %q: %w", stableFile.Path(), err) + } + plugin.NewGeneratedFile(stableFile.Path(), "").P(generatedHeader + content) + } + return nil +} diff --git a/cmd/generate-stable/main_test.go b/cmd/generate-stable/main_test.go new file mode 100644 index 000000000..693336463 --- /dev/null +++ b/cmd/generate-stable/main_test.go @@ -0,0 +1,217 @@ +package main + +import ( + "strings" + "testing" + + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/descriptorpb" +) + +func TestStableProjectionOmitsExperimentalFields(t *testing.T) { + experimentalOptions := &descriptorpb.FieldOptions{} + experimentalOptions.ProtoReflect().SetUnknown( + protowire.AppendString( + protowire.AppendTag(nil, 95134, protowire.BytesType), + "nexus-operation-tags", + ), + ) + input := &descriptorpb.FileDescriptorSet{File: []*descriptorpb.FileDescriptorProto{{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Request"), + Field: []*descriptorpb.FieldDescriptorProto{ + {Name: proto.String("stable"), Number: proto.Int32(1)}, + {Name: proto.String("draft"), Number: proto.Int32(2), Options: experimentalOptions}, + }, + }}, + }}} + + stableAST, err := stripExperimental(input) + if err != nil { + t.Fatalf("stripExperimental() error = %v", err) + } + output := sanitizeImports(stableAST) + + file := output.File[0] + if got, want := file.GetName(), "temporal/api/example/v1/message.proto"; got != want { + t.Fatalf("file name = %q, want %q", got, want) + } + if got, want := file.GetOptions().GetGoPackage(), "go.temporal.io/api/example/v1;example"; got != want { + t.Fatalf("go_package = %q, want %q", got, want) + } + fields := file.MessageType[0].Field + if len(fields) != 1 || fields[0].GetName() != "stable" { + t.Fatalf("fields = %v, want only stable", fields) + } + reservedNames := file.MessageType[0].ReservedName + if len(reservedNames) != 0 { + t.Fatalf("reserved names = %v, want [] (reservation injection is currently disabled)", reservedNames) + } +} + +func TestValidateStableFieldReferencingDraftTypeFails(t *testing.T) { + draftMessageOptions := &descriptorpb.MessageOptions{} + draftMessageOptions.ProtoReflect().SetUnknown( + protowire.AppendString( + protowire.AppendTag(nil, extExperimentalMessage, protowire.BytesType), + "", + ), + ) + input := &descriptorpb.FileDescriptorSet{File: []*descriptorpb.FileDescriptorProto{{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{ + { + Name: proto.String("DraftMsg"), + Options: draftMessageOptions, + }, + { + Name: proto.String("Request"), + Field: []*descriptorpb.FieldDescriptorProto{ + { + Name: proto.String("ref"), + Number: proto.Int32(1), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.DraftMsg"), + }, + }, + }, + }, + }}} + + stableAST, err := stripExperimental(input) + if err != nil { + t.Fatalf("stripExperimental() error = %v, want nil (T11: stripExperimental no longer checks type references, only tag placement)", err) + } + output := sanitizeImports(stableAST) + + _, err = linkStrippedSet(output) + if err == nil { + t.Fatal("linkStrippedSet() error = nil, want a failure (Request.ref points at stripped DraftMsg)") + } + if !strings.Contains(err.Error(), "DraftMsg") { + t.Fatalf("linkStrippedSet() error = %v, want it to mention the unresolved type DraftMsg", err) + } + if !strings.Contains(err.Error(), "marked experimental") { + t.Fatalf("linkStrippedSet() error = %v, want the wrapped hint about experimental types", err) + } +} + +func TestValidateDraftFieldReferencingDraftTypeGeneratesCleanly(t *testing.T) { + draftMessageOptions := &descriptorpb.MessageOptions{} + draftMessageOptions.ProtoReflect().SetUnknown( + protowire.AppendString( + protowire.AppendTag(nil, extExperimentalMessage, protowire.BytesType), + "", + ), + ) + draftFieldOptions := &descriptorpb.FieldOptions{} + draftFieldOptions.ProtoReflect().SetUnknown( + protowire.AppendString( + protowire.AppendTag(nil, extExperimentalField, protowire.BytesType), + "", + ), + ) + input := &descriptorpb.FileDescriptorSet{File: []*descriptorpb.FileDescriptorProto{{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{ + { + Name: proto.String("DraftMsg"), + Options: draftMessageOptions, + }, + { + Name: proto.String("Request"), + Field: []*descriptorpb.FieldDescriptorProto{ + { + Name: proto.String("ref"), + Number: proto.Int32(1), + Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), + TypeName: proto.String(".example.v1.DraftMsg"), + Options: draftFieldOptions, + }, + }, + }, + }, + }}} + + stableAST, err := stripExperimental(input) + if err != nil { + t.Fatalf("stripExperimental() error = %v, want nil", err) + } + output := sanitizeImports(stableAST) + file := output.File[0] + if len(file.MessageType) != 1 || file.MessageType[0].GetName() != "Request" { + t.Fatalf("message types = %v, want only Request (DraftMsg stripped)", file.MessageType) + } + if fields := file.MessageType[0].Field; len(fields) != 0 { + t.Fatalf("fields = %v, want none (draft field stripped)", fields) + } + if _, err := linkStrippedSet(output); err != nil { + t.Fatalf("linkStrippedSet() error = %v, want nil (no dangling reference once both are stripped)", err) + } +} + +func TestValidateRejectsExperimentalOnFileExtension(t *testing.T) { + input := &descriptorpb.FileDescriptorSet{File: []*descriptorpb.FileDescriptorProto{{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + Extension: []*descriptorpb.FieldDescriptorProto{{ + Name: proto.String("my_option"), + Number: proto.Int32(90001), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + Extendee: proto.String(".google.protobuf.MethodOptions"), + Options: experimentalFieldOptions(), + }}, + }}} + + _, err := stripExperimental(input) + if err == nil { + t.Fatal("stripExperimental() error = nil, want error for experimental tag on a file-level extension") + } + if !strings.Contains(err.Error(), "my_option") { + t.Fatalf("stripExperimental() error = %v, want it to name the extension (my_option)", err) + } +} + +func TestValidateRejectsExperimentalOnNestedExtension(t *testing.T) { + input := &descriptorpb.FileDescriptorSet{File: []*descriptorpb.FileDescriptorProto{{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Container"), + Extension: []*descriptorpb.FieldDescriptorProto{{ + Name: proto.String("my_nested_option"), + Number: proto.Int32(90002), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + Extendee: proto.String(".google.protobuf.FieldOptions"), + Options: experimentalFieldOptions(), + }}, + }}, + }}} + + _, err := stripExperimental(input) + if err == nil { + t.Fatal("stripExperimental() error = nil, want error for experimental tag on a nested extension") + } + if !strings.Contains(err.Error(), "my_nested_option") { + t.Fatalf("stripExperimental() error = %v, want it to name the extension (my_nested_option)", err) + } +} diff --git a/cmd/generate-stable/schema.go b/cmd/generate-stable/schema.go new file mode 100644 index 000000000..49b8d3807 --- /dev/null +++ b/cmd/generate-stable/schema.go @@ -0,0 +1,326 @@ +package main + +import ( + "fmt" + "reflect" + "strings" + + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" +) + +const ( + extExperimentalField = protowire.Number(95134) + extExperimentalMessage = protowire.Number(95135) + extExperimentalEnum = protowire.Number(95136) + extExperimentalEnumValue = protowire.Number(95137) + extExperimentalService = protowire.Number(95138) + extExperimentalMethod = protowire.Number(95139) +) + +func filterMessage(msg *descriptorpb.DescriptorProto) bool { + return isExperimental(msg.GetOptions(), extExperimentalMessage) +} + +func filterField(field *descriptorpb.FieldDescriptorProto) bool { + return isExperimental(field.GetOptions(), extExperimentalField) +} + +func filterEnumType(enum *descriptorpb.EnumDescriptorProto) bool { + return isExperimental(enum.GetOptions(), extExperimentalEnum) +} + +func filterEnumValue(value *descriptorpb.EnumValueDescriptorProto) bool { + return isExperimental(value.GetOptions(), extExperimentalEnumValue) +} + +func filterService(service *descriptorpb.ServiceDescriptorProto) bool { + return isExperimental(service.GetOptions(), extExperimentalService) +} + +func filterMethod(method *descriptorpb.MethodDescriptorProto) bool { + return isExperimental(method.GetOptions(), extExperimentalMethod) +} + +func filterExtension(extension *descriptorpb.FieldDescriptorProto) bool { + // Extensions are essentially fields, so they use the field option. + return isExperimental(extension.GetOptions(), extExperimentalField) +} + +func validateTagsOnNodes(file *descriptorpb.FileDescriptorProto) error { + for _, msg := range file.MessageType { + if err := validateMessageTags(msg, file.GetName(), ""); err != nil { + return err + } + } + for _, ext := range file.Extension { + if filterExtension(ext) { + return fmt.Errorf("experimental tags on extensions are not currently supported. Found on extension '%s' in file '%s'", ext.GetName(), file.GetName()) + } + } + return nil +} + +func validateMessageTags(msg *descriptorpb.DescriptorProto, filename, prefix string) error { + msgName := joinProtoName(prefix, msg.GetName()) + for _, ext := range msg.Extension { + if filterExtension(ext) { + return fmt.Errorf("experimental tags on nested extensions are not currently supported. Found on extension '%s' in message '%s' in file '%s'", ext.GetName(), msg.GetName(), filename) + } + } + for _, nested := range msg.NestedType { + if err := validateMessageTags(nested, filename, msgName); err != nil { + return err + } + } + return nil +} + +// ------------------------------------------------------------------------- +// AST STRIPPING LOGIC +// ------------------------------------------------------------------------- + +func stripExperimental(inputFiles *descriptorpb.FileDescriptorSet) (*descriptorpb.FileDescriptorSet, error) { + outputFiles := &descriptorpb.FileDescriptorSet{ + File: make([]*descriptorpb.FileDescriptorProto, 0, len(inputFiles.File)), + } + + // Validate before stripping (1.5) - tag-placement only; see + // validateTagsOnNodes for why type-reference checking was removed here + // (T11, worklist Aug 17). + for _, file := range inputFiles.File { + if isAPINextPath(file.GetName()) { + if err := validateTagsOnNodes(file); err != nil { + return nil, err + } + } + } + + // Create a stable projection for every api_next file, except the + // api_next-only ones (see nextOnlyFiles): those are dropped from the + // output set entirely, so nothing in the stable API can reference them. + for _, file := range inputFiles.File { + if isNextOnlyPath(file.GetName()) { + continue + } + if isAPINextPath(file.GetName()) { + // strip the experimental nodes from the file + outputFiles.File = append(outputFiles.File, stripFile(file)) + } else { + // keep the non-api_next files as is + outputFiles.File = append(outputFiles.File, proto.Clone(file).(*descriptorpb.FileDescriptorProto)) + } + } + + return outputFiles, nil +} + +func stripFile(input *descriptorpb.FileDescriptorProto) *descriptorpb.FileDescriptorProto { + output := proto.Clone(input).(*descriptorpb.FileDescriptorProto) + output.Name = proto.String(stablePath(input.GetName())) + + // Pre-rewrite the imports in Phase 1 so they point to the other stripped files + // in the new output set, rather than colliding with the source files. + // record the imports so cleanup can happen later + for i, dependency := range output.Dependency { + output.Dependency[i] = stablePath(dependency) + } + + output.MessageType = nil + output.EnumType = nil + output.Service = nil + + for _, msg := range input.MessageType { + if filterMessage(msg) { + continue + } + output.MessageType = append(output.MessageType, stripMessage(msg, input.GetPackage(), "")) + } + for _, enum := range input.EnumType { + if filterEnumType(enum) { + continue + } + output.EnumType = append(output.EnumType, stripEnum(enum)) + } + for _, srv := range input.Service { + if filterService(srv) { + continue + } + output.Service = append(output.Service, stripService(srv)) + } + // handle Extensions and Extension Fields - probably not needed/maybe should fail, whats the use-case of an experimental extension?? + // We do not clear output.Extension because we do not support stripping them; + // the validation phase ensures no extensions are marked experimental, so we just keep them all. + + // T2: SourceCodeInfo isn't valid at this point - message_type/enum_type/ + // service just got renumbered (or dropped some elements) without it + // being updated. It's intentionally left unset here rather than carrying + // over the (now wrong) clone from above; main.go rebuilds it from + // scratch once the whole stripped set is linked, via + // rebuildSourceCodeInfo in sourceinfo.go + output.SourceCodeInfo = nil + return output +} + +// stripMessage strips msg's experimental fields/nested types/enums. pkg and +// prefix are msg's own package/nesting context (mirroring catalog.go's +// indexMessage) - needed only to compute msg's fully-qualified name for +// mapEntryFieldSurvives, which must compare a field's TypeName (always fully +// qualified) against a nested map-entry's fully qualified name, not its bare +// short name (T12 follow-up, worklist Aug 17: a suffix-only comparison could +// false-match an unrelated field whose type happens to share the entry's +// bare name). SourceCodeInfo is handled separately, post-link, by +// rebuildSourceCodeInfo - this function only needs to get the structural +// (field/type) filtering right. +func stripMessage(msg *descriptorpb.DescriptorProto, pkg, prefix string) *descriptorpb.DescriptorProto { + out := proto.Clone(msg).(*descriptorpb.DescriptorProto) + out.Field = nil + out.NestedType = nil + out.EnumType = nil + out.OneofDecl = nil + // keep out.Extension as-is because we do not support stripping nested extensions. + + oneofReferenced := make([]bool, len(msg.OneofDecl)) + for _, field := range msg.Field { + if filterField(field) || field.OneofIndex == nil { + continue + } + oneofReferenced[field.GetOneofIndex()] = true + } + + // oneofRemap re-points surviving fields' OneofIndex at their oneof's new + // (renumbered) slot - structural, unrelated to SourceCodeInfo. + oneofRemap := make(map[int32]int32, len(msg.OneofDecl)) + var newOneofIdx int32 + for oldIdx, oneof := range msg.OneofDecl { + if !oneofReferenced[oldIdx] { + continue + } + oneofRemap[int32(oldIdx)] = newOneofIdx + out.OneofDecl = append(out.OneofDecl, proto.Clone(oneof).(*descriptorpb.OneofDescriptorProto)) + newOneofIdx++ + } + + for _, field := range msg.Field { + if filterField(field) { + continue + } + clonedField := proto.Clone(field).(*descriptorpb.FieldDescriptorProto) + if clonedField.OneofIndex != nil { + clonedField.OneofIndex = proto.Int32(oneofRemap[field.GetOneofIndex()]) + } + out.Field = append(out.Field, clonedField) + } + + msgFullName := fullProtoName(pkg, joinProtoName(prefix, msg.GetName())) + for _, nested := range msg.NestedType { + if filterMessage(nested) { + continue + } + if nested.GetOptions().GetMapEntry() && !mapEntryFieldSurvives(msg, nested, msgFullName) { + continue + } + out.NestedType = append(out.NestedType, stripMessage(nested, pkg, joinProtoName(prefix, msg.GetName()))) + } + + for _, enum := range msg.EnumType { + if filterEnumType(enum) { + continue + } + out.EnumType = append(out.EnumType, stripEnum(enum)) + } + + return out +} + +func mapEntryFieldSurvives(msg *descriptorpb.DescriptorProto, nested *descriptorpb.DescriptorProto, msgFullName string) bool { + nestedFullName := msgFullName + "." + nested.GetName() + for _, field := range msg.Field { + if field.GetTypeName() == nestedFullName { + return !filterField(field) + } + } + return true +} + +// stripEnum strips enum's experimental values. +func stripEnum(enum *descriptorpb.EnumDescriptorProto) *descriptorpb.EnumDescriptorProto { + out := proto.Clone(enum).(*descriptorpb.EnumDescriptorProto) + out.Value = nil + + for _, value := range enum.Value { + if filterEnumValue(value) { + continue + } + out.Value = append(out.Value, proto.Clone(value).(*descriptorpb.EnumValueDescriptorProto)) + } + return out +} + +// stripService strips srv's experimental methods. +func stripService(srv *descriptorpb.ServiceDescriptorProto) *descriptorpb.ServiceDescriptorProto { + out := proto.Clone(srv).(*descriptorpb.ServiceDescriptorProto) + out.Method = nil + + for _, method := range srv.Method { + if filterMethod(method) { + continue + } + out.Method = append(out.Method, proto.Clone(method).(*descriptorpb.MethodDescriptorProto)) + } + return out +} + +func isExperimental(options proto.Message, extTag protowire.Number) bool { + if options == nil || reflect.ValueOf(options).IsNil() { + return false + } + + found := false + options.ProtoReflect().Range(func(field protoreflect.FieldDescriptor, _ protoreflect.Value) bool { + found = field.IsExtension() && field.Number() == protoreflect.FieldNumber(extTag) + return !found + }) + if found { + return true + } + + unknown := options.ProtoReflect().GetUnknown() + for len(unknown) > 0 { + number, wireType, tagLength := protowire.ConsumeTag(unknown) + if tagLength < 0 { + return false + } + unknown = unknown[tagLength:] + if number == extTag && wireType == protowire.BytesType { + return true + } + valueLength := protowire.ConsumeFieldValue(number, wireType, unknown) + if valueLength < 0 { + return false + } + unknown = unknown[valueLength:] + } + return false +} + +func sanitizeImports(input *descriptorpb.FileDescriptorSet) *descriptorpb.FileDescriptorSet { + catalog := newCatalog(input) + for _, file := range input.File { + if !isStableAPIPath(file.GetName()) { + continue + } + + imports := catalog.importsFor(file) + file.Dependency = imports.direct + file.PublicDependency = imports.public + file.WeakDependency = imports.weak + } + return input +} + +func stablePath(path string) string { + return strings.Replace(path, apiNextPrefix, stableAPIPrefix, 1) +} diff --git a/cmd/generate-stable/sourceinfo.go b/cmd/generate-stable/sourceinfo.go new file mode 100644 index 000000000..a4c44a23b --- /dev/null +++ b/cmd/generate-stable/sourceinfo.go @@ -0,0 +1,234 @@ +package main + +import ( + "fmt" + "slices" + "strings" + + "github.com/jhump/protoreflect/v2/sourceloc" + "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" +) + +func fixSourceCodeInfo(plugin *protogen.Plugin, output *descriptorpb.FileDescriptorSet) error { + prelim, err := linkStrippedSet(output) + if err != nil { + return fmt.Errorf("preliminary link (for source info remap): %w", err) + } + for _, file := range plugin.Files { + if !file.Generate || !isAPINextPath(file.Desc.Path()) || isNextOnlyPath(file.Desc.Path()) { + continue + } + stableFilePath := stablePath(file.Desc.Path()) + strippedFD, err := prelim.FindFileByPath(stableFilePath) + if err != nil { + return fmt.Errorf("find projected file %q: %w", file.Desc.Path(), err) + } + outFile, err := findFileByName(output, stableFilePath) + if err != nil { + return err + } + rebuilt := rebuildSourceCodeInfo(file.Proto, file.Desc, strippedFD) + if err := validateSourceCodeInfo(file.Proto, file.Desc, strippedFD, rebuilt); err != nil { + return fmt.Errorf("%q: %w", file.Desc.Path(), err) + } + outFile.SourceCodeInfo = rebuilt + } + return nil +} + +func findFileByName(set *descriptorpb.FileDescriptorSet, name string) (*descriptorpb.FileDescriptorProto, error) { + for _, f := range set.File { + if f.GetName() == name { + return f, nil + } + } + return nil, fmt.Errorf("file %q not found in descriptor set", name) +} + +func rebuildSourceCodeInfo(originalProto *descriptorpb.FileDescriptorProto, original, stripped protoreflect.FileDescriptor) *descriptorpb.SourceCodeInfo { + if originalProto.GetSourceCodeInfo() == nil { + return nil + } + + origPathByName := map[protoreflect.FullName]protoreflect.SourcePath{} + allOrigPaths := map[string]bool{} + walkCommentableDescriptors(original, func(d protoreflect.Descriptor) { + p := sourceloc.PathFor(d) + if len(p) == 0 { + return + } + origPathByName[d.FullName()] = p + allOrigPaths[pathKey(p)] = true + }) + + newPathByName := map[protoreflect.FullName]protoreflect.SourcePath{} + walkCommentableDescriptors(stripped, func(d protoreflect.Descriptor) { + p := sourceloc.PathFor(d) + if len(p) == 0 { + return + } + newPathByName[d.FullName()] = p + }) + + remap := map[string]protoreflect.SourcePath{} + for name, origPath := range origPathByName { + if newPath, ok := newPathByName[name]; ok { + remap[pathKey(origPath)] = newPath + } + } + + out := &descriptorpb.SourceCodeInfo{} + for _, loc := range originalProto.GetSourceCodeInfo().GetLocation() { + newPath, ok := remapPath(loc.GetPath(), remap, allOrigPaths) + if !ok { + continue // addressed a declaration that didn't survive stripping + } + newLoc := proto.Clone(loc).(*descriptorpb.SourceCodeInfo_Location) + newLoc.Path = newPath + out.Location = append(out.Location, newLoc) + } + return out +} + +func remapPath(path []int32, remap map[string]protoreflect.SourcePath, allOrigPaths map[string]bool) ([]int32, bool) { + for l := len(path) - len(path)%2; l >= 2; l -= 2 { + key := pathKey(path[:l]) + if !allOrigPaths[key] { + // This prefix was never a real declaration (still inside + // file-level options/syntax, or an untracked container like + // extensions) - keep shrinking toward a real boundary. + continue + } + newPrefix, kept := remap[key] + if !kept { + // Found the real declaration this path is about, and it did NOT + // survive stripping. Drop the whole location now - do not keep + // shrinking to check whether some shorter, enclosing prefix + // happens to still exist (it might; that's irrelevant here). + return nil, false + } + // Found the real declaration and it survived: splice its new + // container path onto whatever trailing sub-field tokens (name, + // number, options...) came after this boundary in the original path. + result := make([]int32, 0, len(newPrefix)+len(path)-l) + result = append(result, newPrefix...) + result = append(result, path[l:]...) + return result, true + } + // No declaration boundary found anywhere in path - it never addressed + // anything stripping could move (e.g. file-level syntax/options), so + // pass it through completely unchanged. + return append([]int32{}, path...), true +} + +func pathKey(p []int32) string { + return fmt.Sprint(p) +} + +// walkCommentableDescriptors visits every declaration in fd that can carry a +// doc comment: messages (incl. nested), fields, oneofs, enums (incl. nested) +// and their values, services and their methods. Extensions are deliberately +// excluded - they're never stripped (see schema.go), so their comments never +// need remapping and their locations pass through remapPath untouched. +func walkCommentableDescriptors(fd protoreflect.FileDescriptor, fn func(protoreflect.Descriptor)) { + for i := 0; i < fd.Messages().Len(); i++ { + walkMessage(fn, fd.Messages().Get(i)) + } + for i := 0; i < fd.Enums().Len(); i++ { + walkEnum(fn, fd.Enums().Get(i)) + } + for i := 0; i < fd.Services().Len(); i++ { + sd := fd.Services().Get(i) + fn(sd) + for j := 0; j < sd.Methods().Len(); j++ { + fn(sd.Methods().Get(j)) + } + } +} + +func walkMessage(fn func(protoreflect.Descriptor), md protoreflect.MessageDescriptor) { + fn(md) + for i := 0; i < md.Fields().Len(); i++ { + fn(md.Fields().Get(i)) + } + for i := 0; i < md.Oneofs().Len(); i++ { + fn(md.Oneofs().Get(i)) + } + for i := 0; i < md.Enums().Len(); i++ { + walkEnum(fn, md.Enums().Get(i)) + } + for i := 0; i < md.Messages().Len(); i++ { + walkMessage(fn, md.Messages().Get(i)) + } +} + +func walkEnum(fn func(protoreflect.Descriptor), ed protoreflect.EnumDescriptor) { + fn(ed) + for i := 0; i < ed.Values().Len(); i++ { + fn(ed.Values().Get(i)) + } +} + +// findByFullName looks up the single descriptor in fd named name, among +// everything walkCommentableDescriptors visits (messages, fields, oneofs, +// enums, enum values, services, methods). Returns ok=false if nothing in fd +// carries that name - which, for stripped, is exactly the "correctly +// dropped" case validateSourceCodeInfo needs to distinguish from a real bug. +func findByFullName(fd protoreflect.FileDescriptor, name protoreflect.FullName) (protoreflect.Descriptor, bool) { + var found protoreflect.Descriptor + walkCommentableDescriptors(fd, func(d protoreflect.Descriptor) { + if found == nil && d.FullName() == name { + found = d + } + }) + return found, found != nil +} + +func validateSourceCodeInfo(originalProto *descriptorpb.FileDescriptorProto, original, stripped protoreflect.FileDescriptor, rebuilt *descriptorpb.SourceCodeInfo) error { + origByPath := map[string]*descriptorpb.SourceCodeInfo_Location{} + for _, loc := range originalProto.GetSourceCodeInfo().GetLocation() { + origByPath[pathKey(loc.GetPath())] = loc + } + rebuiltByPath := map[string]*descriptorpb.SourceCodeInfo_Location{} + for _, loc := range rebuilt.GetLocation() { + rebuiltByPath[pathKey(loc.GetPath())] = loc + } + + var problems []string + walkCommentableDescriptors(original, func(d protoreflect.Descriptor) { + origPath := sourceloc.PathFor(d) + if len(origPath) == 0 { + return + } + origLoc, hadComment := origByPath[pathKey(origPath)] + if !hadComment { + return // nothing to check + } + survivor, survived := findByFullName(stripped, d.FullName()) + if !survived { + return // correctly dropped - the declaration itself is gone, comment loss is expected + } + newPath := sourceloc.PathFor(survivor) + if len(newPath) == 0 { + problems = append(problems, fmt.Sprintf("%s: survived stripping but has no computable path", d.FullName())) + return + } + rebuiltLoc, ok := rebuiltByPath[pathKey(newPath)] + if !ok { + problems = append(problems, fmt.Sprintf("%s: comment lost (had %q)", d.FullName(), origLoc.GetLeadingComments())) + return + } + if rebuiltLoc.GetLeadingComments() != origLoc.GetLeadingComments() || + rebuiltLoc.GetTrailingComments() != origLoc.GetTrailingComments() || + !slices.Equal(rebuiltLoc.GetLeadingDetachedComments(), origLoc.GetLeadingDetachedComments()) { + problems = append(problems, fmt.Sprintf("%s: comment text changed across strip", d.FullName())) + } + }) + if len(problems) > 0 { + return fmt.Errorf("SourceCodeInfo round-trip failed:\n%s", strings.Join(problems, "\n")) + } + return nil +} diff --git a/cmd/generate-stable/sourceinfo_test.go b/cmd/generate-stable/sourceinfo_test.go new file mode 100644 index 000000000..2c35d242e --- /dev/null +++ b/cmd/generate-stable/sourceinfo_test.go @@ -0,0 +1,406 @@ +package main + +import ( + "reflect" + "slices" + "strings" + "testing" + + "github.com/jhump/protoreflect/v2/sourceloc" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" +) + +func TestRemapPathDropsRemovedElement(t *testing.T) { + // message_type[0] and message_type[2] existed originally; only + // message_type[0] (kept at 0) and message_type[2] (kept, renumbered to + // 1) survive stripping - message_type[1] was dropped. + allOrigPaths := map[string]bool{ + pathKey([]int32{fileMessageTypeField, 0}): true, + pathKey([]int32{fileMessageTypeField, 1}): true, + pathKey([]int32{fileMessageTypeField, 2}): true, + } + remap := map[string]protoreflect.SourcePath{ + pathKey([]int32{fileMessageTypeField, 0}): {fileMessageTypeField, 0}, + pathKey([]int32{fileMessageTypeField, 2}): {fileMessageTypeField, 1}, + } + + tests := []struct { + name string + path []int32 + wantPath []int32 + wantOK bool + }{ + {"kept first message", []int32{fileMessageTypeField, 0}, []int32{fileMessageTypeField, 0}, true}, + {"dropped middle message", []int32{fileMessageTypeField, 1}, nil, false}, + {"kept third message renumbered", []int32{fileMessageTypeField, 2}, []int32{fileMessageTypeField, 1}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotPath, gotOK := remapPath(tt.path, remap, allOrigPaths) + if gotOK != tt.wantOK { + t.Fatalf("remapPath(%v) ok = %v, want %v", tt.path, gotOK, tt.wantOK) + } + if gotOK && !reflect.DeepEqual(gotPath, tt.wantPath) { + t.Fatalf("remapPath(%v) = %v, want %v", tt.path, gotPath, tt.wantPath) + } + }) + } +} + +func TestRemapPathPassesThroughUntrackedAndTrailingComponents(t *testing.T) { + // message_type[0]'s field[3] survives, renumbered to field[1]. + allOrigPaths := map[string]bool{ + pathKey([]int32{fileMessageTypeField, 0}): true, + pathKey([]int32{fileMessageTypeField, 0, msgFieldField, 3}): true, + } + remap := map[string]protoreflect.SourcePath{ + pathKey([]int32{fileMessageTypeField, 0}): {fileMessageTypeField, 0}, + pathKey([]int32{fileMessageTypeField, 0, msgFieldField, 3}): {fileMessageTypeField, 0, msgFieldField, 1}, + } + + tests := []struct { + name string + path []int32 + wantPath []int32 + }{ + { + name: "syntax has no index pair, passes through", + path: []int32{12}, + wantPath: []int32{12}, + }, + { + name: "trailing scalar sub-field (field name) passes through untouched", + path: []int32{fileMessageTypeField, 0, msgFieldField, 3, 1}, + wantPath: []int32{fileMessageTypeField, 0, msgFieldField, 1, 1}, + }, + { + // FileDescriptorProto.extension = field 7; never walked by + // walkCommentableDescriptors because extensions are never + // stripped (see schema.go), so it never appears in + // allOrigPaths and passes through whole. + name: "untracked container (extension) passes through entirely", + path: []int32{7, 5, 1}, + wantPath: []int32{7, 5, 1}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotPath, ok := remapPath(tt.path, remap, allOrigPaths) + if !ok { + t.Fatalf("remapPath(%v) ok = false, want true", tt.path) + } + if !reflect.DeepEqual(gotPath, tt.wantPath) { + t.Fatalf("remapPath(%v) = %v, want %v", tt.path, gotPath, tt.wantPath) + } + }) + } +} + +func TestRemapPathNestedContainers(t *testing.T) { + // file.message_type[1] ("Outer") kept at 0. Outer.nested_type[2] + // ("Inner") kept at 0; Outer.nested_type[0] dropped. Inner.field[4] kept + // at 0. + allOrigPaths := map[string]bool{ + pathKey([]int32{fileMessageTypeField, 1}): true, + pathKey([]int32{fileMessageTypeField, 1, msgNestedTypeField, 0}): true, + pathKey([]int32{fileMessageTypeField, 1, msgNestedTypeField, 2}): true, + pathKey([]int32{fileMessageTypeField, 1, msgNestedTypeField, 2, msgFieldField, 4}): true, + pathKey([]int32{fileMessageTypeField, 0}): true, // a whole other dropped top-level message + } + remap := map[string]protoreflect.SourcePath{ + pathKey([]int32{fileMessageTypeField, 1}): {fileMessageTypeField, 0}, + pathKey([]int32{fileMessageTypeField, 1, msgNestedTypeField, 2}): {fileMessageTypeField, 0, msgNestedTypeField, 0}, + pathKey([]int32{fileMessageTypeField, 1, msgNestedTypeField, 2, msgFieldField, 4}): {fileMessageTypeField, 0, msgNestedTypeField, 0, msgFieldField, 0}, + } + + // Path to Outer.Inner.field[4]. + gotPath, ok := remapPath([]int32{fileMessageTypeField, 1, msgNestedTypeField, 2, msgFieldField, 4}, remap, allOrigPaths) + if !ok { + t.Fatal("remapPath: ok = false, want true") + } + want := []int32{fileMessageTypeField, 0, msgNestedTypeField, 0, msgFieldField, 0} + if !reflect.DeepEqual(gotPath, want) { + t.Fatalf("remapPath = %v, want %v", gotPath, want) + } + + // Path to a dropped nested type: Outer.nested_type[0]. + _, ok = remapPath([]int32{fileMessageTypeField, 1, msgNestedTypeField, 0}, remap, allOrigPaths) + if ok { + t.Fatal("remapPath: ok = true for dropped nested_type, want false") + } + + // Path to a message that itself was dropped entirely (file.message_type[0]). + _, ok = remapPath([]int32{fileMessageTypeField, 0}, remap, allOrigPaths) + if ok { + t.Fatal("remapPath: ok = true for dropped message_type, want false") + } +} + +// TestRemapPathDoesNotFallBackToSurvivingAncestor is the regression case +// this design exists to prevent: a location addressing a dropped field +// (draft_field) must not fall back to matching its still-surviving +// enclosing message and be reinterpreted against a sibling's new index. +// Caught by the prototype run before this became production code - see +// worklist T2. +func TestRemapPathDoesNotFallBackToSurvivingAncestor(t *testing.T) { + // Foo (message_type[0]) survives unchanged. Its field[1] (draft_field) + // is dropped; field[2] (beta) survives, renumbered to field[1]. + allOrigPaths := map[string]bool{ + pathKey([]int32{fileMessageTypeField, 0}): true, + pathKey([]int32{fileMessageTypeField, 0, msgFieldField, 1}): true, // draft_field + pathKey([]int32{fileMessageTypeField, 0, msgFieldField, 2}): true, // beta + } + remap := map[string]protoreflect.SourcePath{ + pathKey([]int32{fileMessageTypeField, 0}): {fileMessageTypeField, 0}, + pathKey([]int32{fileMessageTypeField, 0, msgFieldField, 2}): {fileMessageTypeField, 0, msgFieldField, 1}, + } + + _, ok := remapPath([]int32{fileMessageTypeField, 0, msgFieldField, 1}, remap, allOrigPaths) + if ok { + t.Fatal("remapPath: ok = true for dropped field's comment, want false (must not fall back to the surviving enclosing message)") + } +} + +// buildCommentFixture is stripLinkPrint's fixture (TestGoldenCommentRetentionOnMiddleFieldStrip) +// minus gamma - just enough to exercise a real strip (draft_field, middle of +// the list) with real comments on the survivors. Shared by the +// validateSourceCodeInfo tests below, which need direct access to the +// intermediate linked descriptors that stripLinkPrint doesn't return. +func buildCommentFixture() *descriptorpb.FileDescriptorProto { + msgPath := []int32{fileMessageTypeField, 0} + + alpha := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("alpha"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + } + draftField := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("draft_field"), Number: proto.Int32(2), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + Options: experimentalFieldOptions(), + } + beta := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("beta"), Number: proto.Int32(3), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + } + + locFor := func(fieldIdx int32, comment string) *descriptorpb.SourceCodeInfo_Location { + path := append(append([]int32{}, msgPath...), msgFieldField, fieldIdx) + return &descriptorpb.SourceCodeInfo_Location{ + Path: path, + Span: []int32{fieldIdx + 1, 0, 10}, + LeadingComments: proto.String(" " + comment + "\n"), + } + } + + return &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Syntax: proto.String("proto3"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Foo"), + Field: []*descriptorpb.FieldDescriptorProto{alpha, draftField, beta}, + }}, + SourceCodeInfo: &descriptorpb.SourceCodeInfo{ + Location: []*descriptorpb.SourceCodeInfo_Location{ + {Path: []int32{fileMessageTypeField, 0}, Span: []int32{0, 0, 1}, LeadingComments: proto.String(" Foo message\n")}, + locFor(0, "COMMENT FOR alpha"), + locFor(1, "COMMENT FOR draft_field"), + locFor(2, "COMMENT FOR beta"), + }, + }, + } +} + +// TestValidateSourceCodeInfoPassesOnCorrectRebuild is the positive control +// for the two negative tests below: proves validateSourceCodeInfo doesn't +// false-positive on a real, correct rebuildSourceCodeInfo output. Without +// this, a validator that always errored (or always passed) would look +// identical to a working one in the negative tests alone. +func TestValidateSourceCodeInfoPassesOnCorrectRebuild(t *testing.T) { + file := buildCommentFixture() + originalFD := linkStandalone(t, file) + + stripped := stripFile(file) + prelim := linkStandalone(t, stripped) + rebuilt := rebuildSourceCodeInfo(file, originalFD, prelim) + + if err := validateSourceCodeInfo(file, originalFD, prelim, rebuilt); err != nil { + t.Fatalf("validateSourceCodeInfo() error = %v, want nil for a correct rebuild", err) + } +} + +// TestValidateSourceCodeInfoCatchesWrongCommentText simulates the exact +// class of regression validateSourceCodeInfo exists to catch (review notes, +// .agents/worklist.md Aug 17): rebuildSourceCodeInfo attaches the wrong +// comment text to a surviving declaration. Corrupts a real, otherwise-correct +// rebuild rather than hand-crafting a bad SourceCodeInfo from scratch, so the +// only thing under test is the validator's own detection logic. +func TestValidateSourceCodeInfoCatchesWrongCommentText(t *testing.T) { + file := buildCommentFixture() + originalFD := linkStandalone(t, file) + + stripped := stripFile(file) + prelim := linkStandalone(t, stripped) + rebuilt := rebuildSourceCodeInfo(file, originalFD, prelim) + + corrupted := proto.Clone(rebuilt).(*descriptorpb.SourceCodeInfo) + found := false + for _, loc := range corrupted.GetLocation() { + if loc.GetLeadingComments() == " COMMENT FOR beta\n" { + loc.LeadingComments = proto.String(" WRONG COMMENT\n") + found = true + } + } + if !found { + t.Fatal("test setup: didn't find beta's comment location to corrupt") + } + + err := validateSourceCodeInfo(file, originalFD, prelim, corrupted) + if err == nil { + t.Fatal("validateSourceCodeInfo() error = nil, want a failure for a corrupted comment") + } + if !strings.Contains(err.Error(), "beta") { + t.Fatalf("validateSourceCodeInfo() error = %v, want it to name the affected declaration (beta)", err) + } +} + +// TestValidateSourceCodeInfoCatchesLostComment is the other failure shape: +// a surviving declaration's Location is missing from the rebuild entirely +// (comment silently vanished) rather than present with wrong text. +func TestValidateSourceCodeInfoCatchesLostComment(t *testing.T) { + file := buildCommentFixture() + originalFD := linkStandalone(t, file) + + stripped := stripFile(file) + prelim := linkStandalone(t, stripped) + rebuilt := rebuildSourceCodeInfo(file, originalFD, prelim) + + corrupted := &descriptorpb.SourceCodeInfo{} + removed := false + for _, loc := range rebuilt.GetLocation() { + if loc.GetLeadingComments() == " COMMENT FOR beta\n" { + removed = true + continue + } + corrupted.Location = append(corrupted.Location, loc) + } + if !removed { + t.Fatal("test setup: didn't find beta's comment location to remove") + } + + err := validateSourceCodeInfo(file, originalFD, prelim, corrupted) + if err == nil { + t.Fatal("validateSourceCodeInfo() error = nil, want a failure for a lost comment") + } + if !strings.Contains(err.Error(), "beta") { + t.Fatalf("validateSourceCodeInfo() error = %v, want it to name the affected declaration (beta)", err) + } +} + +// TestTrailingAndDetachedCommentsSurviveStripping is T14 (worklist Aug 17): +// every existing fixture across this package only ever set LeadingComments. +// rebuildSourceCodeInfo clones the whole Location and only rewrites Path, so +// TrailingComments/LeadingDetachedComments are expected to travel identically +// - this proves it rather than assuming it from the code path, using +// validateSourceCodeInfo itself as the check (it compares all three comment +// fields, not just LeadingComments), plus a direct check that a stripped +// field's trailing comment doesn't leak onto the next surviving field. +func TestTrailingAndDetachedCommentsSurviveStripping(t *testing.T) { + msgPath := []int32{fileMessageTypeField, 0} + fieldPath := func(idx int32) []int32 { + return append(append([]int32{}, msgPath...), msgFieldField, idx) + } + + alpha := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("alpha"), Number: proto.Int32(1), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + } + draftField := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("draft_field"), Number: proto.Int32(2), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + Options: experimentalFieldOptions(), + } + beta := &descriptorpb.FieldDescriptorProto{ + Name: proto.String("beta"), Number: proto.Int32(3), + Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), + Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(), + } + + file := &descriptorpb.FileDescriptorProto{ + Name: proto.String("temporal/api_next/example/v1/message.proto"), + Package: proto.String("example.v1"), + Syntax: proto.String("proto3"), + Options: &descriptorpb.FileOptions{ + GoPackage: proto.String("go.temporal.io/api/example/v1;example"), + }, + MessageType: []*descriptorpb.DescriptorProto{{ + Name: proto.String("Foo"), + Field: []*descriptorpb.FieldDescriptorProto{alpha, draftField, beta}, + }}, + SourceCodeInfo: &descriptorpb.SourceCodeInfo{ + Location: []*descriptorpb.SourceCodeInfo_Location{ + {Path: msgPath, Span: []int32{0, 0, 1}, LeadingComments: proto.String(" Foo message\n")}, + { + Path: fieldPath(0), + Span: []int32{1, 0, 10}, + TrailingComments: proto.String(" inline trailing comment for alpha\n"), + }, + { + Path: fieldPath(1), + Span: []int32{2, 0, 10}, + TrailingComments: proto.String(" inline trailing comment for draft_field - must not survive\n"), + }, + { + Path: fieldPath(2), + Span: []int32{3, 0, 10}, + LeadingComments: proto.String(" leading comment for beta\n"), + LeadingDetachedComments: []string{" detached paragraph above beta, separated by a blank line\n"}, + }, + }, + }, + } + + originalFD := linkStandalone(t, file) + stripped := stripFile(file) + prelim := linkStandalone(t, stripped) + rebuilt := rebuildSourceCodeInfo(file, originalFD, prelim) + + if err := validateSourceCodeInfo(file, originalFD, prelim, rebuilt); err != nil { + t.Fatalf("validateSourceCodeInfo() error = %v, want nil - trailing/detached comments should round-trip like leading comments", err) + } + + betaFD := prelim.Messages().Get(0).Fields().ByName("beta") + if betaFD == nil { + t.Fatal("test setup: beta not found in stripped/linked descriptor") + } + betaNewPath := pathKey(sourceloc.PathFor(betaFD)) + var betaLoc *descriptorpb.SourceCodeInfo_Location + for _, loc := range rebuilt.GetLocation() { + if pathKey(loc.GetPath()) == betaNewPath { + betaLoc = loc + } + } + if betaLoc == nil { + t.Fatal("beta's rebuilt Location not found") + } + if betaLoc.GetTrailingComments() != "" { + t.Fatalf("beta's TrailingComments = %q, want empty (draft_field's trailing comment must not leak onto beta)", betaLoc.GetTrailingComments()) + } + if got, want := betaLoc.GetLeadingComments(), " leading comment for beta\n"; got != want { + t.Fatalf("beta's LeadingComments = %q, want %q", got, want) + } + wantDetached := []string{" detached paragraph above beta, separated by a blank line\n"} + if got := betaLoc.GetLeadingDetachedComments(); !slices.Equal(got, wantDetached) { + t.Fatalf("beta's LeadingDetachedComments = %v, want %v", got, wantDetached) + } +} diff --git a/temporal/api/activity/v1/message.proto b/temporal/api/activity/v1/message.proto new file mode 100644 index 000000000..3671b2249 --- /dev/null +++ b/temporal/api/activity/v1/message.proto @@ -0,0 +1,281 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.activity.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/callback/v1/message.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/deployment/v1/message.proto"; +import "temporal/api/enums/v1/activity.proto"; +import "temporal/api/enums/v1/workflow.proto"; +import "temporal/api/failure/v1/message.proto"; +import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api/taskqueue/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Activity.V1"; +option go_package = "go.temporal.io/api/activity/v1;activity"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.activity.v1"; +option ruby_package = "Temporalio::Api::Activity::V1"; + +// The outcome of a completed activity execution: either a successful result or a failure. +message ActivityExecutionOutcome { + oneof value { + // The result if the activity completed successfully. + temporal.api.common.v1.Payloads result = 1; + + // The failure if the activity completed unsuccessfully. + temporal.api.failure.v1.Failure failure = 2; + } + + // The retry state associated with an unsuccessful activity execution. + // This field is only meaningful when `failure` is set. + temporal.api.enums.v1.RetryState retry_state = 3; +} + +message ActivityOptions { + temporal.api.taskqueue.v1.TaskQueue task_queue = 1; + + // Indicates how long the caller is willing to wait for an activity completion. Limits how long + // retries will be attempted. Either this or `start_to_close_timeout` must be specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 2; + + // Limits time an activity task can stay in a task queue before a worker picks it up. This + // timeout is always non retryable, as all a retry would achieve is to put it back into the same + // queue. Defaults to `schedule_to_close_timeout` or workflow execution timeout if not + // specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 3; + + // Maximum time an activity is allowed to execute after being picked up by a worker. This + // timeout is always retryable. Either this or `schedule_to_close_timeout` must be + // specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 4; + + // Maximum permitted time between successful worker heartbeats. + google.protobuf.Duration heartbeat_timeout = 5; + + // The retry policy for the activity. Will never exceed `schedule_to_close_timeout`. + temporal.api.common.v1.RetryPolicy retry_policy = 6; + + // Priority metadata. If this message is not present, or any fields are not + // present, they inherit the values from the workflow. + temporal.api.common.v1.Priority priority = 7; + + // Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts. + // When updated, the time is added to the original `schedule_time`, not to the current time. + // If the resulting time is in the past, the task is made available for dispatch immediately. + google.protobuf.Duration start_delay = 8; +} + +// Information about a standalone activity. +message ActivityExecutionInfo { + // Unique identifier of this activity within its namespace along with run ID (below). + string activity_id = 1; + + string run_id = 2; + + // The type of the activity, a string that maps to a registered activity on a worker. + temporal.api.common.v1.ActivityType activity_type = 3; + + // A general status for this activity, indicates whether it is currently running or in one of the terminal statuses. + temporal.api.enums.v1.ActivityExecutionStatus status = 4; + + // More detailed breakdown of ACTIVITY_EXECUTION_STATUS_RUNNING. + temporal.api.enums.v1.PendingActivityState run_state = 5; + + string task_queue = 6; + + // Indicates how long the caller is willing to wait for an activity completion. Limits how long + // retries will be attempted. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 7; + + // Limits time an activity task can stay in a task queue before a worker picks it up. This + // timeout is always non retryable, as all a retry would achieve is to put it back into the same + // queue. Defaults to `schedule_to_close_timeout`. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 8; + + // Maximum time a single activity attempt is allowed to execute after being picked up by a worker. This + // timeout is always retryable. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 9; + + // Maximum permitted time between successful worker heartbeats. + google.protobuf.Duration heartbeat_timeout = 10; + + // The retry policy for the activity. Will never exceed `schedule_to_close_timeout`. + temporal.api.common.v1.RetryPolicy retry_policy = 11; + + // Details provided in the last recorded activity heartbeat. + // DescribeActivityExecution does not set this field unless include_heartbeat_details was true in the request. + temporal.api.common.v1.Payloads heartbeat_details = 12; + + // Time the last heartbeat was recorded. + google.protobuf.Timestamp last_heartbeat_time = 13; + + // Time the last attempt was started. + google.protobuf.Timestamp last_started_time = 14; + + // The attempt this activity is currently on. Incremented each time a new attempt is scheduled. + int32 attempt = 15; + + // How long this activity has been running for, including all attempts and backoff between attempts. + google.protobuf.Duration execution_duration = 16; + + // Time the activity was originally scheduled via a StartActivityExecution request. + google.protobuf.Timestamp schedule_time = 17; + + // The time at which the activity's Schedule-to-Close timeout expires. + // Calculated as `schedule_time` + `start_delay` + `schedule_to_close_timeout`. + google.protobuf.Timestamp expiration_time = 18; + + // Time when the activity transitioned to a closed state. + google.protobuf.Timestamp close_time = 19; + + // Failure details from the last failed attempt. + // DescribeActivityExecution does not set this field unless include_last_failure was true in the request. + temporal.api.failure.v1.Failure last_failure = 20; + + string last_worker_identity = 21; + + // Time from the last attempt failure to the next activity retry. + // If the activity is currently running, this represents the next retry interval in case the attempt fails. + // If activity is currently backing off between attempt, this represents the current retry interval. + // If there is no next retry allowed, this field will be null. + // This interval is typically calculated from the specified retry policy, but may be modified if an activity fails + // with a retryable application failure specifying a retry delay. + google.protobuf.Duration current_retry_interval = 22; + + // The time when the last activity attempt completed. If activity has not been completed yet, it will be null. + google.protobuf.Timestamp last_attempt_complete_time = 23; + + // The time when the next activity attempt will be scheduled. + // If activity is currently scheduled or started, this field will be null. + google.protobuf.Timestamp next_attempt_schedule_time = 24; + + // The Worker Deployment Version this activity was dispatched to most recently. + // If nil, the activity has not yet been dispatched or was last dispatched to an unversioned worker. + temporal.api.deployment.v1.WorkerDeploymentVersion last_deployment_version = 25; + + // Priority metadata. + temporal.api.common.v1.Priority priority = 26; + + // Incremented each time the activity's state is mutated in persistence. + int64 state_transition_count = 27; + + // Updated once on scheduled and once on terminal status. + int64 state_size_bytes = 28; + + temporal.api.common.v1.SearchAttributes search_attributes = 29; + + temporal.api.common.v1.Header header = 30; + + // Metadata for use by user interfaces to display the fixed as-of-start summary and details of the activity. + temporal.api.sdk.v1.UserMetadata user_metadata = 31; + + // Set if activity cancelation was requested. + string canceled_reason = 32; + + // Links to related entities, such as the entity that started this activity. + repeated temporal.api.common.v1.Link links = 33; + + // Total number of heartbeats recorded across all attempts of this activity, including retries. + int64 total_heartbeat_count = 34; + + // The name of the SDK of the worker that most recently picked up an attempt of this activity. + // Overwritten on each new attempt. Empty if unknown. + string sdk_name = 35; + + // The version of the SDK of the worker that most recently picked up an attempt of this activity. + // Overwritten on each new attempt. Empty if unknown. + string sdk_version = 36; + + // Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts. + google.protobuf.Duration start_delay = 37; + + // The time at which the first activity task is made available for dispatch, computed as + // `schedule_time + start_delay`. Same as `schedule_time` if `start_delay` is not set. + google.protobuf.Timestamp execution_time = 38; +} + +// Limited activity information returned in the list response. +// When adding fields here, ensure that it is also present in ActivityExecutionInfo (note that it +// may already be present in ActivityExecutionInfo but not at the top-level). +message ActivityExecutionListInfo { + // A unique identifier of this activity within its namespace along with run ID (below). + string activity_id = 1; + + // The run ID of the standalone activity. + string run_id = 2; + + // The type of the activity, a string that maps to a registered activity on a worker. + temporal.api.common.v1.ActivityType activity_type = 3; + + // Time the activity was originally scheduled via a StartActivityExecution request. + google.protobuf.Timestamp schedule_time = 4; + + // If the activity is in a terminal status, this field represents the time the activity transitioned to that status. + google.protobuf.Timestamp close_time = 5; + + // Only scheduled and terminal statuses appear here. More detailed information in PendingActivityInfo but not + // available in the list response. + temporal.api.enums.v1.ActivityExecutionStatus status = 6; + + // Search attributes from the start request. + temporal.api.common.v1.SearchAttributes search_attributes = 7; + + // The task queue this activity was scheduled on when it was originally started, updated on activity options update. + string task_queue = 8; + + // Updated on terminal status. + int64 state_transition_count = 9; + + // Updated once on scheduled and once on terminal status. + int64 state_size_bytes = 10; + + // The difference between close time and scheduled time. + // This field is only populated if the activity is closed. + google.protobuf.Duration execution_duration = 11; + + // The time at which the first activity task is made available for dispatch, computed as + // `schedule_time + start_delay`. Same as `schedule_time` if `start_delay` is not set. + google.protobuf.Timestamp execution_time = 12; +} + +// CallbackInfo contains the state of an attached activity callback. +message CallbackInfo { + // Trigger for when the activity is closed. + message ActivityClosed {} + + message Trigger { + oneof variant { + ActivityClosed activity_closed = 1; + } + } + + // Trigger for this callback. + Trigger trigger = 1; + + // Common callback info. + temporal.api.callback.v1.CallbackInfo info = 2; +} diff --git a/temporal/api/batch/v1/message.proto b/temporal/api/batch/v1/message.proto new file mode 100644 index 000000000..2a009dd76 --- /dev/null +++ b/temporal/api/batch/v1/message.proto @@ -0,0 +1,239 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.batch.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/activity/v1/message.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/enums/v1/batch_operation.proto"; +import "temporal/api/enums/v1/reset.proto"; +import "temporal/api/rules/v1/message.proto"; +import "temporal/api/workflow/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Batch.V1"; +option go_package = "go.temporal.io/api/batch/v1;batch"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.batch.v1"; +option ruby_package = "Temporalio::Api::Batch::V1"; + +message BatchOperationInfo { + // Batch job ID + string job_id = 1; + + // Batch operation state + temporal.api.enums.v1.BatchOperationState state = 2; + + // Batch operation start time + google.protobuf.Timestamp start_time = 3; + + // Batch operation close time + google.protobuf.Timestamp close_time = 4; + + // Operation type + temporal.api.enums.v1.BatchOperationType operation_type = 5; +} + +// BatchOperationTermination sends terminate requests to batch workflows. +// Keep the parameter in sync with temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest. +// Ignore first_execution_run_id because this is used for single workflow operation. +message BatchOperationTermination { + // Serialized value(s) to provide to the termination event + temporal.api.common.v1.Payloads details = 1; + + // The identity of the worker/client + string identity = 2; +} + +// BatchOperationTerminateActivities sends terminate requests to a batch of activities. +// Keep the parameter in sync with temporal.api.workflowservice.v1.TerminateActivityExecutionRequest. +message BatchOperationTerminateActivities { + // The identity of the worker/client + string identity = 1; + + // Reason for requesting the termination, recorded and available via the PollActivityExecution API. + // Not propagated to a worker if an activity attempt is currently running. + string reason = 2; +} + +// BatchOperationSignal sends signals to batch workflows. +// Keep the parameter in sync with temporal.api.workflowservice.v1.SignalWorkflowExecutionRequest. +message BatchOperationSignal { + // The workflow author-defined name of the signal to send to the workflow + string signal = 1; + + // Serialized value(s) to provide with the signal + temporal.api.common.v1.Payloads input = 2; + + // Headers that are passed with the signal to the processing workflow. + // These can include things like auth or tracing tokens. + temporal.api.common.v1.Header header = 3; + + // The identity of the worker/client + string identity = 4; +} + +// BatchOperationCancellation sends cancel requests to batch workflows. +// Keep the parameter in sync with temporal.api.workflowservice.v1.RequestCancelWorkflowExecutionRequest. +// Ignore first_execution_run_id because this is used for single workflow operation. +message BatchOperationCancellation { + // The identity of the worker/client + string identity = 1; +} + +// BatchOperationCancelActivities sends cancel requests to a batch of activities. +// Keep the parameter in sync with temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest. +message BatchOperationCancelActivities { + // The identity of the worker/client + string identity = 1; + + // Reason for requesting the cancellation, recorded and available via the PollActivityExecution API. + // Not propagated to a worker if an activity attempt is currently running. + string reason = 2; +} + +// BatchOperationDeletion sends deletion requests to batch workflows. +// Keep the parameter in sync with temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest. +message BatchOperationDeletion { + // The identity of the worker/client + string identity = 1; +} + +// BatchOperationDeleteActivities sends deletion requests to a batch of activities. +// Keep the parameter in sync with temporal.api.workflowservice.v1.DeleteActivityExecutionRequest. +message BatchOperationDeleteActivities {} + +// BatchOperationReset sends reset requests to batch workflows. +// Keep the parameter in sync with temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest. +message BatchOperationReset { + // The identity of the worker/client. + string identity = 3; + + // Describes what to reset to and how. If set, `reset_type` and `reset_reapply_type` are ignored. + temporal.api.common.v1.ResetOptions options = 4; + + // Deprecated. Use `options`. + temporal.api.enums.v1.ResetType reset_type = 1 [deprecated = true]; + + // Deprecated. Use `options`. + temporal.api.enums.v1.ResetReapplyType reset_reapply_type = 2 [deprecated = true]; + + // Operations to perform after the workflow has been reset. These operations will be applied + // to the *new* run of the workflow execution in the order they are provided. + // All operations are applied to the workflow before the first new workflow task is generated + repeated temporal.api.workflow.v1.PostResetOperation post_reset_operations = 5; +} + +// BatchOperationUpdateWorkflowExecutionOptions sends UpdateWorkflowExecutionOptions requests to batch workflows. +// Keep the parameters in sync with temporal.api.workflowservice.v1.UpdateWorkflowExecutionOptionsRequest. +message BatchOperationUpdateWorkflowExecutionOptions { + // The identity of the worker/client. + string identity = 1; + + // Update Workflow options that were originally specified via StartWorkflowExecution. Partial updates are accepted and controlled by update_mask. + temporal.api.workflow.v1.WorkflowExecutionOptions workflow_execution_options = 2; + + // Controls which fields from `workflow_execution_options` will be applied. + // To unset a field, set it to null and use the update mask to indicate that it should be mutated. + google.protobuf.FieldMask update_mask = 3; +} + +// BatchOperationUnpauseActivities sends unpause requests to batch workflows. +message BatchOperationUnpauseActivities { + // The identity of the worker/client. + string identity = 1; + + // The activity to unpause. If match_all is set to true, all activities will be unpaused. + oneof activity { + string type = 2; + + bool match_all = 3; + } + + // Setting this flag will also reset the number of attempts. + bool reset_attempts = 4; + + // Setting this flag will also reset the heartbeat details. + bool reset_heartbeat = 5; + + // If set, the activity will start at a random time within the specified jitter + // duration, introducing variability to the start time. + google.protobuf.Duration jitter = 6; +} + +// BatchOperationTriggerWorkflowRule sends TriggerWorkflowRule requests to batch workflows. +message BatchOperationTriggerWorkflowRule { + // The identity of the worker/client. + string identity = 1; + + oneof rule { + // ID of existing rule. + string id = 2; + + // Rule specification to be applied to the workflow without creating a new rule. + temporal.api.rules.v1.WorkflowRuleSpec spec = 3; + } +} + +// BatchOperationResetActivities sends activity reset requests in a batch. +// NOTE: keep in sync with temporal.api.workflowservice.v1.ResetActivityRequest +message BatchOperationResetActivities { + // The identity of the worker/client. + string identity = 1; + + // The activities to reset. If match_all is set to true, all activities will be reset. + oneof activity { + string type = 2; + + bool match_all = 3; + } + + // Setting this flag will also reset the number of attempts. + bool reset_attempts = 4; + + // Setting this flag will also reset the heartbeat details. + bool reset_heartbeat = 5; + + // If activity is paused, it will remain paused after reset + bool keep_paused = 6; + + // If set, the activity will start at a random time within the specified jitter + // duration, introducing variability to the start time. + google.protobuf.Duration jitter = 7; + + // If set, the activity options will be restored to the defaults. + // Default options are then options activity was created with. + // They are part of the first ActivityTaskScheduled event. + bool restore_original_options = 8; +} + +// BatchOperationUpdateActivityOptions sends an update-activity-options requests in a batch. +// NOTE: keep in sync with temporal.api.workflowservice.v1.UpdateActivityRequest +message BatchOperationUpdateActivityOptions { + // The identity of the worker/client. + string identity = 1; + + // The activity to update. If match_all is set to true, all activities will be updated. + oneof activity { + string type = 2; + + bool match_all = 3; + } + + // Update Activity options. Partial updates are accepted and controlled by update_mask. + temporal.api.activity.v1.ActivityOptions activity_options = 4; + + // Controls which fields from `activity_options` will be applied + google.protobuf.FieldMask update_mask = 5; + + // If set, the activity options will be restored to the default. + // Default options are then options activity was created with. + // They are part of the first ActivityTaskScheduled event. + // This flag cannot be combined with any other option; if you supply + // restore_original together with other options, the request will be rejected. + bool restore_original = 6; +} diff --git a/temporal/api/callback/v1/message.proto b/temporal/api/callback/v1/message.proto new file mode 100644 index 000000000..bb7703bcb --- /dev/null +++ b/temporal/api/callback/v1/message.proto @@ -0,0 +1,45 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.callback.v1; + +import "google/protobuf/timestamp.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/enums/v1/common.proto"; +import "temporal/api/failure/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Callback.V1"; +option go_package = "go.temporal.io/api/callback/v1;callback"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.callback.v1"; +option ruby_package = "Temporalio::Api::Callback::V1"; + +// Common callback information. Specific CallbackInfo messages should embed this and may include additional fields. +message CallbackInfo { + // Information on how this callback should be invoked (e.g. its URL and type). + temporal.api.common.v1.Callback callback = 1; + + // The time when the callback was registered. + google.protobuf.Timestamp registration_time = 2; + + // The current state of the callback. + temporal.api.enums.v1.CallbackState state = 3; + + // The number of attempts made to deliver the callback. + // This number represents a minimum bound since the attempt is incremented after the callback request completes. + int32 attempt = 4; + + // The time when the last attempt completed. + google.protobuf.Timestamp last_attempt_complete_time = 5; + + // The last attempt's failure, if any. + temporal.api.failure.v1.Failure last_attempt_failure = 6; + + // The time when the next attempt is scheduled. + google.protobuf.Timestamp next_attempt_schedule_time = 7; + + // If the state is BLOCKED, blocked reason provides additional information. + string blocked_reason = 8; +} diff --git a/temporal/api/command/v1/message.proto b/temporal/api/command/v1/message.proto new file mode 100644 index 000000000..359b64610 --- /dev/null +++ b/temporal/api/command/v1/message.proto @@ -0,0 +1,405 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.command.v1; + +import "google/protobuf/duration.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/enums/v1/command_type.proto"; +import "temporal/api/enums/v1/workflow.proto"; +import "temporal/api/failure/v1/message.proto"; +import "temporal/api/sdk/v1/event_group_marker.proto"; +import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api/taskqueue/v1/message.proto"; +import "temporal/api/workflow/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Command.V1"; +option go_package = "go.temporal.io/api/command/v1;command"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.command.v1"; +option ruby_package = "Temporalio::Api::Command::V1"; + +message ScheduleActivityTaskCommandAttributes { + string activity_id = 1; + + temporal.api.common.v1.ActivityType activity_type = 2; + + reserved 3; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 4; + + temporal.api.common.v1.Header header = 5; + + temporal.api.common.v1.Payloads input = 6; + + // Indicates how long the caller is willing to wait for activity completion. The "schedule" time + // is when the activity is initially scheduled, not when the most recent retry is scheduled. + // Limits how long retries will be attempted. Either this or `start_to_close_timeout` must be + // specified. When not specified, defaults to the workflow execution timeout. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 7; + + // Limits the time an activity task can stay in a task queue before a worker picks it up. The + // "schedule" time is when the most recent retry is scheduled. This timeout should usually not + // be set: it's useful in specific scenarios like worker-specific task queues. This timeout is + // always non retryable, as all a retry would achieve is to put it back into the same queue. + // Defaults to `schedule_to_close_timeout` or workflow execution timeout if that is not + // specified. More info: + // https://docs.temporal.io/docs/content/what-is-a-schedule-to-start-timeout/ + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 8; + + // Maximum time an activity is allowed to execute after being picked up by a worker. This + // timeout is always retryable. Either this or `schedule_to_close_timeout` must be specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 9; + + // Maximum permitted time between successful worker heartbeats. + google.protobuf.Duration heartbeat_timeout = 10; + + // Activities are provided by a default retry policy which is controlled through the service's + // dynamic configuration. Retries will be attempted until `schedule_to_close_timeout` has + // elapsed. To disable retries set retry_policy.maximum_attempts to 1. + temporal.api.common.v1.RetryPolicy retry_policy = 11; + + // Request to start the activity directly bypassing matching service and worker polling + // The slot for executing the activity should be reserved when setting this field to true. + bool request_eager_execution = 12; + + // If this is set, the activity would be assigned to the Build ID of the workflow. Otherwise, + // Assignment rules of the activity's Task Queue will be used to determine the Build ID. + bool use_workflow_build_id = 13; + + // Priority metadata. If this message is not present, or any fields are not + // present, they inherit the values from the workflow. + temporal.api.common.v1.Priority priority = 14; +} + +message RequestCancelActivityTaskCommandAttributes { + // The `ACTIVITY_TASK_SCHEDULED` event id for the activity being cancelled. + int64 scheduled_event_id = 1; +} + +message StartTimerCommandAttributes { + // An id for the timer, currently live timers must have different ids. Typically autogenerated + // by the SDK. + string timer_id = 1; + + // How long until the timer fires, producing a `TIMER_FIRED` event. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_fire_timeout = 2; +} + +message CompleteWorkflowExecutionCommandAttributes { + temporal.api.common.v1.Payloads result = 1; +} + +message FailWorkflowExecutionCommandAttributes { + temporal.api.failure.v1.Failure failure = 1; +} + +message CancelTimerCommandAttributes { + // The same timer id from the start timer command + string timer_id = 1; +} + +message CancelWorkflowExecutionCommandAttributes { + temporal.api.common.v1.Payloads details = 1; +} + +message RequestCancelExternalWorkflowExecutionCommandAttributes { + // Deprecated. Cross-namespace operations are disabled by default as of server 1.30.1. + string namespace = 1 [deprecated = true]; + + string workflow_id = 2; + + string run_id = 3; + + // Deprecated. + string control = 4 [deprecated = true]; + + // Set this to true if the workflow being cancelled is a child of the workflow originating this + // command. The request will be rejected if it is set to true and the target workflow is *not* + // a child of the requesting workflow. + bool child_workflow_only = 5; + + // Reason for requesting the cancellation + string reason = 6; +} + +message SignalExternalWorkflowExecutionCommandAttributes { + // Deprecated. Cross-namespace operations are disabled by default as of server 1.30.1. + string namespace = 1 [deprecated = true]; + + temporal.api.common.v1.WorkflowExecution execution = 2; + + // The workflow author-defined name of the signal to send to the workflow. + string signal_name = 3; + + // Serialized value(s) to provide with the signal. + temporal.api.common.v1.Payloads input = 4; + + // Deprecated + string control = 5 [deprecated = true]; + + // Set this to true if the workflow being cancelled is a child of the workflow originating this + // command. The request will be rejected if it is set to true and the target workflow is *not* + // a child of the requesting workflow. + bool child_workflow_only = 6; + + // Headers that are passed by the workflow that is sending a signal to the external + // workflow that is receiving this signal. + temporal.api.common.v1.Header header = 7; +} + +message UpsertWorkflowSearchAttributesCommandAttributes { + temporal.api.common.v1.SearchAttributes search_attributes = 1; +} + +message ModifyWorkflowPropertiesCommandAttributes { + // If set, update the workflow memo with the provided values. The values will be merged with + // the existing memo. If the user wants to delete values, a default/empty Payload should be + // used as the value for the key being deleted. + temporal.api.common.v1.Memo upserted_memo = 1; +} + +message RecordMarkerCommandAttributes { + string marker_name = 1; + + map details = 2; + + temporal.api.common.v1.Header header = 3; + + temporal.api.failure.v1.Failure failure = 4; +} + +message ContinueAsNewWorkflowExecutionCommandAttributes { + temporal.api.common.v1.WorkflowType workflow_type = 1; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 2; + + temporal.api.common.v1.Payloads input = 3; + + // Timeout of a single workflow run. + google.protobuf.Duration workflow_run_timeout = 4; + + // Timeout of a single workflow task. + google.protobuf.Duration workflow_task_timeout = 5; + + // How long the workflow start will be delayed - not really a "backoff" in the traditional sense. + google.protobuf.Duration backoff_start_interval = 6; + + temporal.api.common.v1.RetryPolicy retry_policy = 7; + + // Should be removed + temporal.api.enums.v1.ContinueAsNewInitiator initiator = 8; + + // Should be removed + temporal.api.failure.v1.Failure failure = 9; + + // Should be removed + temporal.api.common.v1.Payloads last_completion_result = 10; + + // Should be removed. Not necessarily unused but unclear and not exposed by SDKs. + string cron_schedule = 11; + + temporal.api.common.v1.Header header = 12; + + temporal.api.common.v1.Memo memo = 13; + + temporal.api.common.v1.SearchAttributes search_attributes = 14; + + // If this is set, the new execution inherits the Build ID of the current execution. Otherwise, + // the assignment rules will be used to independently assign a Build ID to the new execution. + // Deprecated. Only considered for versioning v0.2. + bool inherit_build_id = 15 [deprecated = true]; + + // Experimental. Optionally decide the versioning behavior that the first task of the new run should use. + // For example, choose to AutoUpgrade on continue-as-new instead of inheriting the pinned version + // of the previous run. + temporal.api.enums.v1.ContinueAsNewVersioningBehavior initial_versioning_behavior = 16; +} + +message StartChildWorkflowExecutionCommandAttributes { + // Deprecated. Cross-namespace operations are disabled by default as of server 1.30.1. + string namespace = 1 [deprecated = true]; + + string workflow_id = 2; + + temporal.api.common.v1.WorkflowType workflow_type = 3; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 4; + + temporal.api.common.v1.Payloads input = 5; + + // Total workflow execution timeout including retries and continue as new. + google.protobuf.Duration workflow_execution_timeout = 6; + + // Timeout of a single workflow run. + google.protobuf.Duration workflow_run_timeout = 7; + + // Timeout of a single workflow task. + google.protobuf.Duration workflow_task_timeout = 8; + + // Default: PARENT_CLOSE_POLICY_TERMINATE. + temporal.api.enums.v1.ParentClosePolicy parent_close_policy = 9; + + string control = 10; + + // Default: WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE. + temporal.api.enums.v1.WorkflowIdReusePolicy workflow_id_reuse_policy = 11; + + temporal.api.common.v1.RetryPolicy retry_policy = 12; + + // Establish a cron schedule for the child workflow. + string cron_schedule = 13; + + temporal.api.common.v1.Header header = 14; + + temporal.api.common.v1.Memo memo = 15; + + temporal.api.common.v1.SearchAttributes search_attributes = 16; + + // If this is set, the child workflow inherits the Build ID of the parent. Otherwise, the assignment + // rules of the child's Task Queue will be used to independently assign a Build ID to it. + // Deprecated. Only considered for versioning v0.2. + bool inherit_build_id = 17 [deprecated = true]; + + // Priority metadata. If this message is not present, or any fields are not + // present, they inherit the values from the workflow. + temporal.api.common.v1.Priority priority = 18; + + // Versioning override for the child workflow. If present, this explicit override takes + // precedence over versioning behavior inherited from the parent workflow. + temporal.api.workflow.v1.VersioningOverride versioning_override = 19; +} + +message ProtocolMessageCommandAttributes { + // The message ID of the message to which this command is a pointer. + string message_id = 1; +} + +message ScheduleNexusOperationCommandAttributes { + // Endpoint name, must exist in the endpoint registry or this command will fail. + string endpoint = 1; + + // Service name. + string service = 2; + + // Operation name. + string operation = 3; + + // Input for the operation. The server converts this into Nexus request content and the appropriate content headers + // internally when sending the StartOperation request. On the handler side, if it is also backed by Temporal, the + // content is transformed back to the original Payload sent in this command. + temporal.api.common.v1.Payload input = 4; + + // Schedule-to-close timeout for this operation. + // Indicates how long the caller is willing to wait for operation completion. + // Calls are retried internally by the server. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 5; + + // Header to attach to the Nexus request. + // Users are responsible for encrypting sensitive data in this header as it is stored in workflow history and + // transmitted to external services as-is. + // This is useful for propagating tracing information. + // Note these headers are not the same as Temporal headers on internal activities and child workflows, these are + // transmitted to Nexus operations that may be external and are not traditional payloads. + map nexus_header = 6; + + // Schedule-to-start timeout for this operation. + // Indicates how long the caller is willing to wait for the operation to be started (or completed if synchronous) + // by the handler. If the operation is not started within this timeout, it will fail with + // TIMEOUT_TYPE_SCHEDULE_TO_START. + // If not set or zero, no schedule-to-start timeout is enforced. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + // Requires server version 1.31.0 or later. + google.protobuf.Duration schedule_to_start_timeout = 7; + + // Start-to-close timeout for this operation. + // Indicates how long the caller is willing to wait for an asynchronous operation to complete after it has been + // started. If the operation does not complete within this timeout after starting, it will fail with + // TIMEOUT_TYPE_START_TO_CLOSE. + // Only applies to asynchronous operations. Synchronous operations ignore this timeout. + // If not set or zero, no start-to-close timeout is enforced. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + // Requires server version 1.31.0 or later. + google.protobuf.Duration start_to_close_timeout = 8; +} + +message RequestCancelNexusOperationCommandAttributes { + // The `NEXUS_OPERATION_SCHEDULED` event ID (a unique identifier) for the operation to be canceled. + // The operation may ignore cancellation and end up with any completion state. + int64 scheduled_event_id = 1; +} + +message Command { + temporal.api.enums.v1.CommandType command_type = 1; + + // Metadata on the command. This is sometimes carried over to the history event if one is + // created as a result of the command. Most commands won't have this information, and how this + // information is used is dependent upon the interface that reads it. + // + // Current well-known uses: + // * start_child_workflow_execution_command_attributes - populates + // temporal.api.workflow.v1.WorkflowExecutionInfo.user_metadata where the summary and details + // are used by user interfaces to show fixed as-of-start workflow summary and details. + // * start_timer_command_attributes - populates temporal.api.history.v1.HistoryEvent for timer + // started where the summary is used to identify the timer. + temporal.api.sdk.v1.UserMetadata user_metadata = 301; + + // Event Group Markers attached to the command by the workflow author. + repeated temporal.api.sdk.v1.EventGroupMarker event_group_markers = 302; + + // The command details. The type must match that in `command_type`. + oneof attributes { + ScheduleActivityTaskCommandAttributes schedule_activity_task_command_attributes = 2; + + StartTimerCommandAttributes start_timer_command_attributes = 3; + + CompleteWorkflowExecutionCommandAttributes complete_workflow_execution_command_attributes = 4; + + FailWorkflowExecutionCommandAttributes fail_workflow_execution_command_attributes = 5; + + RequestCancelActivityTaskCommandAttributes request_cancel_activity_task_command_attributes = 6; + + CancelTimerCommandAttributes cancel_timer_command_attributes = 7; + + CancelWorkflowExecutionCommandAttributes cancel_workflow_execution_command_attributes = 8; + + RequestCancelExternalWorkflowExecutionCommandAttributes request_cancel_external_workflow_execution_command_attributes = 9; + + RecordMarkerCommandAttributes record_marker_command_attributes = 10; + + ContinueAsNewWorkflowExecutionCommandAttributes continue_as_new_workflow_execution_command_attributes = 11; + + StartChildWorkflowExecutionCommandAttributes start_child_workflow_execution_command_attributes = 12; + + SignalExternalWorkflowExecutionCommandAttributes signal_external_workflow_execution_command_attributes = 13; + + UpsertWorkflowSearchAttributesCommandAttributes upsert_workflow_search_attributes_command_attributes = 14; + + ProtocolMessageCommandAttributes protocol_message_command_attributes = 15; + + // 16 is available for use - it was used as part of a prototype that never made it into a release + ModifyWorkflowPropertiesCommandAttributes modify_workflow_properties_command_attributes = 17; + + ScheduleNexusOperationCommandAttributes schedule_nexus_operation_command_attributes = 18; + + RequestCancelNexusOperationCommandAttributes request_cancel_nexus_operation_command_attributes = 19; + } +} diff --git a/temporal/api/common/v1/message.proto b/temporal/api/common/v1/message.proto new file mode 100644 index 000000000..fc2f89350 --- /dev/null +++ b/temporal/api/common/v1/message.proto @@ -0,0 +1,544 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.common.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/enums/v1/common.proto"; +import "temporal/api/enums/v1/event_type.proto"; +import "temporal/api/enums/v1/reset.proto"; + +option csharp_namespace = "Temporalio.Api.Common.V1"; +option go_package = "go.temporal.io/api/common/v1;common"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.common.v1"; +option ruby_package = "Temporalio::Api::Common::V1"; + +message DataBlob { + temporal.api.enums.v1.EncodingType encoding_type = 1; + + bytes data = 2; +} + +// See `Payload` +message Payloads { + repeated Payload payloads = 1; +} + +// Represents some binary (byte array) data (ex: activity input parameters or workflow result) with +// metadata which describes this binary data (format, encoding, encryption, etc). Serialization +// of the data may be user-defined. +message Payload { + map metadata = 1; + + bytes data = 2; + + // Details about externally stored payloads associated with this payload. + repeated ExternalPayloadDetails external_payloads = 3; + + // Describes an externally stored object referenced by this payload. + message ExternalPayloadDetails { + // Size in bytes of the externally stored payload + int64 size_bytes = 1; + } +} + +// A user-defined set of *indexed* fields that are used/exposed when listing/searching workflows. +// The payload is not serialized in a user-defined way. +message SearchAttributes { + map indexed_fields = 1; +} + +// A user-defined set of *unindexed* fields that are exposed when listing/searching workflows +message Memo { + map fields = 1; +} + +// Contains metadata that can be attached to a variety of requests, like starting a workflow, and +// can be propagated between, for example, workflows and activities. +message Header { + map fields = 1; +} + +// Identifies a specific workflow within a namespace. Practically speaking, because run_id is a +// uuid, a workflow execution is globally unique. Note that many commands allow specifying an empty +// run id as a way of saying "target the latest run of the workflow". +message WorkflowExecution { + string workflow_id = 1; + + string run_id = 2; +} + +// Identifies a specific execution within a namespace. This is used for standalone activities +// executions in batch jobs currently. +message Execution { + temporal.api.enums.v1.ExecutionType type = 1; + + string business_id = 2; + + string run_id = 3; +} + +// 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" +message WorkflowType { + string name = 1; +} + +// Represents the identifier used by a activity author to define the activity. Typically, the +// name of a function. This is sometimes referred to as the activity's "name" +message ActivityType { + string name = 1; +} + +// How retries ought to be handled, usable by both workflows and activities +message RetryPolicy { + // Interval of the first retry. If retryBackoffCoefficient is 1.0 then it is used for all retries. + google.protobuf.Duration initial_interval = 1; + + // Coefficient used to calculate the next retry interval. + // The next retry interval is previous interval multiplied by the coefficient. + // Must be 1 or larger. + double backoff_coefficient = 2; + + // Maximum interval between retries. Exponential backoff leads to interval increase. + // This value is the cap of the increase. Default is 100x of the initial interval. + google.protobuf.Duration maximum_interval = 3; + + // Maximum number of attempts. When exceeded the retries stop even if not expired yet. + // 1 disables retries. 0 means unlimited (up to the timeouts) + int32 maximum_attempts = 4; + + // Non-Retryable errors types. Will stop retrying if the error type matches this list. Note that + // this is not a substring match, the error *type* (not message) must match exactly. + repeated string non_retryable_error_types = 5; +} + +// Metadata relevant for metering purposes +message MeteringMetadata { + // Count of local activities which have begun an execution attempt during this workflow task, + // and whose first attempt occurred in some previous task. This is used for metering + // purposes, and does not affect workflow state. + // + // (-- api-linter: core::0141::forbidden-types=disabled + // aip.dev/not-precedent: Negative values make no sense to represent. --) + uint32 nonfirst_local_activity_execution_attempts = 13; +} + +// Deprecated. This message is replaced with `Deployment` and `VersioningBehavior`. +// Identifies the version(s) of a worker that processed a task +message WorkerVersionStamp { + // An opaque whole-worker identifier. Replaces the deprecated `binary_checksum` field when this + // message is included in requests which previously used that. + string build_id = 1; + + // If set, the worker is opting in to worker versioning. Otherwise, this is used only as a + // marker for workflow reset points and the BuildIDs search attribute. + bool use_versioning = 3; +} + +// Identifies the version that a worker is compatible with when polling or identifying itself, +// and whether or not this worker is opting into the build-id based versioning feature. This is +// used by matching to determine which workers ought to receive what tasks. +// Deprecated. Use WorkerDeploymentOptions instead. +message WorkerVersionCapabilities { + // An opaque whole-worker identifier + string build_id = 1; + + // If set, the worker is opting in to worker versioning, and wishes to only receive appropriate + // tasks. + bool use_versioning = 2; + + // Must be sent if user has set a deployment series name (versioning-3). + string deployment_series_name = 4; +} + +// Describes where and how to reset a workflow, used for batch reset currently +// and may be used for single-workflow reset later. +message ResetOptions { + // Which workflow task to reset to. + oneof target { + // Resets to the first workflow task completed or started event. + google.protobuf.Empty first_workflow_task = 1; + + // Resets to the last workflow task completed or started event. + google.protobuf.Empty last_workflow_task = 2; + + // The id of a specific `WORKFLOW_TASK_COMPLETED`,`WORKFLOW_TASK_TIMED_OUT`, `WORKFLOW_TASK_FAILED`, or + // `WORKFLOW_TASK_STARTED` event to reset to. + // Note that this option doesn't make sense when used as part of a batch request. + int64 workflow_task_id = 3; + + // Resets to the first workflow task processed by this build id. + // If the workflow was not processed by the build id, or the workflow task can't be + // determined, no reset will be performed. + // Note that by default, this reset is allowed to be to a prior run in a chain of + // continue-as-new. + string build_id = 4; + } + + // Deprecated. Use `options`. + // Default: RESET_REAPPLY_TYPE_SIGNAL + temporal.api.enums.v1.ResetReapplyType reset_reapply_type = 10 [deprecated = true]; + + // If true, limit the reset to only within the current run. (Applies to build_id targets and + // possibly others in the future.) + bool current_run_only = 11; + + // Event types not to be reapplied + repeated temporal.api.enums.v1.ResetReapplyExcludeType reset_reapply_exclude_types = 12; +} + +// Callback to attach to various events in the system, e.g. workflow run completion. +message Callback { + message Nexus { + // Callback URL. + string url = 1; + + // Header to attach to callback request. + map header = 2; + } + + // Callbacks to be delivered internally within the system. + // This variant is not settable in the API and will be rejected by the service with an INVALID_ARGUMENT error. + // The only reason that this is exposed is because callbacks are replicated across clusters via the + // WorkflowExecutionStarted event, which is defined in the public API. + message Internal { + // Opaque internal data. + bytes data = 1; + } + + reserved 1; + + oneof variant { + Nexus nexus = 2; + + Internal internal = 3; + } + + // Links associated with the callback. It can be used to link to underlying resources of the + // callback. + repeated Link links = 100; +} + +// Link can be associated with history events. It might contain information about an external entity +// related to the history event. For example, workflow A makes a Nexus call that starts workflow B: +// in this case, a history event in workflow A could contain a Link to the workflow started event in +// workflow B, and vice-versa. +message Link { + message WorkflowEvent { + // EventReference is a direct reference to a history event through the event ID. + message EventReference { + int64 event_id = 1; + + temporal.api.enums.v1.EventType event_type = 2; + } + + // RequestIdReference is a indirect reference to a history event through the request ID. + message RequestIdReference { + string request_id = 1; + + temporal.api.enums.v1.EventType event_type = 2; + } + + string namespace = 1; + + string workflow_id = 2; + + string run_id = 3; + + // Additional information about the workflow event. + // Eg: the caller workflow can send the history event details that made the Nexus call. + oneof reference { + EventReference event_ref = 100; + + RequestIdReference request_id_ref = 101; + } + } + + // A link to a built-in batch job. + // Batch jobs can be used to perform operations on a set of workflows (e.g. terminate, signal, cancel, etc). + // This link can be put on workflow history events generated by actions taken by a batch job. + message BatchJob { + string job_id = 1; + } + + // A link to an activity. + message Activity { + string namespace = 1; + + string activity_id = 2; + + string run_id = 3; + } + + // A link to a standalone Nexus operation. + message NexusOperation { + string namespace = 1; + + string operation_id = 2; + + string run_id = 3; + } + + // A link to a workflow execution. This is a more general version of WorkflowEvent that doesn't specify a + // particular event within the workflow, useful when you want to link to a workflow but there is no particular event to link to, + // such as a Query or a Rejected Update. + message Workflow { + string namespace = 1; + + string workflow_id = 2; + + string run_id = 3; + + string reason = 4; + } + + oneof variant { + WorkflowEvent workflow_event = 1; + + BatchJob batch_job = 2; + + Activity activity = 3; + + NexusOperation nexus_operation = 4; + + Workflow workflow = 5; + } +} + +// Principal is an authenticated caller identity computed by the server from trusted +// authentication context. +message Principal { + // Low-cardinality category of the principal (e.g., "jwt", "users"). + string type = 1; + + // Identifier within that category (e.g., sub JWT claim, email address). + string name = 2; +} + +// Priority contains metadata that controls relative ordering of task processing +// when tasks are backed up in a queue. Initially, Priority will be used in +// matching (workflow and activity) task queues. Later it may be used in history +// task queues and in rate limiting decisions. +// +// Priority is attached to workflows and activities. By default, activities +// inherit Priority from the workflow that created them, but may override fields +// when an activity is started or modified. +// +// Despite being named "Priority", this message also contains fields that +// control "fairness" mechanisms. +// +// For all fields, the field not present or equal to zero/empty string means to +// inherit the value from the calling workflow, or if there is no calling +// workflow, then use the default value. +// +// For all fields other than fairness_key, the zero value isn't meaningful so +// there's no confusion between inherit/default and a meaningful value. For +// fairness_key, the empty string will be interpreted as "inherit". This means +// that if a workflow has a non-empty fairness key, you can't override the +// fairness key of its activity to the empty string. +// +// The overall semantics of Priority are: +// 1. First, consider "priority": higher priority (lower number) goes first. +// 2. Then, consider fairness: try to dispatch tasks for different fairness keys +// in proportion to their weight. +// +// Applications may use any subset of mechanisms that are useful to them and +// leave the other fields to use default values. +// +// Not all queues in the system may support the "full" semantics of all priority +// fields. (Currently only support in matching task queues is planned.) +message Priority { + // Priority key is a positive integer from 1 to n, where smaller integers + // correspond to higher priorities (tasks run sooner). In general, tasks in + // a queue should be processed in close to priority order, although small + // deviations are possible. + // + // The maximum priority value (minimum priority) is determined by server + // configuration, and defaults to 5. + // + // If priority is not present (or zero), then the effective priority will be + // the default priority, which is calculated by (min+max)/2. With the + // default max of 5, and min of 1, that comes out to 3. + int32 priority_key = 1; + + // Fairness key is a short string that's used as a key for a fairness + // balancing mechanism. It may correspond to a tenant id, or to a fixed + // string like "high" or "low". The default is the empty string. + // + // The fairness mechanism attempts to dispatch tasks for a given key in + // proportion to its weight. For example, using a thousand distinct tenant + // ids, each with a weight of 1.0 (the default) will result in each tenant + // getting a roughly equal share of task dispatch throughput. + // + // (Note: this does not imply equal share of worker capacity! Fairness + // decisions are made based on queue statistics, not + // current worker load.) + // + // As another example, using keys "high" and "low" with weight 9.0 and 1.0 + // respectively will prefer dispatching "high" tasks over "low" tasks at a + // 9:1 ratio, while allowing either key to use all worker capacity if the + // other is not present. + // + // All fairness mechanisms, including rate limits, are best-effort and + // probabilistic. The results may not match what a "perfect" algorithm with + // infinite resources would produce. The more unique keys are used, the less + // accurate the results will be. + // + // Fairness keys are limited to 64 bytes. + string fairness_key = 2; + + // Fairness weight for a task can come from multiple sources for + // flexibility. From highest to lowest precedence: + // 1. Weights for a small set of keys can be overridden in task queue + // configuration with an API. + // 2. It can be attached to the workflow/activity in this field. + // 3. The default weight of 1.0 will be used. + // + // Weight values are clamped to the range [0.001, 1000]. + float fairness_weight = 3; +} + +// This is used to send commands to a specific worker or a group of workers. +// Right now, it is used to send commands to a specific worker instance. +// Will be extended to be able to send command to multiple workers. +message WorkerSelector { + // Options are: + // - query (will be used as query to ListWorkers, same format as in ListWorkersRequest.query) + // - task queue (just a shortcut. Same as query=' "TaskQueue"="my-task-queue" ') + // - etc. + // All but 'query' are shortcuts, can be replaced with a query, but it is not convenient. + // string query = 5; + // string task_queue = 6; + // ... + oneof selector { + // Worker instance key to which the command should be sent. + string worker_instance_key = 1; + } +} + +// When starting an execution with a conflict policy that uses an existing execution and there is already an existing +// running execution, OnConflictOptions defines actions to be taken on the existing running execution. +message OnConflictOptions { + // Attaches the request ID to the running execution. + bool attach_request_id = 1; + + // Attaches the completion callbacks to the running execution. + bool attach_completion_callbacks = 2; + + // Attaches the links to the running execution. + bool attach_links = 3; +} + +// The configuration for time skipping of an execution. +// When time skipping is enabled, virtual time advances automatically whenever there is no in-flight work. +// Options like fast_forward, disable_propagation, and max_session_skip_count are provided for granular +// control of the execution's time skipping behavior. See each field's comment for a detailed explanation. +// +// An example of workflows with time skipping: +// For workflows, an execution is a chain of runs including retries, cron, and continue-as-new. +// In-flight work includes activities, child workflows, Nexus operations, signal/cancel external workflow operations, etc. +// User timers are not classified as in-flight work and will be skipped over; the virtual clock may also skip to the +// time point of the registered fast-forward when there is no in-flight work. +// Whenever time is skipped, the skip count is incremented by one; max_session_skip_count bounds the number of skips allowed within a single time-skipping session. +// For child workflows, by default, if the parent execution is skipping time, the child execution will also skip time, +// but a parent's fast_forward won't affect its child's execution. A flag is provided to disable propagation of the +// "enabled" flag to child workflows; regardless of that flag, a child workflow inherits the virtual time from the +// parent execution as its start time. +message TimeSkippingConfig { + // Enables or disables time skipping for this workflow execution. + bool enabled = 1; + + // An optional opt-in to control time-skipping behavior through fast-forward; see its definition for details. + FastForwardConfig fast_forward_config = 2; + + // By default, executions started by another execution (e.g. a child workflow of a parent workflow or + // a schedule with the time-skipping policy enabled) inherit the "enabled" flag and skip time when possible. + // This flag disables that inheritance. + bool disable_propagation = 3; + + // The maximum number of skips allowed every time this field is updated. It protects the execution from + // situations like unlimited retries when backoff is skipped. + // + // Every time the execution skips time, the skip count is incremented by one, and when it reaches + // max_session_skip_count, time skipping stops. Whenever this config field is updated, the accumulated + // skip count is cleared, marking the start of a new session. + // For an execution with a chain of runs (retry, cron, continue-as-new), the count is accumulated + // across all runs within the same session. + // + // If this field is not set, the server applies a large default value (e.g. 100). The default can + // be changed through dynamic config, and is overridden by this field when set. + int32 max_session_skip_count = 4; +} + +message FastForwardConfig { + // A client-supplied ID, required field, set alongside `duration`. It is used to poll for + // fast-forward completion via PollWorkflowExecutionTimeSkipping. + // The server performs no idempotency check on this ID; the client is responsible for managing it. + string id = 1; + + // Fast-forward the current execution by this duration ahead of the current execution time; required field. + // The duration yields a target time (current execution time + duration), surfaced as `target_time` in + // TimeSkippingFastForwardInfo. Once virtual time reaches that target, the fast-forward completes, time + // skipping is disabled, and no further time is skipped. Time skipping can be resumed either + // by updating the TimeSkippingConfig with a new FastForwardConfig, or by clearing the FastForwardConfig + // to skip through to the end of the execution. + // + // If this duration exceeds the remaining execution timeout, time will not pass beyond the end + // of the execution, and the fast-forward won't have a chance to complete. + google.protobuf.Duration duration = 2; +} + +// The time-skipping state that needs to be propagated from one execution to another, or through a chain of runs +// within the same execution. +message TimeSkippingStatePropagation { + // The time skipped by the previous run. It is propagated both to executions started by the + // current execution and through a chain of runs (CaN, cron, retry). + google.protobuf.Duration initial_skipped_duration = 1; + + // The fast-forward target time. It only propagates across a chain of runs within the same execution. + google.protobuf.Timestamp fast_forward_target_time = 2; + + // The initial skip count. It only propagates across a chain of runs within the same execution. + int32 initial_skip_count = 3; +} + +// Describes the current time-skipping state of a workflow execution. +message TimeSkippingInfo { + // Current virtual time of the execution. If the execution hasn't skipped + // any time yet, it will be the same as wall clock time. + google.protobuf.Timestamp current_time = 1; + + // The current effective time-skipping config, which can differ from the config the user last set: + // internally-defaulted fields are populated, and `enabled` reflects whether the execution is still + // skipping time — e.g. it is set to false once `max_session_skip_count` is reached, the fast-forward + // completes, or a client call disables time skipping. + TimeSkippingConfig effective_config = 2; + + // The execution's current fast-forward, if any. Unset if time skipping is enabled without a fast-forward. + TimeSkippingFastForwardInfo fast_forward_info = 4; + + // The number of skips accumulated in the current session, bounded by `max_session_skip_count`. + // A new session begins — and this resets to 0 — each time `max_session_skip_count` is updated. + int32 current_session_skip_count = 6; +} + +// TimeSkippingFastForwardInfo describes the current time-skipping fast-forward on an execution. +message TimeSkippingFastForwardInfo { + // The client-supplied `fast_forward` duration. + google.protobuf.Duration fast_forward_duration = 1; + + // The client-supplied ID set alongside `fast_forward` duration. + string fast_forward_id = 2; + + // The target virtual time at which the fast-forward completes. + google.protobuf.Timestamp target_time = 3; + + // True once `target_time` has been reached. + bool has_completed = 4; +} diff --git a/temporal/api/compute/v1/config.proto b/temporal/api/compute/v1/config.proto new file mode 100644 index 000000000..6d605098d --- /dev/null +++ b/temporal/api/compute/v1/config.proto @@ -0,0 +1,70 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.compute.v1; + +import "google/protobuf/field_mask.proto"; +import "temporal/api/compute/v1/provider.proto"; +import "temporal/api/compute/v1/scaler.proto"; +import "temporal/api/enums/v1/task_queue.proto"; + +option csharp_namespace = "Temporalio.Api.Compute.V1"; +option go_package = "go.temporal.io/api/compute/v1;compute"; +option java_multiple_files = true; +option java_outer_classname = "ConfigProto"; +option java_package = "io.temporal.api.compute.v1"; +option ruby_package = "Temporalio::Api::Compute::V1"; + +message ComputeConfigScalingGroup { + // Optional. The set of task queue types this scaling group serves. + // If not provided, this scaling group serves all not otherwise defined + // task types. + repeated temporal.api.enums.v1.TaskQueueType task_queue_types = 1; + + // Stores instructions for a worker control plane controller how to respond + // to worker lifeycle events. + ComputeProvider provider = 3; + + // Informs a worker lifecycle controller *when* and *how often* to perform + // certain worker lifecycle actions like starting a serverless worker. + ComputeScaler scaler = 4; +} + +// ComputeConfig stores configuration that helps a worker control plane +// controller understand *when* and *how* to respond to worker lifecycle +// events. +message ComputeConfig { + // Each scaling group describes a compute config for a specific subset of the worker + // deployment version: covering a specific set of task types and/or regions. + // Having different configurations for different task types, allows independent + // tuning of activity and workflow task processing (for example). + // + // The key of the map is the ID of the scaling group used to reference it in subsequent + // update calls. + map scaling_groups = 1; +} + +message ComputeConfigScalingGroupUpdate { + ComputeConfigScalingGroup scaling_group = 1; + + // Controls which fields from `scaling_group` will be applied. Semantics: + // - Mask is ignored for new scaling groups (only applicable when scaling group already exists). + // - Empty mask for an existing scaling group is no-op: no change. + // - Non-empty mask for an existing scaling group will update/unset only to the fields + // mentioned in the mask. + // - Accepted paths: "task_queue_types", "provider", "provider.type", "provider.details", + // "provider.nexus_endpoint", "scaler", "scaler.type", "scaler.details" + google.protobuf.FieldMask update_mask = 2; +} + +// A subset of information in ComputeConfig optimized for list views. +message ComputeConfigSummary { + map scaling_groups = 1; +} + +message ComputeConfigScalingGroupSummary { + repeated temporal.api.enums.v1.TaskQueueType task_queue_types = 1; + + string provider_type = 2; +} diff --git a/temporal/api/compute/v1/provider.proto b/temporal/api/compute/v1/provider.proto new file mode 100644 index 000000000..6105ef8e3 --- /dev/null +++ b/temporal/api/compute/v1/provider.proto @@ -0,0 +1,37 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.compute.v1; + +import "temporal/api/common/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Compute.V1"; +option go_package = "go.temporal.io/api/compute/v1;compute"; +option java_multiple_files = true; +option java_outer_classname = "ProviderProto"; +option java_package = "io.temporal.api.compute.v1"; +option ruby_package = "Temporalio::Api::Compute::V1"; + +// ComputeProvider stores information used by a worker control plane controller +// to respond to worker lifecycle events. For example, when a Task is received +// on a TaskQueue that has no active pollers, a serverless worker lifecycle +// controller might need to invoke an AWS Lambda Function that itself ends up +// calling the SDK's worker.New() function. +message ComputeProvider { + // Type of the compute provider. This string is implementation-specific and + // can be used by implementations to understand how to interpret the + // contents of the provider_details field. + string type = 1; + + // Contains provider-specific instructions and configuration. + // For server-implemented providers, use the SDK's default content + // converter to ensure the server can understand it. + // For remote-implemented providers, you might use your own content + // converters according to what the remote endpoints understand. + temporal.api.common.v1.Payload details = 2; + + // Optional. If the compute provider is a Nexus service, this should point + // there. + string nexus_endpoint = 10; +} diff --git a/temporal/api/compute/v1/scaler.proto b/temporal/api/compute/v1/scaler.proto new file mode 100644 index 000000000..f1af096c5 --- /dev/null +++ b/temporal/api/compute/v1/scaler.proto @@ -0,0 +1,30 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.compute.v1; + +import "temporal/api/common/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Compute.V1"; +option go_package = "go.temporal.io/api/compute/v1;compute"; +option java_multiple_files = true; +option java_outer_classname = "ScalerProto"; +option java_package = "io.temporal.api.compute.v1"; +option ruby_package = "Temporalio::Api::Compute::V1"; + +// ComputeScaler instructs the Temporal Service when to scale up or down the number of +// Workers that comprise a WorkerDeployment. +message ComputeScaler { + // Type of the compute scaler. this string is implementation-specific and + // can be used by implementations to understand how to interpret the + // contents of the scaler_details field. + string type = 1; + + // Contains scaler-specific instructions and configuration. + // For server-implemented scalers, use the SDK's default data + // converter to ensure the server can understand it. + // For remote-implemented scalers, you might use your own data + // converters according to what the remote endpoints understand. + temporal.api.common.v1.Payload details = 2; +} diff --git a/temporal/api/deployment/v1/message.proto b/temporal/api/deployment/v1/message.proto new file mode 100644 index 000000000..111e642af --- /dev/null +++ b/temporal/api/deployment/v1/message.proto @@ -0,0 +1,393 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.deployment.v1; + +import "google/protobuf/timestamp.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/compute/v1/config.proto"; +import "temporal/api/enums/v1/deployment.proto"; +import "temporal/api/enums/v1/task_queue.proto"; +import "temporal/api/enums/v1/workflow.proto"; + +option csharp_namespace = "Temporalio.Api.Deployment.V1"; +option go_package = "go.temporal.io/api/deployment/v1;deployment"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.deployment.v1"; +option ruby_package = "Temporalio::Api::Deployment::V1"; + +// Worker Deployment options set in SDK that need to be sent to server in every poll. +message WorkerDeploymentOptions { + // Required when `worker_versioning_mode==VERSIONED`. + string deployment_name = 1; + + // The Build ID of the worker. Required when `worker_versioning_mode==VERSIONED`, in which case, + // the worker will be part of a Deployment Version. + string build_id = 2; + + // Required. Versioning Mode for this worker. Must be the same for all workers with the + // same `deployment_name` and `build_id` combination, across all Task Queues. + // When `worker_versioning_mode==VERSIONED`, the worker will be part of a Deployment Version. + temporal.api.enums.v1.WorkerVersioningMode worker_versioning_mode = 3; +} + +// `Deployment` identifies a deployment of Temporal workers. The combination of deployment series +// name + build ID serves as the identifier. User can use `WorkerDeploymentOptions` in their worker +// programs to specify these values. +// Deprecated. +message Deployment { + // Different versions of the same worker service/application are related together by having a + // shared series name. + // Out of all deployments of a series, one can be designated as the current deployment, which + // receives new workflow executions and new tasks of workflows with + // `VERSIONING_BEHAVIOR_AUTO_UPGRADE` versioning behavior. + string series_name = 1; + + // Build ID changes with each version of the worker when the worker program code and/or config + // changes. + string build_id = 2; +} + +// `DeploymentInfo` holds information about a deployment. Deployment information is tracked +// automatically by server as soon as the first poll from that deployment reaches the server. There +// can be multiple task queue workers in a single deployment which are listed in this message. +// Deprecated. +message DeploymentInfo { + Deployment deployment = 1; + + google.protobuf.Timestamp create_time = 2; + + repeated TaskQueueInfo task_queue_infos = 3; + + // A user-defined set of key-values. Can be updated as part of write operations to the + // deployment, such as `SetCurrentDeployment`. + map metadata = 4; + + // If this deployment is the current deployment of its deployment series. + bool is_current = 5; + + message TaskQueueInfo { + string name = 1; + + temporal.api.enums.v1.TaskQueueType type = 2; + + // When server saw the first poller for this task queue in this deployment. + google.protobuf.Timestamp first_poller_time = 3; + } +} + +// Used as part of Deployment write APIs to update metadata attached to a deployment. +// Deprecated. +message UpdateDeploymentMetadata { + map upsert_entries = 1; + + // List of keys to remove from the metadata. + repeated string remove_entries = 2; +} + +// DeploymentListInfo is an abbreviated set of fields from DeploymentInfo that's returned in +// ListDeployments. +// Deprecated. +message DeploymentListInfo { + Deployment deployment = 1; + + google.protobuf.Timestamp create_time = 2; + + // If this deployment is the current deployment of its deployment series. + bool is_current = 3; +} + +// A Worker Deployment Version (Version, for short) represents all workers of the same +// code and config within a Deployment. Workers of the same Version are expected to +// behave exactly the same so when executions move between them there are no +// non-determinism issues. +// Worker Deployment Versions are created in Temporal server automatically when +// their first poller arrives to the server. +message WorkerDeploymentVersionInfo { + // Deprecated. Use `deployment_version`. + string version = 1 [deprecated = true]; + + // The status of the Worker Deployment Version. + temporal.api.enums.v1.WorkerDeploymentVersionStatus status = 14; + + // Required. + WorkerDeploymentVersion deployment_version = 11; + + // Deprecated. User deployment_version.deployment_name. + string deployment_name = 2; + + google.protobuf.Timestamp create_time = 3; + + // Last time `current_since_time`, `ramping_since_time, or `ramp_percentage` of this version changed. + google.protobuf.Timestamp routing_changed_time = 4; + + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: 'Since' captures the field semantics despite being a preposition. --) + // Unset if not current. + google.protobuf.Timestamp current_since_time = 5; + + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: 'Since' captures the field semantics despite being a preposition. --) + // Unset if not ramping. Updated when the version first starts ramping, not on each ramp change. + google.protobuf.Timestamp ramping_since_time = 6; + + // Timestamp when this version first became current or ramping. + google.protobuf.Timestamp first_activation_time = 12; + + // Timestamp when this version last became current. + // Can be used to determine whether a version has ever been Current. + google.protobuf.Timestamp last_current_time = 15; + + // Timestamp when this version last stopped being current or ramping. + // Cleared if the version becomes current or ramping again. + google.protobuf.Timestamp last_deactivation_time = 13; + + // Range: [0, 100]. Must be zero if the version is not ramping (i.e. `ramping_since_time` is nil). + // Can be in the range [0, 100] if the version is ramping. + float ramp_percentage = 7; + + // All the Task Queues that have ever polled from this Deployment version. + // Deprecated. Use `version_task_queues` in DescribeWorkerDeploymentVersionResponse instead. + repeated VersionTaskQueueInfo task_queue_infos = 8; + + message VersionTaskQueueInfo { + string name = 1; + + temporal.api.enums.v1.TaskQueueType type = 2; + } + + // Helps user determine when it is safe to decommission the workers of this + // Version. Not present when version is current or ramping. + // Current limitations: + // - Not supported for Unversioned mode. + // - Periodically refreshed, may have delays up to few minutes (consult the + // last_checked_time value). + // - Refreshed only when version is not current or ramping AND the status is not + // "drained" yet. + // - Once the status is changed to "drained", it is not changed until the Version + // becomes Current or Ramping again, at which time the drainage info is cleared. + // This means if the Version is "drained" but new workflows are sent to it via + // Pinned Versioning Override, the status does not account for those Pinned-override + // executions and remains "drained". + VersionDrainageInfo drainage_info = 9; + + // Arbitrary user-provided metadata attached to this version. + VersionMetadata metadata = 10; + + // Optional. Contains the new worker compute configuration for the Worker + // Deployment. Used for worker scale management. + temporal.api.compute.v1.ComputeConfig compute_config = 16; + + // Identity of the last client who modified the configuration of this Version. + // As of now, this field only covers changes through the following APIs: + // - `CreateWorkerDeploymentVersion` + // - `UpdateWorkerDeploymentVersionComputeConfig` + // - `UpdateWorkerDeploymentVersionMetadata` + string last_modifier_identity = 17; +} + +// Information about workflow drainage to help the user determine when it is safe +// to decommission a Version. Not present while version is current or ramping. +message VersionDrainageInfo { + // Set to DRAINING when the version first stops accepting new executions (is no longer current or ramping). + // Set to DRAINED when no more open pinned workflows exist on this version. + temporal.api.enums.v1.VersionDrainageStatus status = 1; + + // Last time the drainage status changed. + google.protobuf.Timestamp last_changed_time = 2; + + // Last time the system checked for drainage of this version. + google.protobuf.Timestamp last_checked_time = 3; +} + +// ComputeStatus represents compute-related configuration and health for a Worker Deployment Version. +message ComputeStatus { + // ProviderValidationStatus represents the result of the most recent + // connectivity check between Temporal and a customer's compute provider. + message ProviderValidationStatus { + // Human-readable error message if connectivity validation failed. + // An empty string means validation passed. + string error_message = 1; + + // Timestamp of the last validation check. + google.protobuf.Timestamp last_check_time = 2; + } + + // provider_validation encapsulates the health signal for validating the compute provider. + ProviderValidationStatus provider_validation = 1; +} + +// A Worker Deployment (Deployment, for short) represents all workers serving +// a shared set of Task Queues. Typically, a Deployment represents one service or +// application. +// A Deployment contains multiple Deployment Versions, each representing a different +// version of workers. (see documentation of WorkerDeploymentVersionInfo) +// Deployment records are created in Temporal server automatically when their +// first poller arrives to the server. +message WorkerDeploymentInfo { + // Identifies a Worker Deployment. Must be unique within the namespace. + string name = 1; + + // Deployment Versions that are currently tracked in this Deployment. A DeploymentVersion will be + // cleaned up automatically if all the following conditions meet: + // - It does not receive new executions (is not current or ramping) + // - It has no active pollers (see WorkerDeploymentVersionInfo.pollers_status) + // - It is drained (see WorkerDeploymentVersionInfo.drainage_status) + repeated WorkerDeploymentVersionSummary version_summaries = 2; + + google.protobuf.Timestamp create_time = 3; + + RoutingConfig routing_config = 4; + + // Identity of the last client who modified the configuration of this Deployment. Set to the + // `identity` value sent by APIs such as `SetWorkerDeploymentCurrentVersion` and + // `SetWorkerDeploymentRampingVersion`. + string last_modifier_identity = 5; + + // Identity of the client that has the exclusive right to make changes to this Worker Deployment. + // Empty by default. + // If this is set, clients whose identity does not match `manager_identity` will not be able to make changes + // to this Worker Deployment. They can either set their own identity as the manager or unset the field to proceed. + string manager_identity = 6; + + // Indicates whether the routing_config has been fully propagated to all + // relevant task queues and their partitions. + temporal.api.enums.v1.RoutingConfigUpdateState routing_config_update_state = 7; + + message WorkerDeploymentVersionSummary { + // Deprecated. Use `deployment_version`. + string version = 1 [deprecated = true]; + + // The status of the Worker Deployment Version. + temporal.api.enums.v1.WorkerDeploymentVersionStatus status = 11; + + // Required. + WorkerDeploymentVersion deployment_version = 4; + + google.protobuf.Timestamp create_time = 2; + + // Deprecated. Use `drainage_info` instead. + temporal.api.enums.v1.VersionDrainageStatus drainage_status = 3; + + // Information about workflow drainage to help the user determine when it is safe + // to decommission a Version. Not present while version is current or ramping + VersionDrainageInfo drainage_info = 5; + + // Unset if not current. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: 'Since' captures the field semantics despite being a preposition. --) + google.protobuf.Timestamp current_since_time = 6; + + // Unset if not ramping. Updated when the version first starts ramping, not on each ramp change. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: 'Since' captures the field semantics despite being a preposition. --) + google.protobuf.Timestamp ramping_since_time = 7; + + // Last time `current_since_time`, `ramping_since_time, or `ramp_percentage` of this version changed. + google.protobuf.Timestamp routing_update_time = 8; + + // Timestamp when this version first became current or ramping. + google.protobuf.Timestamp first_activation_time = 9; + + // Timestamp when this version last became current. + // Can be used to determine whether a version has ever been Current. + google.protobuf.Timestamp last_current_time = 12; + + // Timestamp when this version last stopped being current or ramping. + // Cleared if the version becomes current or ramping again. + google.protobuf.Timestamp last_deactivation_time = 10; + + temporal.api.compute.v1.ComputeConfigSummary compute_config = 13; + + // ComputeStatus represents compute-related configuration and healthchecks. + ComputeStatus compute_status = 14; + } +} + +// A Worker Deployment Version (Version, for short) represents a +// version of workers within a Worker Deployment. (see documentation of WorkerDeploymentVersionInfo) +// Version records are created in Temporal server automatically when their +// first poller arrives to the server. +// Experimental. Worker Deployment Versions are experimental and might significantly change in the future. +message WorkerDeploymentVersion { + // A unique identifier for this Version within the Deployment it is a part of. + // Not necessarily unique within the namespace. + // The combination of `deployment_name` and `build_id` uniquely identifies this + // Version within the namespace, because Deployment names are unique within a namespace. + string build_id = 1; + + // Identifies the Worker Deployment this Version is part of. + string deployment_name = 2; +} + +message VersionMetadata { + // Arbitrary key-values. + map entries = 1; +} + +message RoutingConfig { + // Specifies which Deployment Version should receive new workflow executions and tasks of + // existing unversioned or AutoUpgrade workflows. + // Nil value means no Version in this Deployment (except Ramping Version, if present) receives traffic other than tasks of previously Pinned workflows. In absence of a Current Version, remaining traffic after any ramp (if set) goes to unversioned workers (those with `UNVERSIONED` (or unspecified) `WorkerVersioningMode`.). + // Note: Current Version is overridden by the Ramping Version for a portion of traffic when ramp percentage + // is non-zero (see `ramping_deployment_version` and `ramping_version_percentage`). + WorkerDeploymentVersion current_deployment_version = 7; + + // Deprecated. Use `current_deployment_version`. + string current_version = 1 [deprecated = true]; + + // When ramp percentage is non-zero, that portion of traffic is shifted from the Current Version to the Ramping Version. + // Must always be different from `current_deployment_version` unless both are nil. + // Nil value represents all the unversioned workers (those with `UNVERSIONED` (or unspecified) `WorkerVersioningMode`.) + // Note that it is possible to ramp from one Version to another Version, or from unversioned + // workers to a particular Version, or from a particular Version to unversioned workers. + WorkerDeploymentVersion ramping_deployment_version = 9; + + // Deprecated. Use `ramping_deployment_version`. + string ramping_version = 2 [deprecated = true]; + + // Percentage of tasks that are routed to the Ramping Version instead of the Current Version. + // Valid range: [0, 100]. A 100% value means the Ramping Version is receiving full traffic but + // not yet "promoted" to be the Current Version, likely due to pending validations. + // A 0% value means the Ramping Version is receiving no traffic. + float ramping_version_percentage = 3; + + // Last time current version was changed. + google.protobuf.Timestamp current_version_changed_time = 4; + + // Last time ramping version was changed. Not updated if only the ramp percentage changes. + google.protobuf.Timestamp ramping_version_changed_time = 5; + + // Last time ramping version percentage was changed. + // If ramping version is changed, this is also updated, even if the percentage stays the same. + google.protobuf.Timestamp ramping_version_percentage_changed_time = 6; + + // Monotonically increasing value which is incremented on every mutation + // to any field of this message to achieve eventual consistency between task queues and their partitions. + int64 revision_number = 10; +} + +// Used as part of WorkflowExecutionStartedEventAttributes to pass down the AutoUpgrade behavior and source deployment version +// to a workflow execution whose parent/previous workflow has an AutoUpgrade behavior. +// Also used for Upgrade-on-CaN behaviors AutoUpgrade and UseRampingVersion. +message InheritedAutoUpgradeInfo { + // The source deployment version of the parent/previous workflow. + WorkerDeploymentVersion source_deployment_version = 1; + + // The revision number of the source deployment version of the parent/previous workflow. + int64 source_deployment_revision_number = 2; + + // Experimental. + // If this workflow is the result of a continue-as-new, this field is set to the initial_versioning_behavior + // specified in that command. + // Only used for the initial task of this run and the initial task of any retries of this run. + // Not passed to children or to future continue-as-new. + // + // Note: In the first release of Upgrade-on-CaN, when the only ContinueAsNewVersioningBehavior was AutoUpgrade, + // a non-empty InheritedAutoUpgradeInfo meant that the workflow should start as AutoUpgrade. So for compatibility + // with history events generated during that time, know that an UNSPECIFIED value here is equivalent to AutoUpgrade + // value if the InheritedAutoUpgradeInfo is non-empty. + temporal.api.enums.v1.ContinueAsNewVersioningBehavior continue_as_new_initial_versioning_behavior = 3; +} diff --git a/temporal/api/enums/v1/activity.proto b/temporal/api/enums/v1/activity.proto new file mode 100644 index 000000000..9a39e9473 --- /dev/null +++ b/temporal/api/enums/v1/activity.proto @@ -0,0 +1,92 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "ActivityProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// Status of a standalone activity. +// The status is updated when the activity is originally scheduled, paused, unpaused, and when the +// activity reaches a terminal state. +// (-- api-linter: core::0216::synonyms=disabled +// aip.dev/not-precedent: Named consistently with WorkflowExecutionStatus. --) +enum ActivityExecutionStatus { + ACTIVITY_EXECUTION_STATUS_UNSPECIFIED = 0; + + // The activity has not reached a terminal status. See PendingActivityState for the run state + // (SCHEDULED, STARTED, or CANCEL_REQUESTED). + ACTIVITY_EXECUTION_STATUS_RUNNING = 1; + + // The activity completed successfully. An activity can complete even after cancellation is + // requested if the worker calls RespondActivityTaskCompleted before acknowledging cancellation. + ACTIVITY_EXECUTION_STATUS_COMPLETED = 2; + + // The activity failed. Causes: + // - Worker returned a non-retryable failure + // - RetryPolicy.maximum_attempts exhausted + // - Attempt failed after cancellation was requested (retries blocked) + ACTIVITY_EXECUTION_STATUS_FAILED = 3; + + // The activity was canceled. Reached when: + // - Cancellation requested while SCHEDULED (immediate), or + // - Cancellation requested while STARTED and worker called RespondActivityTaskCanceled. + // + // Workers discover cancellation requests via heartbeat responses (cancel_requested=true). + // Activities that do not heartbeat will not learn of cancellation and may complete, fail, or + // time out normally. CANCELED requires explicit worker acknowledgment or immediate cancellation + // of a SCHEDULED activity. + ACTIVITY_EXECUTION_STATUS_CANCELED = 4; + + // The activity was terminated. Immediate; does not wait for worker acknowledgment. + ACTIVITY_EXECUTION_STATUS_TERMINATED = 5; + + // The activity timed out. See TimeoutType for the specific timeout. + // - SCHEDULE_TO_START and SCHEDULE_TO_CLOSE timeouts always result in TIMED_OUT. + // - START_TO_CLOSE and HEARTBEAT may retry if RetryPolicy permits; TIMED_OUT is + // reached when retry is blocked (RetryPolicy.maximum_attempts exhausted, + // SCHEDULE_TO_CLOSE would be exceeded, or cancellation has been requested). + ACTIVITY_EXECUTION_STATUS_TIMED_OUT = 6; + + // The activity is paused. Paused state is only reachable after calling + // PauseActivityExecution on a standalone activity. + ACTIVITY_EXECUTION_STATUS_PAUSED = 7; +} + +// Defines whether to allow re-using an activity ID from a previously *closed* activity. +// If the request is denied, the server returns an `ActivityExecutionAlreadyStarted` error. +// +// See `ActivityIdConflictPolicy` for handling ID duplication with a *running* activity. +enum ActivityIdReusePolicy { + ACTIVITY_ID_REUSE_POLICY_UNSPECIFIED = 0; + + // Always allow starting an activity using the same activity ID. + ACTIVITY_ID_REUSE_POLICY_ALLOW_DUPLICATE = 1; + + // Allow starting an activity using the same ID only when the last activity's final state is one + // of {failed, canceled, terminated, timed out}. + ACTIVITY_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY = 2; + + // Do not permit re-use of the ID for this activity. Future start requests could potentially change the policy, + // allowing re-use of the ID. + ACTIVITY_ID_REUSE_POLICY_REJECT_DUPLICATE = 3; +} + +// Defines what to do when trying to start an activity with the same ID as a *running* activity. +// Note that it is *never* valid to have two running instances of the same activity ID. +// +// See `ActivityIdReusePolicy` for handling activity ID duplication with a *closed* activity. +enum ActivityIdConflictPolicy { + ACTIVITY_ID_CONFLICT_POLICY_UNSPECIFIED = 0; + + // Don't start a new activity; instead return `ActivityExecutionAlreadyStarted` error. + ACTIVITY_ID_CONFLICT_POLICY_FAIL = 1; + + // Don't start a new activity; instead return a handle for the running activity. + ACTIVITY_ID_CONFLICT_POLICY_USE_EXISTING = 2; +} diff --git a/temporal/api/enums/v1/batch_operation.proto b/temporal/api/enums/v1/batch_operation.proto new file mode 100644 index 000000000..5b2bc8503 --- /dev/null +++ b/temporal/api/enums/v1/batch_operation.proto @@ -0,0 +1,68 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "BatchOperationProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +enum BatchOperationType { + BATCH_OPERATION_TYPE_UNSPECIFIED = 0; + + // DEPRECATED: Use BATCH_OPERATION_TYPE_TERMINATE_WORKFLOW instead. + BATCH_OPERATION_TYPE_TERMINATE = 1 [deprecated = true]; + + BATCH_OPERATION_TYPE_TERMINATE_WORKFLOW = 13; + + // DEPRECATED: Use BATCH_OPERATION_TYPE_CANCEL_WORKFLOW instead. + BATCH_OPERATION_TYPE_CANCEL = 2 [deprecated = true]; + + BATCH_OPERATION_TYPE_CANCEL_WORKFLOW = 14; + + // DEPRECATED: Use BATCH_OPERATION_TYPE_SIGNAL_WORKFLOW instead. + BATCH_OPERATION_TYPE_SIGNAL = 3 [deprecated = true]; + + BATCH_OPERATION_TYPE_SIGNAL_WORKFLOW = 15; + + // DEPRECATED: Use BATCH_OPERATION_TYPE_DELETE_WORKFLOW instead. + BATCH_OPERATION_TYPE_DELETE = 4 [deprecated = true]; + + BATCH_OPERATION_TYPE_DELETE_WORKFLOW = 16; + + // DEPRECATED: Use BATCH_OPERATION_TYPE_RESET_WORKFLOW instead. + BATCH_OPERATION_TYPE_RESET = 5 [deprecated = true]; + + BATCH_OPERATION_TYPE_RESET_WORKFLOW = 17; + + // DEPRECATED: Use BATCH_OPERATION_TYPE_UPDATE_WORKFLOW_EXECUTION_OPTIONS instead. + BATCH_OPERATION_TYPE_UPDATE_EXECUTION_OPTIONS = 6 [deprecated = true]; + + BATCH_OPERATION_TYPE_UPDATE_WORKFLOW_EXECUTION_OPTIONS = 18; + + BATCH_OPERATION_TYPE_UNPAUSE_ACTIVITY = 7; + + BATCH_OPERATION_TYPE_UPDATE_ACTIVITY_OPTIONS = 8; + + BATCH_OPERATION_TYPE_RESET_ACTIVITY = 9; + + BATCH_OPERATION_TYPE_TERMINATE_ACTIVITY = 10; + + BATCH_OPERATION_TYPE_CANCEL_ACTIVITY = 11; + + BATCH_OPERATION_TYPE_DELETE_ACTIVITY = 12; +} + +enum BatchOperationState { + BATCH_OPERATION_STATE_UNSPECIFIED = 0; + + BATCH_OPERATION_STATE_RUNNING = 1; + + BATCH_OPERATION_STATE_COMPLETED = 2; + + BATCH_OPERATION_STATE_FAILED = 3; +} diff --git a/temporal/api/enums/v1/command_type.proto b/temporal/api/enums/v1/command_type.proto new file mode 100644 index 000000000..ff3d72dad --- /dev/null +++ b/temporal/api/enums/v1/command_type.proto @@ -0,0 +1,51 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "CommandTypeProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// Whenever this list of command types is changed do change the function shouldBufferEvent in mutableStateBuilder.go to make sure to do the correct event ordering. +enum CommandType { + COMMAND_TYPE_UNSPECIFIED = 0; + + COMMAND_TYPE_SCHEDULE_ACTIVITY_TASK = 1; + + COMMAND_TYPE_REQUEST_CANCEL_ACTIVITY_TASK = 2; + + COMMAND_TYPE_START_TIMER = 3; + + COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION = 4; + + COMMAND_TYPE_FAIL_WORKFLOW_EXECUTION = 5; + + COMMAND_TYPE_CANCEL_TIMER = 6; + + COMMAND_TYPE_CANCEL_WORKFLOW_EXECUTION = 7; + + COMMAND_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION = 8; + + COMMAND_TYPE_RECORD_MARKER = 9; + + COMMAND_TYPE_CONTINUE_AS_NEW_WORKFLOW_EXECUTION = 10; + + COMMAND_TYPE_START_CHILD_WORKFLOW_EXECUTION = 11; + + COMMAND_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION = 12; + + COMMAND_TYPE_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES = 13; + + COMMAND_TYPE_PROTOCOL_MESSAGE = 14; + + COMMAND_TYPE_MODIFY_WORKFLOW_PROPERTIES = 16; + + COMMAND_TYPE_SCHEDULE_NEXUS_OPERATION = 17; + + COMMAND_TYPE_REQUEST_CANCEL_NEXUS_OPERATION = 18; +} diff --git a/temporal/api/enums/v1/common.proto b/temporal/api/enums/v1/common.proto new file mode 100644 index 000000000..cfb751004 --- /dev/null +++ b/temporal/api/enums/v1/common.proto @@ -0,0 +1,154 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "CommonProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +enum EncodingType { + ENCODING_TYPE_UNSPECIFIED = 0; + + ENCODING_TYPE_PROTO3 = 1; + + ENCODING_TYPE_JSON = 2; +} + +enum IndexedValueType { + INDEXED_VALUE_TYPE_UNSPECIFIED = 0; + + INDEXED_VALUE_TYPE_TEXT = 1; + + INDEXED_VALUE_TYPE_KEYWORD = 2; + + INDEXED_VALUE_TYPE_INT = 3; + + INDEXED_VALUE_TYPE_DOUBLE = 4; + + INDEXED_VALUE_TYPE_BOOL = 5; + + INDEXED_VALUE_TYPE_DATETIME = 6; + + INDEXED_VALUE_TYPE_KEYWORD_LIST = 7; +} + +enum Severity { + SEVERITY_UNSPECIFIED = 0; + + SEVERITY_HIGH = 1; + + SEVERITY_MEDIUM = 2; + + SEVERITY_LOW = 3; +} + +// State of a callback. +enum CallbackState { + // Default value, unspecified state. + CALLBACK_STATE_UNSPECIFIED = 0; + + // Callback is standing by, waiting to be triggered. + CALLBACK_STATE_STANDBY = 1; + + // Callback is in the queue waiting to be executed or is currently executing. + CALLBACK_STATE_SCHEDULED = 2; + + // Callback has failed with a retryable error and is backing off before the next attempt. + CALLBACK_STATE_BACKING_OFF = 3; + + // Callback has failed. + CALLBACK_STATE_FAILED = 4; + + // Callback has succeeded. + CALLBACK_STATE_SUCCEEDED = 5; + + // Callback is blocked (eg: by circuit breaker). + CALLBACK_STATE_BLOCKED = 6; +} + +// State of a pending Nexus operation. +enum PendingNexusOperationState { + // Default value, unspecified state. + PENDING_NEXUS_OPERATION_STATE_UNSPECIFIED = 0; + + // Operation is in the queue waiting to be executed or is currently executing. + PENDING_NEXUS_OPERATION_STATE_SCHEDULED = 1; + + // Operation has failed with a retryable error and is backing off before the next attempt. + PENDING_NEXUS_OPERATION_STATE_BACKING_OFF = 2; + + // Operation was started and will complete asynchronously. + PENDING_NEXUS_OPERATION_STATE_STARTED = 3; + + // Operation is blocked (eg: by circuit breaker). + PENDING_NEXUS_OPERATION_STATE_BLOCKED = 4; +} + +// State of a Nexus operation cancellation. +enum NexusOperationCancellationState { + // Default value, unspecified state. + NEXUS_OPERATION_CANCELLATION_STATE_UNSPECIFIED = 0; + + // Cancellation request is in the queue waiting to be executed or is currently executing. + NEXUS_OPERATION_CANCELLATION_STATE_SCHEDULED = 1; + + // Cancellation request has failed with a retryable error and is backing off before the next attempt. + NEXUS_OPERATION_CANCELLATION_STATE_BACKING_OFF = 2; + + // Cancellation request succeeded. + NEXUS_OPERATION_CANCELLATION_STATE_SUCCEEDED = 3; + + // Cancellation request failed with a non-retryable error. + NEXUS_OPERATION_CANCELLATION_STATE_FAILED = 4; + + // The associated operation timed out - exceeded the user supplied schedule-to-close timeout. + NEXUS_OPERATION_CANCELLATION_STATE_TIMED_OUT = 5; + + // Cancellation request is blocked (eg: by circuit breaker). + NEXUS_OPERATION_CANCELLATION_STATE_BLOCKED = 6; +} + +enum WorkflowRuleActionScope { + // Default value, unspecified scope. + WORKFLOW_RULE_ACTION_SCOPE_UNSPECIFIED = 0; + + // The action will be applied to the entire workflow. + WORKFLOW_RULE_ACTION_SCOPE_WORKFLOW = 1; + + // The action will be applied to a specific activity. + WORKFLOW_RULE_ACTION_SCOPE_ACTIVITY = 2; +} + +enum ApplicationErrorCategory { + APPLICATION_ERROR_CATEGORY_UNSPECIFIED = 0; + + // Expected application error with little/no severity. + APPLICATION_ERROR_CATEGORY_BENIGN = 1; +} + +// (-- api-linter: core::0216::synonyms=disabled +// aip.dev/not-precedent: It seems we have both state and status, and status is a better fit for workers. --) +enum WorkerStatus { + WORKER_STATUS_UNSPECIFIED = 0; + + WORKER_STATUS_RUNNING = 1; + + WORKER_STATUS_SHUTTING_DOWN = 2; + + WORKER_STATUS_SHUTDOWN = 3; +} + +enum ExecutionType { + EXECUTION_TYPE_UNSPECIFIED = 0; + + // A workflow execution archetype. + EXECUTION_TYPE_WORKFLOW = 1; + + // An activity execution archetype. This is reserved for standalone activities. + EXECUTION_TYPE_ACTIVITY = 2; +} diff --git a/temporal/api/enums/v1/deployment.proto b/temporal/api/enums/v1/deployment.proto new file mode 100644 index 000000000..e60ce8c59 --- /dev/null +++ b/temporal/api/enums/v1/deployment.proto @@ -0,0 +1,115 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "DeploymentProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// Specify the reachability level for a deployment so users can decide if it is time to +// decommission the deployment. +enum DeploymentReachability { + // Reachability level is not specified. + DEPLOYMENT_REACHABILITY_UNSPECIFIED = 0; + + // The deployment is reachable by new and/or open workflows. The deployment cannot be + // decommissioned safely. + DEPLOYMENT_REACHABILITY_REACHABLE = 1; + + // The deployment is not reachable by new or open workflows, but might be still needed by + // Queries sent to closed workflows. The deployment can be decommissioned safely if user does + // not query closed workflows. + DEPLOYMENT_REACHABILITY_CLOSED_WORKFLOWS_ONLY = 2; + + // The deployment is not reachable by any workflow because all the workflows who needed this + // deployment went out of retention period. The deployment can be decommissioned safely. + DEPLOYMENT_REACHABILITY_UNREACHABLE = 3; +} + +// (-- api-linter: core::0216::synonyms=disabled +// aip.dev/not-precedent: Call this status because it is . --) +// Specify the drainage status for a Worker Deployment Version so users can decide whether they +// can safely decommission the version. +enum VersionDrainageStatus { + // Drainage Status is not specified. + VERSION_DRAINAGE_STATUS_UNSPECIFIED = 0; + + // The Worker Deployment Version is not used by new workflows but is still used by + // open pinned workflows. The version cannot be decommissioned safely. + VERSION_DRAINAGE_STATUS_DRAINING = 1; + + // The Worker Deployment Version is not used by new or open workflows, but might be still needed by + // Queries sent to closed workflows. The version can be decommissioned safely if user does + // not query closed workflows. If the user does query closed workflows for some time x after + // workflows are closed, they should decommission the version after it has been drained for that duration. + VERSION_DRAINAGE_STATUS_DRAINED = 2; +} + +// Versioning Mode of a worker is set by the app developer in the worker code, and specifies the +// behavior of the system in the following related aspects: +// - Whether or not Temporal Server considers this worker's version (Build ID) when dispatching +// tasks to it. +// - Whether or not the workflows processed by this worker are versioned using the worker's version. +enum WorkerVersioningMode { + WORKER_VERSIONING_MODE_UNSPECIFIED = 0; + + // Workers with this mode are not distinguished from each other for task routing, even if they + // have different Build IDs. + // Workflows processed by this worker will be unversioned and user needs to use Patching to keep + // the new code compatible with prior versions. + // This mode is recommended to be used along with Rolling Upgrade deployment strategies. + // Workers with this mode are represented by the special string `__unversioned__` in the APIs. + WORKER_VERSIONING_MODE_UNVERSIONED = 1; + + // Workers with this mode are part of a Worker Deployment Version which is identified as + // ".". Such workers are called "versioned" as opposed to + // "unversioned". + // Each Deployment Version is distinguished from other Versions for task routing and users can + // configure Temporal Server to send tasks to a particular Version (see + // `WorkerDeploymentInfo.routing_config`). This mode is the best option for Blue/Green and + // Rainbow strategies (but typically not suitable for Rolling upgrades.) + // Workflow Versioning Behaviors are enabled in this mode: each workflow type must choose + // between the Pinned and AutoUpgrade behaviors. Depending on the chosen behavior, the user may + // or may not need to use Patching to keep the new code compatible with prior versions. (see + // VersioningBehavior enum.) + WORKER_VERSIONING_MODE_VERSIONED = 2; +} + +// (-- api-linter: core::0216::synonyms=disabled +// aip.dev/not-precedent: Call this status because it is . --) +// Specify the status of a Worker Deployment Version. +enum WorkerDeploymentVersionStatus { + WORKER_DEPLOYMENT_VERSION_STATUS_UNSPECIFIED = 0; + + // The Worker Deployment Version has been created inside the Worker Deployment but is not used by any + // workflow executions. These Versions can still have workflows if they have an explicit Versioning Override targeting + // this Version. Such Versioning Override could be set at workflow start time, or at a later time via `UpdateWorkflowExecutionOptions`. + WORKER_DEPLOYMENT_VERSION_STATUS_INACTIVE = 1; + + // The Worker Deployment Version is the current version of the Worker Deployment. All new workflow executions + // and tasks of existing unversioned or AutoUpgrade workflows are routed to this version. + WORKER_DEPLOYMENT_VERSION_STATUS_CURRENT = 2; + + // The Worker Deployment Version is the ramping version of the Worker Deployment. A subset of new Pinned workflow executions are + // routed to this version. Moreover, a portion of existing unversioned or AutoUpgrade workflow executions are also routed to this version. + WORKER_DEPLOYMENT_VERSION_STATUS_RAMPING = 3; + + // The Worker Deployment Version is not used by new workflows but is still used by + // open pinned workflows. The version cannot be decommissioned safely. + WORKER_DEPLOYMENT_VERSION_STATUS_DRAINING = 4; + + // The Worker Deployment Version is not used by new or open workflows, but might be still needed by + // Queries sent to closed workflows. The version can be decommissioned safely if user does + // not query closed workflows. If the user does query closed workflows for some time x after + // workflows are closed, they should decommission the version after it has been drained for that duration. + WORKER_DEPLOYMENT_VERSION_STATUS_DRAINED = 5; + + // The Worker Deployment Version is created by user (via `CreateWorkerDeploymentVersion` API) + // but server has not seen any poller for it yet. + WORKER_DEPLOYMENT_VERSION_STATUS_CREATED = 6; +} diff --git a/temporal/api/enums/v1/event_type.proto b/temporal/api/enums/v1/event_type.proto new file mode 100644 index 000000000..eb56fc9ca --- /dev/null +++ b/temporal/api/enums/v1/event_type.proto @@ -0,0 +1,240 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "EventTypeProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// Whenever this list of events is changed do change the function shouldBufferEvent in mutableStateBuilder.go to make sure to do the correct event ordering +enum EventType { + // Place holder and should never appear in a Workflow execution history + EVENT_TYPE_UNSPECIFIED = 0; + + // Workflow execution has been triggered/started + // It contains Workflow execution inputs, as well as Workflow timeout configurations + EVENT_TYPE_WORKFLOW_EXECUTION_STARTED = 1; + + // Workflow execution has successfully completed and contains Workflow execution results + EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED = 2; + + // Workflow execution has unsuccessfully completed and contains the Workflow execution error + EVENT_TYPE_WORKFLOW_EXECUTION_FAILED = 3; + + // Workflow execution has timed out by the Temporal Server + // Usually due to the Workflow having not been completed within timeout settings + EVENT_TYPE_WORKFLOW_EXECUTION_TIMED_OUT = 4; + + // Workflow Task has been scheduled and the SDK client should now be able to process any new history events + EVENT_TYPE_WORKFLOW_TASK_SCHEDULED = 5; + + // Workflow Task has started and the SDK client has picked up the Workflow Task and is processing new history events + EVENT_TYPE_WORKFLOW_TASK_STARTED = 6; + + // Workflow Task has completed + // The SDK client picked up the Workflow Task and processed new history events + // SDK client may or may not ask the Temporal Server to do additional work, such as: + // EVENT_TYPE_ACTIVITY_TASK_SCHEDULED + // EVENT_TYPE_TIMER_STARTED + // EVENT_TYPE_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES + // EVENT_TYPE_MARKER_RECORDED + // EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_INITIATED + // EVENT_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED + // EVENT_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED + // EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED + // EVENT_TYPE_WORKFLOW_EXECUTION_FAILED + // EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED + // EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW + EVENT_TYPE_WORKFLOW_TASK_COMPLETED = 7; + + // Workflow Task encountered a timeout + // Either an SDK client with a local cache was not available at the time, or it took too long for the SDK client to process the task + EVENT_TYPE_WORKFLOW_TASK_TIMED_OUT = 8; + + // Workflow Task encountered a failure + // Usually this means that the Workflow was non-deterministic + // However, the Workflow reset functionality also uses this event + EVENT_TYPE_WORKFLOW_TASK_FAILED = 9; + + // Activity Task was scheduled + // The SDK client should pick up this activity task and execute + // This event type contains activity inputs, as well as activity timeout configurations + EVENT_TYPE_ACTIVITY_TASK_SCHEDULED = 10; + + // Activity Task has started executing + // The SDK client has picked up the Activity Task and is processing the Activity invocation + EVENT_TYPE_ACTIVITY_TASK_STARTED = 11; + + // Activity Task has finished successfully + // The SDK client has picked up and successfully completed the Activity Task + // This event type contains Activity execution results + EVENT_TYPE_ACTIVITY_TASK_COMPLETED = 12; + + // Activity Task has finished unsuccessfully + // The SDK picked up the Activity Task but unsuccessfully completed it + // This event type contains Activity execution errors + EVENT_TYPE_ACTIVITY_TASK_FAILED = 13; + + // Activity has timed out according to the Temporal Server + // Activity did not complete within the timeout settings + EVENT_TYPE_ACTIVITY_TASK_TIMED_OUT = 14; + + // A request to cancel the Activity has occurred + // The SDK client will be able to confirm cancellation of an Activity during an Activity heartbeat + EVENT_TYPE_ACTIVITY_TASK_CANCEL_REQUESTED = 15; + + // Activity has been cancelled + EVENT_TYPE_ACTIVITY_TASK_CANCELED = 16; + + // A timer has started + EVENT_TYPE_TIMER_STARTED = 17; + + // A timer has fired + EVENT_TYPE_TIMER_FIRED = 18; + + // A time has been cancelled + EVENT_TYPE_TIMER_CANCELED = 19; + + // A request has been made to cancel the Workflow execution + EVENT_TYPE_WORKFLOW_EXECUTION_CANCEL_REQUESTED = 20; + + // SDK client has confirmed the cancellation request and the Workflow execution has been cancelled + EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED = 21; + + // Workflow has requested that the Temporal Server try to cancel another Workflow + EVENT_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED = 22; + + // Temporal Server could not cancel the targeted Workflow + // This is usually because the target Workflow could not be found + EVENT_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_FAILED = 23; + + // Temporal Server has successfully requested the cancellation of the target Workflow + EVENT_TYPE_EXTERNAL_WORKFLOW_EXECUTION_CANCEL_REQUESTED = 24; + + // A marker has been recorded. + // This event type is transparent to the Temporal Server + // The Server will only store it and will not try to understand it. + EVENT_TYPE_MARKER_RECORDED = 25; + + // Workflow has received a Signal event + // The event type contains the Signal name, as well as a Signal payload + EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED = 26; + + // Workflow execution has been forcefully terminated + // This is usually because the terminate Workflow API was called + EVENT_TYPE_WORKFLOW_EXECUTION_TERMINATED = 27; + + // Workflow has successfully completed and a new Workflow has been started within the same transaction + // Contains last Workflow execution results as well as new Workflow execution inputs + EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW = 28; + + // Temporal Server will try to start a child Workflow + EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_INITIATED = 29; + + // Child Workflow execution cannot be started/triggered + // Usually due to a child Workflow ID collision + EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_FAILED = 30; + + // Child Workflow execution has successfully started/triggered + EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_STARTED = 31; + + // Child Workflow execution has successfully completed + EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_COMPLETED = 32; + + // Child Workflow execution has unsuccessfully completed + EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_FAILED = 33; + + // Child Workflow execution has been cancelled + EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_CANCELED = 34; + + // Child Workflow execution has timed out by the Temporal Server + EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_TIMED_OUT = 35; + + // Child Workflow execution has been terminated + EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_TERMINATED = 36; + + // Temporal Server will try to Signal the targeted Workflow + // Contains the Signal name, as well as a Signal payload + EVENT_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED = 37; + + // Temporal Server cannot Signal the targeted Workflow + // Usually because the Workflow could not be found + EVENT_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED = 38; + + // Temporal Server has successfully Signaled the targeted Workflow + EVENT_TYPE_EXTERNAL_WORKFLOW_EXECUTION_SIGNALED = 39; + + // Workflow search attributes should be updated and synchronized with the visibility store + EVENT_TYPE_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES = 40; + + // An update was admitted. Note that not all admitted updates result in this + // event. See UpdateAdmittedEventOrigin for situations in which this event + // is created. + EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ADMITTED = 47; + + // An update was accepted (i.e. passed validation, perhaps because no validator was defined) + EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED = 41; + + // This event is never written to history. + EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_REJECTED = 42; + + // An update completed + EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_COMPLETED = 43; + + // Some property or properties of the workflow as a whole have changed by non-workflow code. + // The distinction of external vs. command-based modification is important so the SDK can + // maintain determinism when using the command-based approach. + EVENT_TYPE_WORKFLOW_PROPERTIES_MODIFIED_EXTERNALLY = 44; + + // Some property or properties of an already-scheduled activity have changed by non-workflow code. + // The distinction of external vs. command-based modification is important so the SDK can + // maintain determinism when using the command-based approach. + EVENT_TYPE_ACTIVITY_PROPERTIES_MODIFIED_EXTERNALLY = 45; + + // Workflow properties modified by user workflow code + EVENT_TYPE_WORKFLOW_PROPERTIES_MODIFIED = 46; + + // A Nexus operation was scheduled using a ScheduleNexusOperation command. + EVENT_TYPE_NEXUS_OPERATION_SCHEDULED = 48; + + // An asynchronous Nexus operation was started by a Nexus handler. + EVENT_TYPE_NEXUS_OPERATION_STARTED = 49; + + // A Nexus operation completed successfully. + EVENT_TYPE_NEXUS_OPERATION_COMPLETED = 50; + + // A Nexus operation failed. + EVENT_TYPE_NEXUS_OPERATION_FAILED = 51; + + // A Nexus operation completed as canceled. + EVENT_TYPE_NEXUS_OPERATION_CANCELED = 52; + + // A Nexus operation timed out. + EVENT_TYPE_NEXUS_OPERATION_TIMED_OUT = 53; + + // A Nexus operation was requested to be canceled using a RequestCancelNexusOperation command. + EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED = 54; + + // Workflow execution options updated by user. + EVENT_TYPE_WORKFLOW_EXECUTION_OPTIONS_UPDATED = 55; + + // A cancellation request for a Nexus operation was successfully delivered to the Nexus handler. + EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_COMPLETED = 56; + + // A cancellation request for a Nexus operation resulted in an error. + EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_FAILED = 57; + + // An event that indicates that the workflow execution has been paused. + EVENT_TYPE_WORKFLOW_EXECUTION_PAUSED = 58; + + // An event that indicates that the previously paused workflow execution has been unpaused. + EVENT_TYPE_WORKFLOW_EXECUTION_UNPAUSED = 59; + + // An event that indicates time skipping advanced time or was disabled automatically after a bound was reached. + EVENT_TYPE_WORKFLOW_EXECUTION_TIME_SKIPPING_TRANSITIONED = 60; +} diff --git a/temporal/api/enums/v1/failed_cause.proto b/temporal/api/enums/v1/failed_cause.proto new file mode 100644 index 000000000..f7f109a56 --- /dev/null +++ b/temporal/api/enums/v1/failed_cause.proto @@ -0,0 +1,206 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "FailedCauseProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// Workflow tasks can fail for various reasons. Note that some of these reasons can only originate +// from the server, and some of them can only originate from the SDK/worker. +enum WorkflowTaskFailedCause { + WORKFLOW_TASK_FAILED_CAUSE_UNSPECIFIED = 0; + + // Between starting and completing the workflow task (with a workflow completion command), some + // new command (like a signal) was processed into workflow history. The outstanding task will be + // failed with this reason, and a worker must pick up a new task. + WORKFLOW_TASK_FAILED_CAUSE_UNHANDLED_COMMAND = 1; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_SCHEDULE_ACTIVITY_ATTRIBUTES = 2; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_REQUEST_CANCEL_ACTIVITY_ATTRIBUTES = 3; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_START_TIMER_ATTRIBUTES = 4; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_CANCEL_TIMER_ATTRIBUTES = 5; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_RECORD_MARKER_ATTRIBUTES = 6; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_COMPLETE_WORKFLOW_EXECUTION_ATTRIBUTES = 7; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_FAIL_WORKFLOW_EXECUTION_ATTRIBUTES = 8; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_CANCEL_WORKFLOW_EXECUTION_ATTRIBUTES = 9; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_ATTRIBUTES = 10; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_CONTINUE_AS_NEW_ATTRIBUTES = 11; + + WORKFLOW_TASK_FAILED_CAUSE_START_TIMER_DUPLICATE_ID = 12; + + // The worker wishes to fail the task and have the next one be generated on a normal, not sticky + // queue. Generally workers should prefer to use the explicit `ResetStickyTaskQueue` RPC call. + WORKFLOW_TASK_FAILED_CAUSE_RESET_STICKY_TASK_QUEUE = 13; + + WORKFLOW_TASK_FAILED_CAUSE_WORKFLOW_WORKER_UNHANDLED_FAILURE = 14; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_SIGNAL_WORKFLOW_EXECUTION_ATTRIBUTES = 15; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_START_CHILD_EXECUTION_ATTRIBUTES = 16; + + WORKFLOW_TASK_FAILED_CAUSE_FORCE_CLOSE_COMMAND = 17; + + WORKFLOW_TASK_FAILED_CAUSE_FAILOVER_CLOSE_COMMAND = 18; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_SIGNAL_INPUT_SIZE = 19; + + WORKFLOW_TASK_FAILED_CAUSE_RESET_WORKFLOW = 20; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_BINARY = 21; + + WORKFLOW_TASK_FAILED_CAUSE_SCHEDULE_ACTIVITY_DUPLICATE_ID = 22; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_SEARCH_ATTRIBUTES = 23; + + // The worker encountered a mismatch while replaying history between what was expected, and + // what the workflow code actually did. + WORKFLOW_TASK_FAILED_CAUSE_NON_DETERMINISTIC_ERROR = 24; + + WORKFLOW_TASK_FAILED_CAUSE_BAD_MODIFY_WORKFLOW_PROPERTIES_ATTRIBUTES = 25; + + // We send the below error codes to users when their requests would violate a size constraint + // of their workflow. We do this to ensure that the state of their workflow does not become too + // large because that can cause severe performance degradation. You can modify the thresholds for + // each of these errors within your dynamic config. + // + // Spawning a new child workflow would cause this workflow to exceed its limit of pending child + // workflows. + WORKFLOW_TASK_FAILED_CAUSE_PENDING_CHILD_WORKFLOWS_LIMIT_EXCEEDED = 26; + + // Starting a new activity would cause this workflow to exceed its limit of pending activities + // that we track. + WORKFLOW_TASK_FAILED_CAUSE_PENDING_ACTIVITIES_LIMIT_EXCEEDED = 27; + + // A workflow has a buffer of signals that have not yet reached their destination. We return this + // error when sending a new signal would exceed the capacity of this buffer. + WORKFLOW_TASK_FAILED_CAUSE_PENDING_SIGNALS_LIMIT_EXCEEDED = 28; + + // Similarly, we have a buffer of pending requests to cancel other workflows. We return this error + // when our capacity for pending cancel requests is already reached. + WORKFLOW_TASK_FAILED_CAUSE_PENDING_REQUEST_CANCEL_LIMIT_EXCEEDED = 29; + + // Workflow execution update message (update.Acceptance, update.Rejection, or update.Response) + // has wrong format, or missing required fields. + WORKFLOW_TASK_FAILED_CAUSE_BAD_UPDATE_WORKFLOW_EXECUTION_MESSAGE = 30; + + // Similar to WORKFLOW_TASK_FAILED_CAUSE_UNHANDLED_COMMAND, but for updates. + WORKFLOW_TASK_FAILED_CAUSE_UNHANDLED_UPDATE = 31; + + // A workflow task completed with an invalid ScheduleNexusOperation command. + WORKFLOW_TASK_FAILED_CAUSE_BAD_SCHEDULE_NEXUS_OPERATION_ATTRIBUTES = 32; + + // A workflow task completed requesting to schedule a Nexus Operation exceeding the server configured limit. + WORKFLOW_TASK_FAILED_CAUSE_PENDING_NEXUS_OPERATIONS_LIMIT_EXCEEDED = 33; + + // A workflow task completed with an invalid RequestCancelNexusOperation command. + WORKFLOW_TASK_FAILED_CAUSE_BAD_REQUEST_CANCEL_NEXUS_OPERATION_ATTRIBUTES = 34; + + // A workflow task completed requesting a feature that's disabled on the server (either system wide or - typically - + // for the workflow's namespace). + // Check the workflow task failure message for more information. + WORKFLOW_TASK_FAILED_CAUSE_FEATURE_DISABLED = 35; + + // A workflow task failed because a grpc message was too large. + WORKFLOW_TASK_FAILED_CAUSE_GRPC_MESSAGE_TOO_LARGE = 36; + + // A workflow task failed because payloads were too large. + WORKFLOW_TASK_FAILED_CAUSE_PAYLOADS_TOO_LARGE = 37; + + // A workflow task failed because an external storage operation failed. + // Check the workflow task failure message for more information. + WORKFLOW_TASK_FAILED_CAUSE_EXTERNAL_STORAGE_FAILURE = 38; + + // A workflow task is failed because the workflow is paused before the task is started. + WORKFLOW_TASK_FAILED_CAUSE_WORKFLOW_PAUSE_REQUESTED_BEFORE_TASK_STARTED = 39; + + // A workflow task failed because the request exceeded a size limit. + WORKFLOW_TASK_FAILED_CAUSE_REQUEST_TOO_LARGE = 40; +} + +enum StartChildWorkflowExecutionFailedCause { + START_CHILD_WORKFLOW_EXECUTION_FAILED_CAUSE_UNSPECIFIED = 0; + + START_CHILD_WORKFLOW_EXECUTION_FAILED_CAUSE_WORKFLOW_ALREADY_EXISTS = 1; + + START_CHILD_WORKFLOW_EXECUTION_FAILED_CAUSE_NAMESPACE_NOT_FOUND = 2; + + START_CHILD_WORKFLOW_EXECUTION_FAILED_CAUSE_INVALID_VERSIONING_OVERRIDE = 3; +} + +enum CancelExternalWorkflowExecutionFailedCause { + CANCEL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_UNSPECIFIED = 0; + + CANCEL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_EXTERNAL_WORKFLOW_EXECUTION_NOT_FOUND = 1; + + CANCEL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_NAMESPACE_NOT_FOUND = 2; +} + +enum SignalExternalWorkflowExecutionFailedCause { + SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_UNSPECIFIED = 0; + + SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_EXTERNAL_WORKFLOW_EXECUTION_NOT_FOUND = 1; + + SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_NAMESPACE_NOT_FOUND = 2; + + // Signal count limit is per workflow and controlled by server dynamic config "history.maximumSignalsPerExecution" + SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_SIGNAL_COUNT_LIMIT_EXCEEDED = 3; +} + +enum ResourceExhaustedCause { + RESOURCE_EXHAUSTED_CAUSE_UNSPECIFIED = 0; + + // Caller exceeds request per second limit. + RESOURCE_EXHAUSTED_CAUSE_RPS_LIMIT = 1; + + // Caller exceeds max concurrent request limit. + RESOURCE_EXHAUSTED_CAUSE_CONCURRENT_LIMIT = 2; + + // System overloaded. + RESOURCE_EXHAUSTED_CAUSE_SYSTEM_OVERLOADED = 3; + + // Namespace exceeds persistence rate limit. + RESOURCE_EXHAUSTED_CAUSE_PERSISTENCE_LIMIT = 4; + + // Workflow is busy + RESOURCE_EXHAUSTED_CAUSE_BUSY_WORKFLOW = 5; + + // Caller exceeds action per second limit. + RESOURCE_EXHAUSTED_CAUSE_APS_LIMIT = 6; + + // Persistence storage limit exceeded. + RESOURCE_EXHAUSTED_CAUSE_PERSISTENCE_STORAGE_LIMIT = 7; + + // Circuit breaker is open/half-open. + RESOURCE_EXHAUSTED_CAUSE_CIRCUIT_BREAKER_OPEN = 8; + + // Namespace exceeds operations rate limit. + RESOURCE_EXHAUSTED_CAUSE_OPS_LIMIT = 9; + + // Limits related to Worker Deployments are reached. + RESOURCE_EXHAUSTED_CAUSE_WORKER_DEPLOYMENT_LIMITS = 10; +} + +enum ResourceExhaustedScope { + RESOURCE_EXHAUSTED_SCOPE_UNSPECIFIED = 0; + + // Exhausted resource is a system-level resource. + RESOURCE_EXHAUSTED_SCOPE_NAMESPACE = 1; + + // Exhausted resource is a namespace-level resource. + RESOURCE_EXHAUSTED_SCOPE_SYSTEM = 2; +} diff --git a/temporal/api/enums/v1/namespace.proto b/temporal/api/enums/v1/namespace.proto new file mode 100644 index 000000000..cb391aa96 --- /dev/null +++ b/temporal/api/enums/v1/namespace.proto @@ -0,0 +1,38 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "NamespaceProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +enum NamespaceState { + NAMESPACE_STATE_UNSPECIFIED = 0; + + NAMESPACE_STATE_REGISTERED = 1; + + NAMESPACE_STATE_DEPRECATED = 2; + + NAMESPACE_STATE_DELETED = 3; +} + +enum ArchivalState { + ARCHIVAL_STATE_UNSPECIFIED = 0; + + ARCHIVAL_STATE_DISABLED = 1; + + ARCHIVAL_STATE_ENABLED = 2; +} + +enum ReplicationState { + REPLICATION_STATE_UNSPECIFIED = 0; + + REPLICATION_STATE_NORMAL = 1; + + REPLICATION_STATE_HANDOVER = 2; +} diff --git a/temporal/api/enums/v1/nexus.proto b/temporal/api/enums/v1/nexus.proto new file mode 100644 index 000000000..b31e8c828 --- /dev/null +++ b/temporal/api/enums/v1/nexus.proto @@ -0,0 +1,99 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "NexusProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// NexusHandlerErrorRetryBehavior allows nexus handlers to explicity set the retry behavior of a HandlerError. If not +// specified, retry behavior is determined from the error type. For example internal errors are not retryable by default +// unless specified otherwise. +enum NexusHandlerErrorRetryBehavior { + NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_UNSPECIFIED = 0; + + // A handler error is explicitly marked as retryable. + NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_RETRYABLE = 1; + + // A handler error is explicitly marked as non-retryable. + NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_NON_RETRYABLE = 2; +} + +// Status of a standalone Nexus operation execution. +// The status is updated once, when the operation is originally scheduled, and again when the +// operation reaches a terminal status. +// (-- api-linter: core::0216::synonyms=disabled +// aip.dev/not-precedent: Named consistently with WorkflowExecutionStatus. --) +enum NexusOperationExecutionStatus { + NEXUS_OPERATION_EXECUTION_STATUS_UNSPECIFIED = 0; + + // The operation is not in a terminal status. The operation may be attempting to start, + // backing off between attempts, or already started. + NEXUS_OPERATION_EXECUTION_STATUS_RUNNING = 1; + + // The operation completed successfully. + NEXUS_OPERATION_EXECUTION_STATUS_COMPLETED = 2; + + // The operation completed with failure. + NEXUS_OPERATION_EXECUTION_STATUS_FAILED = 3; + + // The operation completed as canceled. + // Requesting to cancel an operation does not automatically transition the operation to canceled status, depending + // on the current operation status and the cancelation type used. + NEXUS_OPERATION_EXECUTION_STATUS_CANCELED = 4; + + // The operation was terminated. Termination happens immediately without notifying the handler. + NEXUS_OPERATION_EXECUTION_STATUS_TERMINATED = 5; + + // The operation has timed out by reaching one of the specified timeouts. + NEXUS_OPERATION_EXECUTION_STATUS_TIMED_OUT = 6; +} + +// Stage that can be specified when waiting on a nexus operation. +enum NexusOperationWaitStage { + NEXUS_OPERATION_WAIT_STAGE_UNSPECIFIED = 0; + + // Wait for the operation to be started. + NEXUS_OPERATION_WAIT_STAGE_STARTED = 1; + + // Wait for the operation to be in a terminal state, either successful or unsuccessful. + NEXUS_OPERATION_WAIT_STAGE_CLOSED = 2; +} + +// Defines whether to allow re-using an operation ID from a previously *closed* Nexus operation. +// If the request is denied, the server returns a `NexusOperationAlreadyStarted` error. +// +// See `NexusOperationIdConflictPolicy` for handling ID duplication with a *running* operation. +enum NexusOperationIdReusePolicy { + NEXUS_OPERATION_ID_REUSE_POLICY_UNSPECIFIED = 0; + + // Always allow starting an operation using the same operation ID. + NEXUS_OPERATION_ID_REUSE_POLICY_ALLOW_DUPLICATE = 1; + + // Allow starting an operation using the same ID only when the last operation's final state is one + // of {failed, canceled, terminated, timed out}. + NEXUS_OPERATION_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY = 2; + + // Do not permit re-use of the ID for this operation. Future start requests could potentially change the policy, + // allowing re-use of the ID. + NEXUS_OPERATION_ID_REUSE_POLICY_REJECT_DUPLICATE = 3; +} + +// Defines what to do when trying to start a Nexus operation with the same ID as a *running* operation. +// Note that it is *never* valid to have two running instances of the same operation ID. +// +// See `NexusOperationIdReusePolicy` for handling operation ID duplication with a *closed* operation. +enum NexusOperationIdConflictPolicy { + NEXUS_OPERATION_ID_CONFLICT_POLICY_UNSPECIFIED = 0; + + // Don't start a new operation; instead return `NexusOperationAlreadyStarted` error. + NEXUS_OPERATION_ID_CONFLICT_POLICY_FAIL = 1; + + // Don't start a new operation; instead return a handle for the running operation. + NEXUS_OPERATION_ID_CONFLICT_POLICY_USE_EXISTING = 2; +} diff --git a/temporal/api/enums/v1/query.proto b/temporal/api/enums/v1/query.proto new file mode 100644 index 000000000..97bec8cf8 --- /dev/null +++ b/temporal/api/enums/v1/query.proto @@ -0,0 +1,33 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "QueryProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +enum QueryResultType { + QUERY_RESULT_TYPE_UNSPECIFIED = 0; + + QUERY_RESULT_TYPE_ANSWERED = 1; + + QUERY_RESULT_TYPE_FAILED = 2; +} + +enum QueryRejectCondition { + QUERY_REJECT_CONDITION_UNSPECIFIED = 0; + + // None indicates that query should not be rejected. + QUERY_REJECT_CONDITION_NONE = 1; + + // NotOpen indicates that query should be rejected if workflow is not open. + QUERY_REJECT_CONDITION_NOT_OPEN = 2; + + // NotCompletedCleanly indicates that query should be rejected if workflow did not complete cleanly. + QUERY_REJECT_CONDITION_NOT_COMPLETED_CLEANLY = 3; +} diff --git a/temporal/api/enums/v1/reset.proto b/temporal/api/enums/v1/reset.proto new file mode 100644 index 000000000..7bd11ac44 --- /dev/null +++ b/temporal/api/enums/v1/reset.proto @@ -0,0 +1,56 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "ResetProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// Event types to exclude when reapplying events beyond the reset point. +enum ResetReapplyExcludeType { + RESET_REAPPLY_EXCLUDE_TYPE_UNSPECIFIED = 0; + + // Exclude signals when reapplying events beyond the reset point. + RESET_REAPPLY_EXCLUDE_TYPE_SIGNAL = 1; + + // Exclude updates when reapplying events beyond the reset point. + RESET_REAPPLY_EXCLUDE_TYPE_UPDATE = 2; + + // Exclude nexus events when reapplying events beyond the reset point. + RESET_REAPPLY_EXCLUDE_TYPE_NEXUS = 3; + + // Deprecated, unimplemented option. + RESET_REAPPLY_EXCLUDE_TYPE_CANCEL_REQUEST = 4 [deprecated = true]; +} + +// Deprecated: applications should use ResetReapplyExcludeType to specify +// exclusions from this set, and new event types should be added to ResetReapplyExcludeType +// instead of here. +enum ResetReapplyType { + RESET_REAPPLY_TYPE_UNSPECIFIED = 0; + + // Signals are reapplied when workflow is reset. + RESET_REAPPLY_TYPE_SIGNAL = 1; + + // No events are reapplied when workflow is reset. + RESET_REAPPLY_TYPE_NONE = 2; + + // All eligible events are reapplied when workflow is reset. + RESET_REAPPLY_TYPE_ALL_ELIGIBLE = 3; +} + +// Deprecated, see temporal.api.common.v1.ResetOptions. +enum ResetType { + RESET_TYPE_UNSPECIFIED = 0; + + // Resets to event of the first workflow task completed, or if it does not exist, the event after task scheduled. + RESET_TYPE_FIRST_WORKFLOW_TASK = 1; + + // Resets to event of the last workflow task completed, or if it does not exist, the event after task scheduled. + RESET_TYPE_LAST_WORKFLOW_TASK = 2; +} diff --git a/temporal/api/enums/v1/schedule.proto b/temporal/api/enums/v1/schedule.proto new file mode 100644 index 000000000..3334f0607 --- /dev/null +++ b/temporal/api/enums/v1/schedule.proto @@ -0,0 +1,45 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "ScheduleProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// ScheduleOverlapPolicy controls what happens when a workflow would be started +// by a schedule, and is already running. +enum ScheduleOverlapPolicy { + SCHEDULE_OVERLAP_POLICY_UNSPECIFIED = 0; + + // SCHEDULE_OVERLAP_POLICY_SKIP (default) means don't start anything. When the + // workflow completes, the next scheduled event after that time will be considered. + SCHEDULE_OVERLAP_POLICY_SKIP = 1; + + // SCHEDULE_OVERLAP_POLICY_BUFFER_ONE means start the workflow again soon as the + // current one completes, but only buffer one start in this way. If another start is + // supposed to happen when the workflow is running, and one is already buffered, then + // only the first one will be started after the running workflow finishes. + SCHEDULE_OVERLAP_POLICY_BUFFER_ONE = 2; + + // SCHEDULE_OVERLAP_POLICY_BUFFER_ALL means buffer up any number of starts to all + // happen sequentially, immediately after the running workflow completes. + SCHEDULE_OVERLAP_POLICY_BUFFER_ALL = 3; + + // SCHEDULE_OVERLAP_POLICY_CANCEL_OTHER means that if there is another workflow + // running, cancel it, and start the new one after the old one completes cancellation. + SCHEDULE_OVERLAP_POLICY_CANCEL_OTHER = 4; + + // SCHEDULE_OVERLAP_POLICY_TERMINATE_OTHER means that if there is another workflow + // running, terminate it and start the new one immediately. + SCHEDULE_OVERLAP_POLICY_TERMINATE_OTHER = 5; + + // SCHEDULE_OVERLAP_POLICY_ALLOW_ALL means start any number of concurrent workflows. + // Note that with this policy, last completion result and last failure will not be + // available since workflows are not sequential. + SCHEDULE_OVERLAP_POLICY_ALLOW_ALL = 6; +} diff --git a/temporal/api/enums/v1/task_queue.proto b/temporal/api/enums/v1/task_queue.proto new file mode 100644 index 000000000..0cbb72a09 --- /dev/null +++ b/temporal/api/enums/v1/task_queue.proto @@ -0,0 +1,143 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "TaskQueueProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +enum TaskQueueKind { + // Tasks from any non workflow task may be unspecified. + // + // Task queue kind is used to differentiate whether a workflow task queue is sticky or + // normal. If a task is not a workflow task, Task queue kind will sometimes be + // unspecified. + TASK_QUEUE_KIND_UNSPECIFIED = 0; + + // Tasks from a normal workflow task queue always include complete workflow history + // + // The task queue specified by the user is always a normal task queue. There can be as many + // workers as desired for a single normal task queue. All those workers may pick up tasks from + // that queue. + TASK_QUEUE_KIND_NORMAL = 1; + + // A sticky queue only includes new history since the last workflow task, and they are + // per-worker. + // + // Sticky queues are created dynamically by each worker during their start up. They only exist + // for the lifetime of the worker process. Tasks in a sticky task queue are only available to + // the worker that created the sticky queue. + // + // Sticky queues are only for workflow tasks. There are no sticky task queues for activities. + TASK_QUEUE_KIND_STICKY = 2; + + // A worker-commands task queue is used for server-to-worker communication (e.g. activity + // cancellations). These queues are ephemeral and per-worker-process — they exist only for + // the lifetime of the worker process. Used with TASK_QUEUE_TYPE_NEXUS and polled via + // PollNexusTaskQueue. + TASK_QUEUE_KIND_WORKER_COMMANDS = 3; +} + +enum TaskQueueType { + TASK_QUEUE_TYPE_UNSPECIFIED = 0; + + // Workflow type of task queue. + TASK_QUEUE_TYPE_WORKFLOW = 1; + + // Activity type of task queue. + TASK_QUEUE_TYPE_ACTIVITY = 2; + + // Task queue type for dispatching Nexus requests. + TASK_QUEUE_TYPE_NEXUS = 3; +} + +// Specifies which category of tasks may reach a worker on a versioned task queue. +// Used both in a reachability query and its response. +// Deprecated. +enum TaskReachability { + TASK_REACHABILITY_UNSPECIFIED = 0; + + // There's a possiblity for a worker to receive new workflow tasks. Workers should *not* be retired. + TASK_REACHABILITY_NEW_WORKFLOWS = 1; + + // There's a possiblity for a worker to receive existing workflow and activity tasks from existing workflows. Workers + // should *not* be retired. + // This enum value does not distinguish between open and closed workflows. + TASK_REACHABILITY_EXISTING_WORKFLOWS = 2; + + // There's a possiblity for a worker to receive existing workflow and activity tasks from open workflows. Workers + // should *not* be retired. + TASK_REACHABILITY_OPEN_WORKFLOWS = 3; + + // There's a possiblity for a worker to receive existing workflow tasks from closed workflows. Workers may be + // retired dependending on application requirements. For example, if there's no need to query closed workflows. + TASK_REACHABILITY_CLOSED_WORKFLOWS = 4; +} + +// Specifies which category of tasks may reach a versioned worker of a certain Build ID. +// +// Task Reachability is eventually consistent; there may be a delay (up to few minutes) until it +// converges to the most accurate value but it is designed in a way to take the more conservative +// side until it converges. For example REACHABLE is more conservative than CLOSED_WORKFLOWS_ONLY. +// +// Note: future activities who inherit their workflow's Build ID but not its Task Queue will not be +// accounted for reachability as server cannot know if they'll happen as they do not use +// assignment rules of their Task Queue. Same goes for Child Workflows or Continue-As-New Workflows +// who inherit the parent/previous workflow's Build ID but not its Task Queue. In those cases, make +// sure to query reachability for the parent/previous workflow's Task Queue as well. +enum BuildIdTaskReachability { + // Task reachability is not reported + BUILD_ID_TASK_REACHABILITY_UNSPECIFIED = 0; + + // Build ID may be used by new workflows or activities (base on versioning rules), or there MAY + // be open workflows or backlogged activities assigned to it. + BUILD_ID_TASK_REACHABILITY_REACHABLE = 1; + + // Build ID does not have open workflows and is not reachable by new workflows, + // but MAY have closed workflows within the namespace retention period. + // Not applicable to activity-only task queues. + BUILD_ID_TASK_REACHABILITY_CLOSED_WORKFLOWS_ONLY = 2; + + // Build ID is not used for new executions, nor it has been used by any existing execution + // within the retention period. + BUILD_ID_TASK_REACHABILITY_UNREACHABLE = 3; +} + +enum DescribeTaskQueueMode { + // Unspecified means legacy behavior. + DESCRIBE_TASK_QUEUE_MODE_UNSPECIFIED = 0; + + // Enhanced mode reports aggregated results for all partitions, supports Build IDs, and reports richer info. + DESCRIBE_TASK_QUEUE_MODE_ENHANCED = 1; +} + +// Source for the effective rate limit. +enum RateLimitSource { + RATE_LIMIT_SOURCE_UNSPECIFIED = 0; + + // The value was set by the API. + RATE_LIMIT_SOURCE_API = 1; + + // The value was set by a worker. + RATE_LIMIT_SOURCE_WORKER = 2; + + // The value was set as the system default. + RATE_LIMIT_SOURCE_SYSTEM = 3; +} + +// Indicates whether a change to the Routing Config has been +// propagated to all relevant Task Queues and their partitions. +enum RoutingConfigUpdateState { + ROUTING_CONFIG_UPDATE_STATE_UNSPECIFIED = 0; + + // Update to the RoutingConfig is currently in progress. + ROUTING_CONFIG_UPDATE_STATE_IN_PROGRESS = 1; + + // Update to the RoutingConfig has completed successfully. + ROUTING_CONFIG_UPDATE_STATE_COMPLETED = 2; +} diff --git a/temporal/api/enums/v1/time_skipping.proto b/temporal/api/enums/v1/time_skipping.proto new file mode 100644 index 000000000..bb5385313 --- /dev/null +++ b/temporal/api/enums/v1/time_skipping.proto @@ -0,0 +1,35 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "TimeSkippingProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// FastForwardPollingResult is the result of polling and waiting for a fast-forward to complete +// on a time-skipping execution. +// FAST_FORWARD_POLLING_RESULT_POLL_TIMEOUT and FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_COMPLETED +// are the normal poll outcomes; FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_FAILED means the +// fast-forward can no longer complete. +enum FastForwardPollingResult { + // Never returned; guards against an unset result. + FAST_FORWARD_POLLING_RESULT_UNSPECIFIED = 0; + + // The poll timed out server-side before the fast-forward completed. The caller may poll again. + FAST_FORWARD_POLLING_RESULT_POLL_TIMEOUT = 1; + + // The fast-forward identified by the request's `fast_forward_id` reached its target time and completed. + FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_COMPLETED = 2; + + // The fast-forward can no longer complete, which usually indicates improper usage of + // fast-forward on the client side. Possible reasons: the `fast_forward_id` does not match + // the execution's current fast-forward, the execution ended before the fast-forward + // completed, the fast-forward config was updated while the poll was in flight, etc. + // See `failed_reason` in the response for the specific cause. + FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_FAILED = 3; +} diff --git a/temporal/api/enums/v1/update.proto b/temporal/api/enums/v1/update.proto new file mode 100644 index 000000000..a20021d3e --- /dev/null +++ b/temporal/api/enums/v1/update.proto @@ -0,0 +1,51 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "UpdateProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// UpdateWorkflowExecutionLifecycleStage is specified by clients invoking +// Workflow Updates and used to indicate to the server how long the +// client wishes to wait for a return value from the API. If any value other +// than UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED is sent by the +// client then the API will complete before the Update is finished and will +// return a handle to the running Update so that it can later be polled for +// completion. +// If specified stage wasn't reached before server timeout, server returns +// actual stage reached. +enum UpdateWorkflowExecutionLifecycleStage { + // An unspecified value for this enum. + UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_UNSPECIFIED = 0; + + // The API call will not return until the Update request has been admitted + // by the server - it may be the case that due to a considerations like load + // or resource limits that an Update is made to wait before the server will + // indicate that it has been received and will be processed. This value + // does not wait for any sort of acknowledgement from a worker. + UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED = 1; + + // The API call will not return until the Update has passed validation on a worker. + UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED = 2; + + // The API call will not return until the Update has executed to completion + // on a worker and has either been rejected or returned a value or an error. + UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED = 3; +} + +// Records why a WorkflowExecutionUpdateAdmittedEvent was written to history. +// Note that not all admitted Updates result in this event. +enum UpdateAdmittedEventOrigin { + UPDATE_ADMITTED_EVENT_ORIGIN_UNSPECIFIED = 0; + + // The UpdateAdmitted event was created when reapplying events during reset + // or replication. I.e. an accepted Update on one branch of Workflow history + // was converted into an admitted Update on a different branch. + UPDATE_ADMITTED_EVENT_ORIGIN_REAPPLY = 1; +} diff --git a/temporal/api/enums/v1/workflow.proto b/temporal/api/enums/v1/workflow.proto new file mode 100644 index 000000000..4390b033a --- /dev/null +++ b/temporal/api/enums/v1/workflow.proto @@ -0,0 +1,269 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.enums.v1; + +option csharp_namespace = "Temporalio.Api.Enums.V1"; +option go_package = "go.temporal.io/api/enums/v1;enums"; +option java_multiple_files = true; +option java_outer_classname = "WorkflowProto"; +option java_package = "io.temporal.api.enums.v1"; +option ruby_package = "Temporalio::Api::Enums::V1"; + +// Defines whether to allow re-using a workflow id from a previously *closed* workflow. +// If the request is denied, the server returns a `WorkflowExecutionAlreadyStartedFailure` error. +// +// See `WorkflowIdConflictPolicy` for handling workflow id duplication with a *running* workflow. +enum WorkflowIdReusePolicy { + WORKFLOW_ID_REUSE_POLICY_UNSPECIFIED = 0; + + // Allow starting a workflow execution using the same workflow id. + WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE = 1; + + // Allow starting a workflow execution using the same workflow id, only when the last + // execution's final state is one of [terminated, cancelled, timed out, failed]. + WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY = 2; + + // Do not permit re-use of the workflow id for this workflow. Future start workflow requests + // could potentially change the policy, allowing re-use of the workflow id. + WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE = 3; + + // Terminate the current Workflow if one is already running; otherwise allow reusing the + // Workflow ID. When using this option, `WorkflowIdConflictPolicy` must be left unspecified. + // + // Deprecated. Instead, set `WorkflowIdReusePolicy` to `ALLOW_DUPLICATE` and + // `WorkflowIdConflictPolicy` to `TERMINATE_EXISTING`. Note that `WorkflowIdConflictPolicy` + // requires Temporal Server v1.24.0 or later. + WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING = 4 [deprecated = true]; +} + +// Defines what to do when trying to start a workflow with the same workflow id as a *running* workflow. +// Note that it is *never* valid to have two actively running instances of the same workflow id. +// +// See `WorkflowIdReusePolicy` for handling workflow id duplication with a *closed* workflow. +enum WorkflowIdConflictPolicy { + WORKFLOW_ID_CONFLICT_POLICY_UNSPECIFIED = 0; + + // Don't start a new workflow; instead return `WorkflowExecutionAlreadyStartedFailure`. + WORKFLOW_ID_CONFLICT_POLICY_FAIL = 1; + + // Don't start a new workflow; instead return a workflow handle for the running workflow. + WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING = 2; + + // Terminate the running workflow before starting a new one. + WORKFLOW_ID_CONFLICT_POLICY_TERMINATE_EXISTING = 3; +} + +// Defines how child workflows will react to their parent completing +enum ParentClosePolicy { + PARENT_CLOSE_POLICY_UNSPECIFIED = 0; + + // The child workflow will also terminate + PARENT_CLOSE_POLICY_TERMINATE = 1; + + // The child workflow will do nothing + PARENT_CLOSE_POLICY_ABANDON = 2; + + // Cancellation will be requested of the child workflow + PARENT_CLOSE_POLICY_REQUEST_CANCEL = 3; +} + +enum ContinueAsNewInitiator { + CONTINUE_AS_NEW_INITIATOR_UNSPECIFIED = 0; + + // The workflow itself requested to continue as new + CONTINUE_AS_NEW_INITIATOR_WORKFLOW = 1; + + // The workflow continued as new because it is retrying + CONTINUE_AS_NEW_INITIATOR_RETRY = 2; + + // The workflow continued as new because cron has triggered a new execution + CONTINUE_AS_NEW_INITIATOR_CRON_SCHEDULE = 3; +} + +// (-- api-linter: core::0216::synonyms=disabled +// aip.dev/not-precedent: There is WorkflowExecutionState already in another package. --) +enum WorkflowExecutionStatus { + WORKFLOW_EXECUTION_STATUS_UNSPECIFIED = 0; + + // Value 1 is hardcoded in SQL persistence. + WORKFLOW_EXECUTION_STATUS_RUNNING = 1; + + WORKFLOW_EXECUTION_STATUS_COMPLETED = 2; + + WORKFLOW_EXECUTION_STATUS_FAILED = 3; + + WORKFLOW_EXECUTION_STATUS_CANCELED = 4; + + WORKFLOW_EXECUTION_STATUS_TERMINATED = 5; + + WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW = 6; + + WORKFLOW_EXECUTION_STATUS_TIMED_OUT = 7; + + WORKFLOW_EXECUTION_STATUS_PAUSED = 8; +} + +enum PendingActivityState { + PENDING_ACTIVITY_STATE_UNSPECIFIED = 0; + + PENDING_ACTIVITY_STATE_SCHEDULED = 1; + + PENDING_ACTIVITY_STATE_STARTED = 2; + + PENDING_ACTIVITY_STATE_CANCEL_REQUESTED = 3; + + // PAUSED means activity is paused on the server, and is not running in the worker + PENDING_ACTIVITY_STATE_PAUSED = 4; + + // PAUSE_REQUESTED means activity is currently running on the worker, but paused on the server + PENDING_ACTIVITY_STATE_PAUSE_REQUESTED = 5; +} + +enum PendingWorkflowTaskState { + PENDING_WORKFLOW_TASK_STATE_UNSPECIFIED = 0; + + PENDING_WORKFLOW_TASK_STATE_SCHEDULED = 1; + + PENDING_WORKFLOW_TASK_STATE_STARTED = 2; +} + +enum HistoryEventFilterType { + HISTORY_EVENT_FILTER_TYPE_UNSPECIFIED = 0; + + HISTORY_EVENT_FILTER_TYPE_ALL_EVENT = 1; + + HISTORY_EVENT_FILTER_TYPE_CLOSE_EVENT = 2; +} + +enum RetryState { + RETRY_STATE_UNSPECIFIED = 0; + + RETRY_STATE_IN_PROGRESS = 1; + + RETRY_STATE_NON_RETRYABLE_FAILURE = 2; + + RETRY_STATE_TIMEOUT = 3; + + RETRY_STATE_MAXIMUM_ATTEMPTS_REACHED = 4; + + RETRY_STATE_RETRY_POLICY_NOT_SET = 5; + + RETRY_STATE_INTERNAL_SERVER_ERROR = 6; + + RETRY_STATE_CANCEL_REQUESTED = 7; +} + +enum TimeoutType { + TIMEOUT_TYPE_UNSPECIFIED = 0; + + TIMEOUT_TYPE_START_TO_CLOSE = 1; + + TIMEOUT_TYPE_SCHEDULE_TO_START = 2; + + TIMEOUT_TYPE_SCHEDULE_TO_CLOSE = 3; + + TIMEOUT_TYPE_HEARTBEAT = 4; +} + +// Versioning Behavior specifies if and how a workflow execution moves between Worker Deployment +// Versions. The Versioning Behavior of a workflow execution is typically specified by the worker +// who completes the first task of the execution, but is also overridable manually for new and +// existing workflows (see VersioningOverride). +enum VersioningBehavior { + // Workflow execution does not have a Versioning Behavior and is called Unversioned. This is the + // legacy behavior. An Unversioned workflow's task can go to any Unversioned worker (see + // `WorkerVersioningMode`.) + // User needs to use Patching to keep the new code compatible with prior versions when dealing + // with Unversioned workflows. + VERSIONING_BEHAVIOR_UNSPECIFIED = 0; + + // Workflow will start on its Target Version and then will be pinned to that same Deployment + // Version until completion (the Version that this Workflow is pinned to is specified in + // `versioning_info.version` and is the Pinned Version of the Workflow). + // + // The workflow's Target Version is the Current Version of its Task Queue, or, if the + // Task Queue has a Ramping Version with non-zero Ramp Percentage `P`, the workflow's Target + // Version has a P% chance of being the Ramping Version. Whether a workflow falls into the + // Ramping group depends on its Workflow ID and and the Ramp Percentage. + // + // This behavior eliminates most of compatibility concerns users face when changing their code. + // Patching is not needed when pinned workflows code change. + // Can be overridden explicitly via `UpdateWorkflowExecutionOptions` API to move the + // execution to another Deployment Version. + // Activities of `PINNED` workflows are sent to the same Deployment Version. Exception to this + // would be when the activity Task Queue workers are not present in the workflow's Deployment + // Version, in which case the activity will be sent to the Current Deployment Version of its own + // task queue. + VERSIONING_BEHAVIOR_PINNED = 1; + + // Workflow will automatically move to its Target Version when the next workflow task is dispatched. + // + // The workflow's Target Version is the Current Version of its Task Queue, or, if the + // Task Queue has a Ramping Version with non-zero Ramp Percentage `P`, the workflow's Target + // Version has a P% chance of being the Ramping Version. Whether a workflow falls into the + // Ramping group depends on its Workflow ID and and the Ramp Percentage. + // + // AutoUpgrade behavior is suitable for long-running workflows as it allows them to move to the + // latest Deployment Version, but the user still needs to use Patching to keep the new code + // compatible with prior versions for changed workflow types. + // Activities of `AUTO_UPGRADE` workflows are sent to the Deployment Version of the workflow + // execution (as specified in versioning_info.version based on the last completed + // workflow task). Exception to this would be when the activity Task Queue workers are not + // present in the workflow's Deployment Version, in which case, the activity will be sent to a + // different Deployment Version according to the Current or Ramping Deployment Version of its own + // Task Queue. + // Workflows stuck on a backlogged activity will still auto-upgrade if their Target Version + // changes, without having to wait for the backlogged activity to complete on the old Version. + VERSIONING_BEHAVIOR_AUTO_UPGRADE = 2; +} + +// Experimental. Defines the versioning behavior to be used by the first task of a new workflow run in a continue-as-new chain. +enum ContinueAsNewVersioningBehavior { + CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_UNSPECIFIED = 0; + + // Experimental. + // Start the new run with AutoUpgrade behavior. Use the Target Version of the workflow's task queue at + // start-time, as AutoUpgrade workflows do. After the first workflow task completes, use whatever + // Versioning Behavior the workflow is annotated with in the workflow code. + // + // Note that if the workflow being continued has a Pinned override, that override will be inherited by the + // new workflow run regardless of the ContinueAsNewVersioningBehavior specified in the continue-as-new + // command. Versioning Override always takes precedence until it's removed manually via UpdateWorkflowExecutionOptions. + CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_AUTO_UPGRADE = 1; + + // Experimental. + // Use the Ramping Version of the workflow's task queue at start time, regardless of the workflow's + // Target Version (according to f(workflow_id, ramp_percentage)). After the first workflow task completes, + // the workflow will use whatever Versioning Behavior it is annotated with. If there is no Ramping + // Version by the time that the first workflow task is dispatched, it will be sent to the Current Version. + // + // It is highly discouraged to use this if the workflow is annotated with AutoUpgrade behavior, because + // this setting ONLY applies to the first task of the workflow. If, after the first task, the workflow + // is AutoUpgrade, it will behave like a normal AutoUpgrade workflow and go to the Target Version, which + // may be the Current Version instead of the Ramping Version. + // + // Note that if the workflow being continued has a Pinned override, that override will be inherited by the + // new workflow run regardless of the ContinueAsNewVersioningBehavior specified in the continue-as-new + // command. Versioning Override always takes precedence until it's removed manually via UpdateWorkflowExecutionOptions. + CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_USE_RAMPING_VERSION = 2; +} + +// SuggestContinueAsNewReason specifies why SuggestContinueAsNew is true. +enum SuggestContinueAsNewReason { + SUGGEST_CONTINUE_AS_NEW_REASON_UNSPECIFIED = 0; + + // Workflow History size is getting too large. + SUGGEST_CONTINUE_AS_NEW_REASON_HISTORY_SIZE_TOO_LARGE = 1; + + // Workflow History event count is getting too large. + SUGGEST_CONTINUE_AS_NEW_REASON_TOO_MANY_HISTORY_EVENTS = 2; + + // Workflow's count of completed plus in-flight updates is too large. + SUGGEST_CONTINUE_AS_NEW_REASON_TOO_MANY_UPDATES = 3; + + reserved 4; + + reserved "SUGGEST_CONTINUE_AS_NEW_REASON_TARGET_WORKER_DEPLOYMENT_VERSION_CHANGED"; +} diff --git a/temporal/api/errordetails/v1/message.proto b/temporal/api/errordetails/v1/message.proto new file mode 100644 index 000000000..fe0e7e095 --- /dev/null +++ b/temporal/api/errordetails/v1/message.proto @@ -0,0 +1,159 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +// These error details are supplied in google.rpc.Status#details as described in "Google APIs, Error Model" (https://cloud.google.com/apis/design/errors#error_model) +// and extend standard Error Details defined in https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto + +package temporal.api.errordetails.v1; + +import "google/protobuf/any.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/enums/v1/failed_cause.proto"; +import "temporal/api/enums/v1/namespace.proto"; +import "temporal/api/failure/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.ErrorDetails.V1"; +option go_package = "go.temporal.io/api/errordetails/v1;errordetails"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.errordetails.v1"; +option ruby_package = "Temporalio::Api::ErrorDetails::V1"; + +message NotFoundFailure { + string current_cluster = 1; + + string active_cluster = 2; +} + +message WorkflowExecutionAlreadyStartedFailure { + string start_request_id = 1; + + string run_id = 2; + + string first_execution_run_id = 3; +} + +message NamespaceNotActiveFailure { + string namespace = 1; + + string current_cluster = 2; + + string active_cluster = 3; +} + +// NamespaceUnavailableFailure is returned by the service when a request addresses a namespace that is unavailable. For +// example, when a namespace is in the process of failing over between clusters. +// This is a transient error that should be automatically retried by clients. +message NamespaceUnavailableFailure { + string namespace = 1; +} + +message NamespaceInvalidStateFailure { + string namespace = 1; + + // Current state of the requested namespace. + temporal.api.enums.v1.NamespaceState state = 2; + + // Allowed namespace states for requested operation. + // For example NAMESPACE_STATE_DELETED is forbidden for most operations but allowed for DescribeNamespace. + repeated temporal.api.enums.v1.NamespaceState allowed_states = 3; +} + +message NamespaceNotFoundFailure { + string namespace = 1; +} + +message NamespaceAlreadyExistsFailure {} + +message ClientVersionNotSupportedFailure { + string client_version = 1; + + string client_name = 2; + + string supported_versions = 3; +} + +message ServerVersionNotSupportedFailure { + string server_version = 1; + + string client_supported_server_versions = 2; +} + +message CancellationAlreadyRequestedFailure {} + +message QueryFailedFailure { + // The full reason for this query failure. May not be available if the response is generated by an old + // SDK. This field can be encoded by the SDK's failure converter to support E2E encryption of messages and stack + // traces. + temporal.api.failure.v1.Failure failure = 1; +} + +message PermissionDeniedFailure { + string reason = 1; +} + +message ResourceExhaustedFailure { + temporal.api.enums.v1.ResourceExhaustedCause cause = 1; + + temporal.api.enums.v1.ResourceExhaustedScope scope = 2; +} + +message SystemWorkflowFailure { + // WorkflowId and RunId of the Temporal system workflow performing the underlying operation. + // Looking up the info of the system workflow run may help identify the issue causing the failure. + temporal.api.common.v1.WorkflowExecution workflow_execution = 1; + + // Serialized error returned by the system workflow performing the underlying operation. + string workflow_error = 2; +} + +message WorkflowNotReadyFailure {} + +message NewerBuildExistsFailure { + // The current default compatible build ID which will receive tasks + string default_build_id = 1; +} + +message MultiOperationExecutionFailure { + // One status for each requested operation from the failed MultiOperation. The failed + // operation(s) have the same error details as if it was executed separately. All other operations have the + // status code `Aborted` and `MultiOperationExecutionAborted` is added to the details field. + repeated OperationStatus statuses = 1; + + // NOTE: `OperationStatus` is modelled after + // [`google.rpc.Status`](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto). + // + // (-- api-linter: core::0146::any=disabled + // aip.dev/not-precedent: details are meant to hold arbitrary payloads. --) + message OperationStatus { + int32 code = 1; + + string message = 2; + + repeated google.protobuf.Any details = 3; + } +} + +// An error indicating that an activity execution failed to start. Returned when there is an existing activity with the +// given activity ID, and the given ID reuse and conflict policies do not permit starting a new one or attaching to an +// existing one. +message ActivityExecutionAlreadyStartedFailure { + string start_request_id = 1; + + string run_id = 2; +} + +// An error indicating that a Nexus operation failed to start. Returned when there is an existing operation with the +// given operation ID, and the given ID reuse and conflict policies do not permit starting a new one or attaching to an +// existing one. +message NexusOperationExecutionAlreadyStartedFailure { + string start_request_id = 1; + + string run_id = 2; +} + +// An error indicating that the server lost the buffered pages of a paginated workflow task +// completion. This is a transient error: the workflow task is still valid, and the client +// should resend all pages from page 0 using the same task token. +message WorkflowTaskCompletionBufferLostFailure {} diff --git a/temporal/api/export/v1/message.proto b/temporal/api/export/v1/message.proto new file mode 100644 index 000000000..bda614035 --- /dev/null +++ b/temporal/api/export/v1/message.proto @@ -0,0 +1,24 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.export.v1; + +import "temporal/api/history/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Export.V1"; +option go_package = "go.temporal.io/api/export/v1;export"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.export.v1"; +option ruby_package = "Temporalio::Api::Export::V1"; + +message WorkflowExecution { + temporal.api.history.v1.History history = 1; +} + +// WorkflowExecutions is used by the Cloud Export feature to deserialize +// the exported file. It encapsulates a collection of workflow execution information. +message WorkflowExecutions { + repeated WorkflowExecution items = 1; +} diff --git a/temporal/api/failure/v1/message.proto b/temporal/api/failure/v1/message.proto new file mode 100644 index 000000000..e6dea5350 --- /dev/null +++ b/temporal/api/failure/v1/message.proto @@ -0,0 +1,173 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.failure.v1; + +import "google/protobuf/duration.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/enums/v1/common.proto"; +import "temporal/api/enums/v1/nexus.proto"; +import "temporal/api/enums/v1/workflow.proto"; + +option csharp_namespace = "Temporalio.Api.Failure.V1"; +option go_package = "go.temporal.io/api/failure/v1;failure"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.failure.v1"; +option ruby_package = "Temporalio::Api::Failure::V1"; + +message ApplicationFailureInfo { + string type = 1; + + bool non_retryable = 2; + + temporal.api.common.v1.Payloads details = 3; + + // next_retry_delay can be used by the client to override the activity + // retry interval calculated by the retry policy. Retry attempts will + // still be subject to the maximum retries limit and total time limit + // defined by the policy. + google.protobuf.Duration next_retry_delay = 4; + + temporal.api.enums.v1.ApplicationErrorCategory category = 5; +} + +message TimeoutFailureInfo { + temporal.api.enums.v1.TimeoutType timeout_type = 1; + + temporal.api.common.v1.Payloads last_heartbeat_details = 2; +} + +message CanceledFailureInfo { + temporal.api.common.v1.Payloads details = 1; + + // The identity of the worker or client that requested the cancellation. + string identity = 2; +} + +message TerminatedFailureInfo { + // The identity of the worker or client that requested the termination. + string identity = 1; +} + +message ServerFailureInfo { + bool non_retryable = 1; +} + +message ResetWorkflowFailureInfo { + temporal.api.common.v1.Payloads last_heartbeat_details = 1; +} + +message ActivityFailureInfo { + int64 scheduled_event_id = 1; + + int64 started_event_id = 2; + + string identity = 3; + + temporal.api.common.v1.ActivityType activity_type = 4; + + string activity_id = 5; + + temporal.api.enums.v1.RetryState retry_state = 6; +} + +message ChildWorkflowExecutionFailureInfo { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + temporal.api.common.v1.WorkflowType workflow_type = 3; + + int64 initiated_event_id = 4; + + int64 started_event_id = 5; + + temporal.api.enums.v1.RetryState retry_state = 6; +} + +// Representation of the Temporal SDK NexusOperationError object that is returned to workflow callers. +message NexusOperationFailureInfo { + // The NexusOperationScheduled event ID. + int64 scheduled_event_id = 1; + + // Endpoint name. + string endpoint = 2; + + // Service name. + string service = 3; + + // Operation name. + string operation = 4; + + // Operation ID - may be empty if the operation completed synchronously. + // + // Deprecated. Renamed to operation_token. + string operation_id = 5 [deprecated = true]; + + // Operation token - may be empty if the operation completed synchronously. + string operation_token = 6; +} + +message NexusHandlerFailureInfo { + // The Nexus error type as defined in the spec: + // https://github.com/nexus-rpc/api/blob/main/SPEC.md#predefined-handler-errors. + string type = 1; + + // Retry behavior, defaults to the retry behavior of the error type as defined in the spec. + temporal.api.enums.v1.NexusHandlerErrorRetryBehavior retry_behavior = 2; +} + +message Failure { + string message = 1; + + // The source this Failure originated in, e.g. TypeScriptSDK / JavaSDK + // In some SDKs this is used to rehydrate the stack trace into an exception object. + string source = 2; + + string stack_trace = 3; + + // Alternative way to supply `message` and `stack_trace` and possibly other attributes, used for encryption of + // errors originating in user code which might contain sensitive information. + // The `encoded_attributes` Payload could represent any serializable object, e.g. JSON object or a `Failure` proto + // message. + // + // SDK authors: + // - The SDK should provide a default `encodeFailureAttributes` and `decodeFailureAttributes` implementation that: + // - Uses a JSON object to represent `{ message, stack_trace }`. + // - Overwrites the original message with "Encoded failure" to indicate that more information could be extracted. + // - Overwrites the original stack_trace with an empty string. + // - The resulting JSON object is converted to Payload using the default PayloadConverter and should be processed + // by the user-provided PayloadCodec + // + // - If there's demand, we could allow overriding the default SDK implementation to encode other opaque Failure attributes. + // (-- api-linter: core::0203::optional=disabled --) + temporal.api.common.v1.Payload encoded_attributes = 20; + + Failure cause = 4; + + oneof failure_info { + ApplicationFailureInfo application_failure_info = 5; + + TimeoutFailureInfo timeout_failure_info = 6; + + CanceledFailureInfo canceled_failure_info = 7; + + TerminatedFailureInfo terminated_failure_info = 8; + + ServerFailureInfo server_failure_info = 9; + + ResetWorkflowFailureInfo reset_workflow_failure_info = 10; + + ActivityFailureInfo activity_failure_info = 11; + + ChildWorkflowExecutionFailureInfo child_workflow_execution_failure_info = 12; + + NexusOperationFailureInfo nexus_operation_execution_failure_info = 13; + + NexusHandlerFailureInfo nexus_handler_failure_info = 14; + } +} + +message MultiOperationExecutionAborted {} diff --git a/temporal/api/filter/v1/message.proto b/temporal/api/filter/v1/message.proto new file mode 100644 index 000000000..a3dc4c963 --- /dev/null +++ b/temporal/api/filter/v1/message.proto @@ -0,0 +1,35 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.filter.v1; + +import "google/protobuf/timestamp.proto"; +import "temporal/api/enums/v1/workflow.proto"; + +option csharp_namespace = "Temporalio.Api.Filter.V1"; +option go_package = "go.temporal.io/api/filter/v1;filter"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.filter.v1"; +option ruby_package = "Temporalio::Api::Filter::V1"; + +message WorkflowExecutionFilter { + string workflow_id = 1; + + string run_id = 2; +} + +message WorkflowTypeFilter { + string name = 1; +} + +message StartTimeFilter { + google.protobuf.Timestamp earliest_time = 1; + + google.protobuf.Timestamp latest_time = 2; +} + +message StatusFilter { + temporal.api.enums.v1.WorkflowExecutionStatus status = 1; +} diff --git a/temporal/api/history/v1/message.proto b/temporal/api/history/v1/message.proto new file mode 100644 index 000000000..c25f54399 --- /dev/null +++ b/temporal/api/history/v1/message.proto @@ -0,0 +1,1631 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.history.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/deployment/v1/message.proto"; +import "temporal/api/enums/v1/event_type.proto"; +import "temporal/api/enums/v1/failed_cause.proto"; +import "temporal/api/enums/v1/update.proto"; +import "temporal/api/enums/v1/workflow.proto"; +import "temporal/api/failure/v1/message.proto"; +import "temporal/api/sdk/v1/event_group_marker.proto"; +import "temporal/api/sdk/v1/task_complete_metadata.proto"; +import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api/taskqueue/v1/message.proto"; +import "temporal/api/update/v1/message.proto"; +import "temporal/api/workflow/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.History.V1"; +option go_package = "go.temporal.io/api/history/v1;history"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.history.v1"; +option ruby_package = "Temporalio::Api::History::V1"; + +// Always the first event in workflow history +message WorkflowExecutionStartedEventAttributes { + temporal.api.common.v1.WorkflowType workflow_type = 1; + + // If this workflow is a child, the namespace our parent lives in. + // SDKs and UI tools should use `parent_workflow_namespace` field but server must use `parent_workflow_namespace_id` only. + string parent_workflow_namespace = 2; + + string parent_workflow_namespace_id = 27; + + // Contains information about parent workflow execution that initiated the child workflow these attributes belong to. + // If the workflow these attributes belong to is not a child workflow of any other execution, this field will not be populated. + temporal.api.common.v1.WorkflowExecution parent_workflow_execution = 3; + + // EventID of the child execution initiated event in parent workflow + int64 parent_initiated_event_id = 4; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 5; + + // SDK will deserialize this and provide it as arguments to the workflow function + temporal.api.common.v1.Payloads input = 6; + + // Total workflow execution timeout including retries and continue as new. + google.protobuf.Duration workflow_execution_timeout = 7; + + // Timeout of a single workflow run. + google.protobuf.Duration workflow_run_timeout = 8; + + // Timeout of a single workflow task. + google.protobuf.Duration workflow_task_timeout = 9; + + // Run id of the previous workflow which continued-as-new or retried or cron executed into this + // workflow. + string continued_execution_run_id = 10; + + temporal.api.enums.v1.ContinueAsNewInitiator initiator = 11; + + temporal.api.failure.v1.Failure continued_failure = 12; + + temporal.api.common.v1.Payloads last_completion_result = 13; + + // This is the run id when the WorkflowExecutionStarted event was written. + // A workflow reset changes the execution run_id, but preserves this field. + string original_execution_run_id = 14; + + // Identity of the client who requested this execution + string identity = 15; + + // This is the very first runId along the chain of ContinueAsNew, Retry, Cron and Reset. + // Used to identify a chain. + string first_execution_run_id = 16; + + temporal.api.common.v1.RetryPolicy retry_policy = 17; + + // Starting at 1, the number of times we have tried to execute this workflow + int32 attempt = 18; + + // The absolute time at which the workflow will be timed out. + // This is passed without change to the next run/retry of a workflow. + google.protobuf.Timestamp workflow_execution_expiration_time = 19; + + // If this workflow runs on a cron schedule, it will appear here + string cron_schedule = 20; + + // For a cron workflow, this contains the amount of time between when this iteration of + // the cron workflow was scheduled and when it should run next per its cron_schedule. + google.protobuf.Duration first_workflow_task_backoff = 21; + + temporal.api.common.v1.Memo memo = 22; + + temporal.api.common.v1.SearchAttributes search_attributes = 23; + + temporal.api.workflow.v1.ResetPoints prev_auto_reset_points = 24; + + temporal.api.common.v1.Header header = 25; + + // Version of the child execution initiated event in parent workflow + // It should be used together with parent_initiated_event_id to identify + // a child initiated event for global namespace + int64 parent_initiated_event_version = 26; + + // This field is new in 1.21. + string workflow_id = 28; + + // If this workflow intends to use anything other than the current overall default version for + // the queue, then we include it here. + // Deprecated. [cleanup-experimental-wv] + temporal.api.common.v1.WorkerVersionStamp source_version_stamp = 29 [deprecated = true]; + + // Completion callbacks attached when this workflow was started. + repeated temporal.api.common.v1.Callback completion_callbacks = 30; + + // Contains information about the root workflow execution. + // The root workflow execution is defined as follows: + // 1. A workflow without parent workflow is its own root workflow. + // 2. A workflow that has a parent workflow has the same root workflow as its parent workflow. + // When the workflow is its own root workflow, then root_workflow_execution is nil. + // Note: workflows continued as new or reseted may or may not have parents, check examples below. + // + // Examples: + // Scenario 1: Workflow W1 starts child workflow W2, and W2 starts child workflow W3. + // - The root workflow of all three workflows is W1. + // - W1 has root_workflow_execution set to nil. + // - W2 and W3 have root_workflow_execution set to W1. + // Scenario 2: Workflow W1 starts child workflow W2, and W2 continued as new W3. + // - The root workflow of all three workflows is W1. + // - W1 has root_workflow_execution set to nil. + // - W2 and W3 have root_workflow_execution set to W1. + // Scenario 3: Workflow W1 continued as new W2. + // - The root workflow of W1 is W1 and the root workflow of W2 is W2. + // - W1 and W2 have root_workflow_execution set to nil. + // Scenario 4: Workflow W1 starts child workflow W2, and W2 is reseted, creating W3 + // - The root workflow of all three workflows is W1. + // - W1 has root_workflow_execution set to nil. + // - W2 and W3 have root_workflow_execution set to W1. + // Scenario 5: Workflow W1 is reseted, creating W2. + // - The root workflow of W1 is W1 and the root workflow of W2 is W2. + // - W1 and W2 have root_workflow_execution set to nil. + temporal.api.common.v1.WorkflowExecution root_workflow_execution = 31; + + // When present, this execution is assigned to the build ID of its parent or previous execution. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + string inherited_build_id = 32 [deprecated = true]; + + // Versioning override applied to this workflow when it was started. + // Children, crons, retries, and continue-as-new will inherit source run's override if pinned + // and if the new workflow's Task Queue belongs to the override version. + temporal.api.workflow.v1.VersioningOverride versioning_override = 33; + + // When present, it means this is a child workflow of a parent that is Pinned to this Worker + // Deployment Version. In this case, child workflow will start as Pinned to this Version instead + // of starting on the Current Version of its Task Queue. + // This is set only if the child workflow is starting on a Task Queue belonging to the same + // Worker Deployment Version. + // Deprecated. Use `parent_versioning_info`. + string parent_pinned_worker_deployment_version = 34 [deprecated = true]; + + // Priority metadata + temporal.api.common.v1.Priority priority = 35; + + reserved 36; + + reserved "parent_pinned_deployment_version"; + + // If present, the new workflow should start on this version with pinned base behavior. + // Child of pinned parent will inherit the parent's version if the Child's Task Queue belongs to that version. + // + // A new run initiated by workflow ContinueAsNew of pinned run, will inherit the previous run's version if the + // new run's Task Queue belongs to that version. + // + // A new run initiated by workflow Cron will never inherit. + // + // A new run initiated by workflow Retry will only inherit if the retried run is effectively pinned at the time + // of retry, and the retried run inherited a pinned version when it started (ie. it is a child of a pinned + // parent, or a CaN of a pinned run, and is running on a Task Queue in the inherited version). + // + // Pinned override is inherited if Task Queue of new run is compatible with the override version. + // Override is inherited separately and takes precedence over inherited base version. + // + // Note: This field is mutually exclusive with inherited_auto_upgrade_info. + // Additionaly, versioning_override, if present, overrides this field during routing decisions. + temporal.api.deployment.v1.WorkerDeploymentVersion inherited_pinned_version = 37; + + // If present, the new workflow begins with AutoUpgrade behavior. Before dispatching the + // first workflow task, this field is set to the deployment version on which the parent/ + // previous run was operating. This inheritance only happens when the task queues belong to + // the same deployment version. The first workflow task will then be dispatched to either + // this inherited deployment version, or the current deployment version of the task queue's + // Deployment. After the first workflow task, the effective behavior depends on worker-sent + // values in subsequent workflow tasks. + // + // Inheritance rules: + // - ContinueAsNew and child workflows: inherit AutoUpgrade behavior and deployment version + // - Cron: never inherits + // - Retry: inherits only if the retried run is effectively AutoUpgrade at the time of + // retry, and inherited AutoUpgrade behavior when it started (i.e. it is a child of an + // AutoUpgrade parent or ContinueAsNew of an AutoUpgrade run, running on the same + // deployment as the parent/previous run) + // + // Additional notes: + // - This field is mutually exclusive with `inherited_pinned_version`. + // - `versioning_override`, if present, overrides this field during routing decisions. + // - SDK implementations do not interact with this field and is only used internally by + // the server to ensure task routing correctness. + temporal.api.deployment.v1.InheritedAutoUpgradeInfo inherited_auto_upgrade_info = 39; + + // A boolean indicating whether the SDK has asked to eagerly execute the first workflow task for this workflow and + // eager execution was accepted by the server. + // Only populated by server with version >= 1.29.0. + bool eager_execution_accepted = 38; + + // During a previous run of this workflow, the server may have notified the SDK + // that the Target Worker Deployment Version changed, but the SDK declined to + // upgrade (e.g., by continuing-as-new with PINNED behavior). This field records + // the target version that was declined. + // + // This is a wrapper message to distinguish "never declined" (nil wrapper) from + // "declined an unversioned target" (non-nil wrapper with nil deployment_version). + // + // Used internally by the server during continue-as-new and retry. + // Should not be read or interpreted by SDKs. + DeclinedTargetVersionUpgrade declined_target_version_upgrade = 40; + + // Initial time-skipping configuration for this workflow execution, recorded at start time. + // This may have been set explicitly via the start workflow request, or propagated from a + // parent/previous execution. + // + // The configuration may be updated after start via UpdateWorkflowExecutionOptions, which + // will be reflected in the WorkflowExecutionOptionsUpdatedEvent. + temporal.api.common.v1.TimeSkippingConfig time_skipping_config = 41; + + reserved 42; + + reserved "initial_skipped_duration"; + + // The time-skipping state propagated from a previous run of this workflow. This can be nil + // if no time skipping has occurred or there is no previous run. + temporal.api.common.v1.TimeSkippingStatePropagation time_skipping_state_propagation = 43; +} + +// Wrapper for a target deployment version that the SDK declined to upgrade to. +// See declined_target_version_upgrade on WorkflowExecutionStartedEventAttributes. +message DeclinedTargetVersionUpgrade { + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 1; + + // Revision number of the task queue routing config at the time the target + // was declined. If an incoming target's revision is <= this value, it is + // not newer and is not used for deciding whether or not to suppress the + // upgrade signal. + int64 revision_number = 2; +} + +message WorkflowExecutionCompletedEventAttributes { + // Serialized result of workflow completion (ie: The return value of the workflow function) + temporal.api.common.v1.Payloads result = 1; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 2; + + // If another run is started by cron, this contains the new run id. + string new_execution_run_id = 3; +} + +message WorkflowExecutionFailedEventAttributes { + // Serialized result of workflow failure (ex: An exception thrown, or error returned) + temporal.api.failure.v1.Failure failure = 1; + + temporal.api.enums.v1.RetryState retry_state = 2; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 3; + + // If another run is started by cron or retry, this contains the new run id. + string new_execution_run_id = 4; +} + +message WorkflowExecutionTimedOutEventAttributes { + temporal.api.enums.v1.RetryState retry_state = 1; + + // If another run is started by cron or retry, this contains the new run id. + string new_execution_run_id = 2; +} + +message WorkflowExecutionContinuedAsNewEventAttributes { + // The run ID of the new workflow started by this continue-as-new + string new_execution_run_id = 1; + + temporal.api.common.v1.WorkflowType workflow_type = 2; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 3; + + temporal.api.common.v1.Payloads input = 4; + + // Timeout of a single workflow run. + google.protobuf.Duration workflow_run_timeout = 5; + + // Timeout of a single workflow task. + google.protobuf.Duration workflow_task_timeout = 6; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 7; + + // How long the server will wait before scheduling the first workflow task for the new run. + // Used for cron, retry, and other continue-as-new cases that server may enforce some minimal + // delay between new runs for system protection purpose. + google.protobuf.Duration backoff_start_interval = 8; + + temporal.api.enums.v1.ContinueAsNewInitiator initiator = 9; + + // Deprecated. If a workflow's retry policy would cause a new run to start when the current one + // has failed, this field would be populated with that failure. Now (when supported by server + // and sdk) the final event will be `WORKFLOW_EXECUTION_FAILED` with `new_execution_run_id` set. + temporal.api.failure.v1.Failure failure = 10 [deprecated = true]; + + // The result from the most recent completed run of this workflow. The SDK surfaces this to the + // new run via APIs such as `GetLastCompletionResult`. + temporal.api.common.v1.Payloads last_completion_result = 11; + + temporal.api.common.v1.Header header = 12; + + temporal.api.common.v1.Memo memo = 13; + + temporal.api.common.v1.SearchAttributes search_attributes = 14; + + // If this is set, the new execution inherits the Build ID of the current execution. Otherwise, + // the assignment rules will be used to independently assign a Build ID to the new execution. + // Deprecated. Only considered for versioning v0.2. + bool inherit_build_id = 15 [deprecated = true]; + + // Experimental. Optionally decide the versioning behavior that the first task of the new run should use. + // For example, choose to AutoUpgrade on continue-as-new instead of inheriting the pinned version + // of the previous run. + temporal.api.enums.v1.ContinueAsNewVersioningBehavior initial_versioning_behavior = 16; +} + +message WorkflowTaskScheduledEventAttributes { + // The task queue this workflow task was enqueued in, which could be a normal or sticky queue + temporal.api.taskqueue.v1.TaskQueue task_queue = 1; + + // How long the worker has to process this task once receiving it before it times out + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 2; + + // Starting at 1, how many attempts there have been to complete this task + int32 attempt = 3; +} + +message WorkflowTaskStartedEventAttributes { + // The id of the `WORKFLOW_TASK_SCHEDULED` event this task corresponds to + int64 scheduled_event_id = 1; + + // Identity of the worker who picked up this task + string identity = 2; + + // This field is populated from the RecordWorkflowTaskStartedRequest. Matching service would + // set the request_id on the RecordWorkflowTaskStartedRequest to a new UUID. This is useful + // in case a RecordWorkflowTaskStarted call succeed but matching doesn't get that response, + // so matching could retry and history service would return success if the request_id matches. + // In that case, matching will continue to deliver the task to worker. Without this field, history + // service would return AlreadyStarted error, and matching would drop the task. + string request_id = 3; + + // True if this workflow should continue-as-new soon. See `suggest_continue_as_new_reasons` for why. + bool suggest_continue_as_new = 4; + + // The reason(s) that suggest_continue_as_new is true, if it is. + // Unset if suggest_continue_as_new is false. + repeated temporal.api.enums.v1.SuggestContinueAsNewReason suggest_continue_as_new_reasons = 8; + + // True if Workflow's Target Worker Deployment Version is different from its Pinned Version and + // the workflow is Pinned. + // Experimental. + bool target_worker_deployment_version_changed = 9; + + // Total history size in bytes, which the workflow might use to decide when to + // continue-as-new regardless of the suggestion. Note that history event count is + // just the event id of this event, so we don't include it explicitly here. + int64 history_size_bytes = 5; + + // Version info of the worker to whom this task was dispatched. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + temporal.api.common.v1.WorkerVersionStamp worker_version = 6 [deprecated = true]; + + // Used by server internally to properly reapply build ID redirects to an execution + // when rebuilding it from events. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + int64 build_id_redirect_counter = 7 [deprecated = true]; +} + +message WorkflowTaskCompletedEventAttributes { + // The id of the `WORKFLOW_TASK_SCHEDULED` event this task corresponds to + int64 scheduled_event_id = 1; + + // The id of the `WORKFLOW_TASK_STARTED` event this task corresponds to + int64 started_event_id = 2; + + // Identity of the worker who completed this task + string identity = 3; + + // Binary ID of the worker who completed this task + // Deprecated. Replaced with `deployment_version`. + string binary_checksum = 4 [deprecated = true]; + + // Version info of the worker who processed this workflow task. If present, the `build_id` field + // within is also used as `binary_checksum`, which may be omitted in that case (it may also be + // populated to preserve compatibility). + // Deprecated. Use `deployment_version` and `versioning_behavior` instead. + temporal.api.common.v1.WorkerVersionStamp worker_version = 5 [deprecated = true]; + + // Data the SDK wishes to record for itself, but server need not interpret, and does not + // directly impact workflow state. + temporal.api.sdk.v1.WorkflowTaskCompletedMetadata sdk_metadata = 6; + + // Local usage data sent during workflow task completion and recorded here for posterity + temporal.api.common.v1.MeteringMetadata metering_metadata = 13; + + // The deployment that completed this task. May or may not be set for unversioned workers, + // depending on whether a value is sent by the SDK. This value updates workflow execution's + // `versioning_info.deployment`. + // Deprecated. Replaced with `deployment_version`. + temporal.api.deployment.v1.Deployment deployment = 7 [deprecated = true]; + + // Versioning behavior sent by the worker that completed this task for this particular workflow + // execution. UNSPECIFIED means the task was completed by an unversioned worker. This value + // updates workflow execution's `versioning_info.behavior`. + temporal.api.enums.v1.VersioningBehavior versioning_behavior = 8; + + // The Worker Deployment Version that completed this task. Must be set if `versioning_behavior` + // is set. This value updates workflow execution's `versioning_info.version`. + // Deprecated. Replaced with `deployment_version`. + string worker_deployment_version = 9 [deprecated = true]; + + // The name of Worker Deployment that completed this task. Must be set if `versioning_behavior` + // is set. This value updates workflow execution's `worker_deployment_name`. + string worker_deployment_name = 10; + + // The Worker Deployment Version that completed this task. Must be set if `versioning_behavior` + // is set. This value updates workflow execution's `versioning_info.deployment_version`. + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 11; +} + +message WorkflowTaskTimedOutEventAttributes { + // The id of the `WORKFLOW_TASK_SCHEDULED` event this task corresponds to + int64 scheduled_event_id = 1; + + // The id of the `WORKFLOW_TASK_STARTED` event this task corresponds to + int64 started_event_id = 2; + + temporal.api.enums.v1.TimeoutType timeout_type = 3; +} + +message WorkflowTaskFailedEventAttributes { + // The id of the `WORKFLOW_TASK_SCHEDULED` event this task corresponds to + int64 scheduled_event_id = 1; + + // The id of the `WORKFLOW_TASK_STARTED` event this task corresponds to + int64 started_event_id = 2; + + temporal.api.enums.v1.WorkflowTaskFailedCause cause = 3; + + // The failure details + temporal.api.failure.v1.Failure failure = 4; + + // If a worker explicitly failed this task, this field contains the worker's identity. + // When the server generates the failure internally this field is set as 'history-service'. + string identity = 5; + + // The original run id of the workflow. For reset workflow. + string base_run_id = 6; + + // If the workflow is being reset, the new run id. + string new_run_id = 7; + + // Version of the event where the history branch was forked. Used by multi-cluster replication + // during resets to identify the correct history branch. + int64 fork_event_version = 8; + + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + // If a worker explicitly failed this task, its binary id + string binary_checksum = 9 [deprecated = true]; + + // Version info of the worker who processed this workflow task. If present, the `build_id` field + // within is also used as `binary_checksum`, which may be omitted in that case (it may also be + // populated to preserve compatibility). + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + temporal.api.common.v1.WorkerVersionStamp worker_version = 10 [deprecated = true]; +} + +message ActivityTaskScheduledEventAttributes { + // The worker/user assigned identifier for the activity + string activity_id = 1; + + temporal.api.common.v1.ActivityType activity_type = 2; + + reserved 3; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 4; + + temporal.api.common.v1.Header header = 5; + + temporal.api.common.v1.Payloads input = 6; + + // Indicates how long the caller is willing to wait for an activity completion. Limits how long + // retries will be attempted. Either this or `start_to_close_timeout` must be specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 7; + + // Limits time an activity task can stay in a task queue before a worker picks it up. This + // timeout is always non retryable, as all a retry would achieve is to put it back into the same + // queue. Defaults to `schedule_to_close_timeout` or workflow execution timeout if not + // specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 8; + + // Maximum time an activity is allowed to execute after being picked up by a worker. This + // timeout is always retryable. Either this or `schedule_to_close_timeout` must be + // specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 9; + + // Maximum permitted time between successful worker heartbeats. + google.protobuf.Duration heartbeat_timeout = 10; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 11; + + // Activities are assigned a default retry policy controlled by the service's dynamic + // configuration. Retries will happen up to `schedule_to_close_timeout`. To disable retries set + // retry_policy.maximum_attempts to 1. + temporal.api.common.v1.RetryPolicy retry_policy = 12; + + // If this is set, the activity would be assigned to the Build ID of the workflow. Otherwise, + // Assignment rules of the activity's Task Queue will be used to determine the Build ID. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + bool use_workflow_build_id = 13 [deprecated = true]; + + // Priority metadata. If this message is not present, or any fields are not + // present, they inherit the values from the workflow. + temporal.api.common.v1.Priority priority = 14; +} + +message ActivityTaskStartedEventAttributes { + // The id of the `ACTIVITY_TASK_SCHEDULED` event this task corresponds to + int64 scheduled_event_id = 1; + + // id of the worker that picked up this task + string identity = 2; + + // This field is populated from the RecordActivityTaskStartedRequest. Matching service would + // set the request_id on the RecordActivityTaskStartedRequest to a new UUID. This is useful + // in case a RecordActivityTaskStarted call succeed but matching doesn't get that response, + // so matching could retry and history service would return success if the request_id matches. + // In that case, matching will continue to deliver the task to worker. Without this field, history + // service would return AlreadyStarted error, and matching would drop the task. + string request_id = 3; + + // Starting at 1, the number of times this task has been attempted + int32 attempt = 4; + + // Will be set to the most recent failure details, if this task has previously failed and then + // been retried. + temporal.api.failure.v1.Failure last_failure = 5; + + // Version info of the worker to whom this task was dispatched. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + temporal.api.common.v1.WorkerVersionStamp worker_version = 6 [deprecated = true]; + + // Used by server internally to properly reapply build ID redirects to an execution + // when rebuilding it from events. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + int64 build_id_redirect_counter = 7 [deprecated = true]; +} + +message ActivityTaskCompletedEventAttributes { + // Serialized results of the activity. IE: The return value of the activity function + temporal.api.common.v1.Payloads result = 1; + + // The id of the `ACTIVITY_TASK_SCHEDULED` event this completion corresponds to + int64 scheduled_event_id = 2; + + // The id of the `ACTIVITY_TASK_STARTED` event this completion corresponds to + int64 started_event_id = 3; + + // id of the worker that completed this task + string identity = 4; + + // Version info of the worker who processed this workflow task. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + temporal.api.common.v1.WorkerVersionStamp worker_version = 5 [deprecated = true]; +} + +message ActivityTaskFailedEventAttributes { + // Failure details + temporal.api.failure.v1.Failure failure = 1; + + // The id of the `ACTIVITY_TASK_SCHEDULED` event this failure corresponds to + int64 scheduled_event_id = 2; + + // The id of the `ACTIVITY_TASK_STARTED` event this failure corresponds to + int64 started_event_id = 3; + + // id of the worker that failed this task + string identity = 4; + + temporal.api.enums.v1.RetryState retry_state = 5; + + // Version info of the worker who processed this workflow task. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + temporal.api.common.v1.WorkerVersionStamp worker_version = 6 [deprecated = true]; +} + +message ActivityTaskTimedOutEventAttributes { + // If this activity had failed, was retried, and then timed out, that failure is stored as the + // `cause` in here. + temporal.api.failure.v1.Failure failure = 1; + + // The id of the `ACTIVITY_TASK_SCHEDULED` event this timeout corresponds to + int64 scheduled_event_id = 2; + + // The id of the `ACTIVITY_TASK_STARTED` event this timeout corresponds to + int64 started_event_id = 3; + + temporal.api.enums.v1.RetryState retry_state = 4; +} + +message ActivityTaskCancelRequestedEventAttributes { + // The id of the `ACTIVITY_TASK_SCHEDULED` event this cancel request corresponds to + int64 scheduled_event_id = 1; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 2; +} + +message ActivityTaskCanceledEventAttributes { + // Additional information that the activity reported upon confirming cancellation + temporal.api.common.v1.Payloads details = 1; + + // id of the most recent `ACTIVITY_TASK_CANCEL_REQUESTED` event which refers to the same + // activity + int64 latest_cancel_requested_event_id = 2; + + // The id of the `ACTIVITY_TASK_SCHEDULED` event this cancel confirmation corresponds to + int64 scheduled_event_id = 3; + + // The id of the `ACTIVITY_TASK_STARTED` event this cancel confirmation corresponds to + int64 started_event_id = 4; + + // id of the worker who canceled this activity + string identity = 5; + + // Version info of the worker who processed this workflow task. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + temporal.api.common.v1.WorkerVersionStamp worker_version = 6 [deprecated = true]; +} + +message TimerStartedEventAttributes { + // The worker/user assigned id for this timer + string timer_id = 1; + + // How long until this timer fires + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_fire_timeout = 2; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 3; +} + +message TimerFiredEventAttributes { + // Will match the `timer_id` from `TIMER_STARTED` event for this timer + string timer_id = 1; + + // The id of the `TIMER_STARTED` event itself + int64 started_event_id = 2; +} + +message TimerCanceledEventAttributes { + // Will match the `timer_id` from `TIMER_STARTED` event for this timer + string timer_id = 1; + + // The id of the `TIMER_STARTED` event itself + int64 started_event_id = 2; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 3; + + // The id of the worker who requested this cancel + string identity = 4; +} + +message WorkflowExecutionCancelRequestedEventAttributes { + // User provided reason for requesting cancellation + string cause = 1; + + // The ID of the `REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED` event in the external + // workflow history when the cancellation was requested by another workflow. + int64 external_initiated_event_id = 2; + + temporal.api.common.v1.WorkflowExecution external_workflow_execution = 3; + + // id of the worker or client who requested this cancel + string identity = 4; +} + +message WorkflowExecutionCanceledEventAttributes { + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 1; + + temporal.api.common.v1.Payloads details = 2; +} + +message MarkerRecordedEventAttributes { + // Workers use this to identify the "types" of various markers. Ex: Local activity, side effect. + string marker_name = 1; + + // Serialized information recorded in the marker + map details = 2; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 3; + + temporal.api.common.v1.Header header = 4; + + // Some uses of markers, like a local activity, could "fail". If they did that is recorded here. + temporal.api.failure.v1.Failure failure = 5; +} + +message WorkflowExecutionSignaledEventAttributes { + // The name/type of the signal to fire + string signal_name = 1; + + // Will be deserialized and provided as argument(s) to the signal handler + temporal.api.common.v1.Payloads input = 2; + + // id of the worker/client who sent this signal + string identity = 3; + + // Headers that were passed by the sender of the signal and copied by temporal + // server into the workflow task. + temporal.api.common.v1.Header header = 4; + + // Deprecated. This field is never respected and should always be set to false. + bool skip_generate_workflow_task = 5 [deprecated = true]; + + // When signal origin is a workflow execution, this field is set. + temporal.api.common.v1.WorkflowExecution external_workflow_execution = 6; + + // The request ID of the Signal request, used by the server to attach this to + // the correct Event ID when generating link. + string request_id = 7; +} + +message WorkflowExecutionTerminatedEventAttributes { + // User/client provided reason for termination + string reason = 1; + + temporal.api.common.v1.Payloads details = 2; + + // id of the client who requested termination + string identity = 3; +} + +message RequestCancelExternalWorkflowExecutionInitiatedEventAttributes { + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 1; + + // The namespace the workflow to be cancelled lives in. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 2; + + string namespace_id = 7; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 3; + + // Deprecated. + string control = 4 [deprecated = true]; + + // Workers are expected to set this to true if the workflow they are requesting to cancel is + // a child of the workflow which issued the request + bool child_workflow_only = 5; + + // Reason for requesting the cancellation + string reason = 6; +} + +message RequestCancelExternalWorkflowExecutionFailedEventAttributes { + temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause cause = 1; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 2; + + // Namespace of the workflow which failed to cancel. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 3; + + string namespace_id = 7; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 4; + + // id of the `REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED` event this failure + // corresponds to + int64 initiated_event_id = 5; + + // Deprecated. + string control = 6 [deprecated = true]; +} + +message ExternalWorkflowExecutionCancelRequestedEventAttributes { + // id of the `REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED` event this event corresponds + // to + int64 initiated_event_id = 1; + + // Namespace of the to-be-cancelled workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 2; + + string namespace_id = 4; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 3; +} + +message SignalExternalWorkflowExecutionInitiatedEventAttributes { + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 1; + + // Namespace of the to-be-signalled workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 2; + + string namespace_id = 9; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 3; + + // name/type of the signal to fire in the external workflow + string signal_name = 4; + + // Serialized arguments to provide to the signal handler + temporal.api.common.v1.Payloads input = 5; + + // Deprecated. + string control = 6 [deprecated = true]; + + // Workers are expected to set this to true if the workflow they are requesting to cancel is + // a child of the workflow which issued the request + bool child_workflow_only = 7; + + temporal.api.common.v1.Header header = 8; +} + +message SignalExternalWorkflowExecutionFailedEventAttributes { + temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause cause = 1; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 2; + + // Namespace of the workflow which failed the signal. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 3; + + string namespace_id = 7; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 4; + + int64 initiated_event_id = 5; + + // Deprecated. + string control = 6 [deprecated = true]; +} + +message ExternalWorkflowExecutionSignaledEventAttributes { + // id of the `SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED` event this event corresponds to + int64 initiated_event_id = 1; + + // Namespace of the workflow which was signaled. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 2; + + string namespace_id = 5; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 3; + + // Deprecated. + string control = 4 [deprecated = true]; +} + +message UpsertWorkflowSearchAttributesEventAttributes { + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 1; + + temporal.api.common.v1.SearchAttributes search_attributes = 2; +} + +message WorkflowPropertiesModifiedEventAttributes { + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 1; + + // If set, update the workflow memo with the provided values. The values will be merged with + // the existing memo. If the user wants to delete values, a default/empty Payload should be + // used as the value for the key being deleted. + temporal.api.common.v1.Memo upserted_memo = 2; +} + +message StartChildWorkflowExecutionInitiatedEventAttributes { + // Namespace of the child workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 1; + + string namespace_id = 18; + + string workflow_id = 2; + + temporal.api.common.v1.WorkflowType workflow_type = 3; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 4; + + temporal.api.common.v1.Payloads input = 5; + + // Total workflow execution timeout including retries and continue as new. + google.protobuf.Duration workflow_execution_timeout = 6; + + // Timeout of a single workflow run. + google.protobuf.Duration workflow_run_timeout = 7; + + // Timeout of a single workflow task. + google.protobuf.Duration workflow_task_timeout = 8; + + // Default: PARENT_CLOSE_POLICY_TERMINATE. + temporal.api.enums.v1.ParentClosePolicy parent_close_policy = 9; + + // Deprecated. + string control = 10 [deprecated = true]; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 11; + + // Default: WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE. + temporal.api.enums.v1.WorkflowIdReusePolicy workflow_id_reuse_policy = 12; + + temporal.api.common.v1.RetryPolicy retry_policy = 13; + + // If this child runs on a cron schedule, it will appear here + string cron_schedule = 14; + + temporal.api.common.v1.Header header = 15; + + temporal.api.common.v1.Memo memo = 16; + + temporal.api.common.v1.SearchAttributes search_attributes = 17; + + // If this is set, the child workflow inherits the Build ID of the parent. Otherwise, the assignment + // rules of the child's Task Queue will be used to independently assign a Build ID to it. + // Deprecated. Only considered for versioning v0.2. + bool inherit_build_id = 19 [deprecated = true]; + + // Priority metadata + temporal.api.common.v1.Priority priority = 20; + + // The propagated time-skipping configuration for the child workflow. + temporal.api.common.v1.TimeSkippingConfig time_skipping_config = 21; + + reserved 22; + + reserved "initial_skipped_duration"; + + // The time-skipping state propagated from the parent workflow. This can be nil if no time skipping + // has occurred or there is no previous run. + temporal.api.common.v1.TimeSkippingStatePropagation time_skipping_state_propagation = 23; + + // Versioning override requested for the child workflow. If present, this explicit override + // takes precedence over versioning behavior inherited from the parent workflow. + temporal.api.workflow.v1.VersioningOverride versioning_override = 24; +} + +message StartChildWorkflowExecutionFailedEventAttributes { + // Namespace of the child workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 1; + + string namespace_id = 8; + + string workflow_id = 2; + + temporal.api.common.v1.WorkflowType workflow_type = 3; + + temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause cause = 4; + + // Deprecated. + string control = 5 [deprecated = true]; + + // Id of the `START_CHILD_WORKFLOW_EXECUTION_INITIATED` event which this event corresponds to + int64 initiated_event_id = 6; + + // The `WORKFLOW_TASK_COMPLETED` event which this command was reported with + int64 workflow_task_completed_event_id = 7; +} + +message ChildWorkflowExecutionStartedEventAttributes { + // Namespace of the child workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 1; + + string namespace_id = 6; + + // Id of the `START_CHILD_WORKFLOW_EXECUTION_INITIATED` event which this event corresponds to + int64 initiated_event_id = 2; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 3; + + temporal.api.common.v1.WorkflowType workflow_type = 4; + + temporal.api.common.v1.Header header = 5; +} + +message ChildWorkflowExecutionCompletedEventAttributes { + temporal.api.common.v1.Payloads result = 1; + + // Namespace of the child workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 2; + + string namespace_id = 7; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 3; + + temporal.api.common.v1.WorkflowType workflow_type = 4; + + // Id of the `START_CHILD_WORKFLOW_EXECUTION_INITIATED` event which this event corresponds to + int64 initiated_event_id = 5; + + // Id of the `CHILD_WORKFLOW_EXECUTION_STARTED` event which this event corresponds to + int64 started_event_id = 6; +} + +message ChildWorkflowExecutionFailedEventAttributes { + temporal.api.failure.v1.Failure failure = 1; + + // Namespace of the child workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 2; + + string namespace_id = 8; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 3; + + temporal.api.common.v1.WorkflowType workflow_type = 4; + + // Id of the `START_CHILD_WORKFLOW_EXECUTION_INITIATED` event which this event corresponds to + int64 initiated_event_id = 5; + + // Id of the `CHILD_WORKFLOW_EXECUTION_STARTED` event which this event corresponds to + int64 started_event_id = 6; + + temporal.api.enums.v1.RetryState retry_state = 7; +} + +message ChildWorkflowExecutionCanceledEventAttributes { + temporal.api.common.v1.Payloads details = 1; + + // Namespace of the child workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 2; + + string namespace_id = 7; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 3; + + temporal.api.common.v1.WorkflowType workflow_type = 4; + + // Id of the `START_CHILD_WORKFLOW_EXECUTION_INITIATED` event which this event corresponds to + int64 initiated_event_id = 5; + + // Id of the `CHILD_WORKFLOW_EXECUTION_STARTED` event which this event corresponds to + int64 started_event_id = 6; +} + +message ChildWorkflowExecutionTimedOutEventAttributes { + // Namespace of the child workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 1; + + string namespace_id = 7; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + temporal.api.common.v1.WorkflowType workflow_type = 3; + + // Id of the `START_CHILD_WORKFLOW_EXECUTION_INITIATED` event which this event corresponds to + int64 initiated_event_id = 4; + + // Id of the `CHILD_WORKFLOW_EXECUTION_STARTED` event which this event corresponds to + int64 started_event_id = 5; + + temporal.api.enums.v1.RetryState retry_state = 6; +} + +message ChildWorkflowExecutionTerminatedEventAttributes { + // Namespace of the child workflow. + // SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. + string namespace = 1; + + string namespace_id = 6; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + temporal.api.common.v1.WorkflowType workflow_type = 3; + + // Id of the `START_CHILD_WORKFLOW_EXECUTION_INITIATED` event which this event corresponds to + int64 initiated_event_id = 4; + + // Id of the `CHILD_WORKFLOW_EXECUTION_STARTED` event which this event corresponds to + int64 started_event_id = 5; +} + +message WorkflowExecutionOptionsUpdatedEventAttributes { + message WorkflowUpdateOptionsUpdate { + // The ID of the workflow update this update options update corresponds to. + string update_id = 1; + + // Request ID attached to the running workflow update so that subsequent requests with same + // request ID will be deduped + string attached_request_id = 2; + + // Completion callbacks attached to the running workflow update. + repeated temporal.api.common.v1.Callback attached_completion_callbacks = 3; + } + + // Versioning override upserted in this event. + // Ignored if nil or if unset_versioning_override is true. + temporal.api.workflow.v1.VersioningOverride versioning_override = 1; + + // Versioning override removed in this event. + bool unset_versioning_override = 2; + + // Request ID attached to the running workflow execution so that subsequent requests with same + // request ID will be deduped. + string attached_request_id = 3; + + // Completion callbacks attached to the running workflow execution. + repeated temporal.api.common.v1.Callback attached_completion_callbacks = 4; + + // Optional. The identity of the client who initiated the request that created this event. + string identity = 5; + + // Priority override upserted in this event. Represents the full priority; not just partial fields. + // Ignored if nil. + temporal.api.common.v1.Priority priority = 6; + + // TimeSkippingConfig override upserted in this event. Represents the full config. + temporal.api.common.v1.TimeSkippingConfig time_skipping_config = 7; + + // Indicates the time skipping config was updated by the recent call to update + // workflow execution options. + bool time_skipping_config_updated = 9; + + // Updates to workflow updates options. + repeated WorkflowUpdateOptionsUpdate workflow_update_options = 8; +} + +// Not used anywhere. Use case is replaced by WorkflowExecutionOptionsUpdatedEventAttributes +message WorkflowPropertiesModifiedExternallyEventAttributes { + // Not used. + string new_task_queue = 1; + + // Not used. + google.protobuf.Duration new_workflow_task_timeout = 2; + + // Not used. + google.protobuf.Duration new_workflow_run_timeout = 3; + + // Not used. + google.protobuf.Duration new_workflow_execution_timeout = 4; + + // Not used. + temporal.api.common.v1.Memo upserted_memo = 5; +} + +message ActivityPropertiesModifiedExternallyEventAttributes { + // The id of the `ACTIVITY_TASK_SCHEDULED` event this modification corresponds to. + int64 scheduled_event_id = 1; + + // If set, update the retry policy of the activity, replacing it with the specified one. + // The number of attempts at the activity is preserved. + temporal.api.common.v1.RetryPolicy new_retry_policy = 2; +} + +message WorkflowExecutionUpdateAcceptedEventAttributes { + // The instance ID of the update protocol that generated this event. + string protocol_instance_id = 1; + + // The message ID of the original request message that initiated this + // update. Needed so that the worker can recreate and deliver that same + // message as part of replay. + string accepted_request_message_id = 2; + + // The event ID used to sequence the original request message. + int64 accepted_request_sequencing_event_id = 3; + + // The message payload of the original request message that initiated this + // update. + temporal.api.update.v1.Request accepted_request = 4; +} + +message WorkflowExecutionUpdateCompletedEventAttributes { + // The metadata about this update. + temporal.api.update.v1.Meta meta = 1; + + // The event ID indicating the acceptance of this update. + int64 accepted_event_id = 3; + + // The outcome of executing the workflow update function. + temporal.api.update.v1.Outcome outcome = 2; +} + +message WorkflowExecutionUpdateRejectedEventAttributes { + // The instance ID of the update protocol that generated this event. + string protocol_instance_id = 1; + + // The message ID of the original request message that initiated this + // update. Needed so that the worker can recreate and deliver that same + // message as part of replay. + string rejected_request_message_id = 2; + + // The event ID used to sequence the original request message. + int64 rejected_request_sequencing_event_id = 3; + + // The message payload of the original request message that initiated this + // update. + temporal.api.update.v1.Request rejected_request = 4; + + // The cause of rejection. + temporal.api.failure.v1.Failure failure = 5; +} + +message WorkflowExecutionUpdateAdmittedEventAttributes { + // The update request associated with this event. + temporal.api.update.v1.Request request = 1; + + // An explanation of why this event was written to history. + temporal.api.enums.v1.UpdateAdmittedEventOrigin origin = 2; +} + +// Attributes for an event marking that a workflow execution was paused. +message WorkflowExecutionPausedEventAttributes { + // The identity of the client who paused the workflow execution. + string identity = 1; + + // The reason for pausing the workflow execution. + string reason = 2; + + // The request ID of the request that paused the workflow execution. + string request_id = 3; +} + +// Attributes for an event marking that a workflow execution was unpaused. +message WorkflowExecutionUnpausedEventAttributes { + // The identity of the client who unpaused the workflow execution. + string identity = 1; + + // The reason for unpausing the workflow execution. + string reason = 2; + + // The request ID of the request that unpaused the workflow execution. + string request_id = 3; +} + +// Attributes for an event indicating that time skipping state changed for a workflow execution: +// either time was advanced, or time skipping was stopped automatically due to the fast_forward completing. +// The worker_may_ignore field in HistoryEvent should always be set true for this event. +message WorkflowExecutionTimeSkippingTransitionedEventAttributes { + // The virtual time point that time skipping advanced to. + google.protobuf.Timestamp target_time = 1; + + // When true, time skipping has been stopped automatically due to a call to fast_forward completing. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "after" is used to indicate temporal ordering. --) + bool disabled_after_fast_forward = 2; + + // The wall-clock time when the time-skipping state changed event was generated. + google.protobuf.Timestamp wall_clock_time = 3; +} + +// Event marking that an operation was scheduled by a workflow via the ScheduleNexusOperation command. +message NexusOperationScheduledEventAttributes { + // Endpoint name, must exist in the endpoint registry. + string endpoint = 1; + + // Service name. + string service = 2; + + // Operation name. + string operation = 3; + + // Input for the operation. The server converts this into Nexus request content and the appropriate content headers + // internally when sending the StartOperation request. On the handler side, if it is also backed by Temporal, the + // content is transformed back to the original Payload stored in this event. + temporal.api.common.v1.Payload input = 4; + + // Schedule-to-close timeout for this operation. + // Indicates how long the caller is willing to wait for operation completion. + // Calls are retried internally by the server. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + // (-- api-linter: core::0142::time-field-names=disabled + // aip.dev/not-precedent: "timeout" is an acceptable suffix for duration fields in this API. --) + google.protobuf.Duration schedule_to_close_timeout = 5; + + // Header to attach to the Nexus request. Note these headers are not the same as Temporal headers on internal + // activities and child workflows, these are transmitted to Nexus operations that may be external and are not + // traditional payloads. + map nexus_header = 6; + + // The `WORKFLOW_TASK_COMPLETED` event that the corresponding ScheduleNexusOperation command was reported with. + int64 workflow_task_completed_event_id = 7; + + // A unique ID generated by the history service upon creation of this event. + // The ID will be transmitted with all nexus StartOperation requests and is used as an idempotentency key. + string request_id = 8; + + // Endpoint ID as resolved in the endpoint registry at the time this event was generated. + // This is stored on the event and used internally by the server in case the endpoint is renamed from the time the + // event was originally scheduled. + string endpoint_id = 9; + + // Schedule-to-start timeout for this operation. + // See ScheduleNexusOperationCommandAttributes.schedule_to_start_timeout for details. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 10; + + // Start-to-close timeout for this operation. + // See ScheduleNexusOperationCommandAttributes.start_to_close_timeout for details. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 11; +} + +// Event marking an asynchronous operation was started by the responding Nexus handler. +// If the operation completes synchronously, this event is not generated. +// In rare situations, such as request timeouts, the service may fail to record the actual start time and will fabricate +// this event upon receiving the operation completion via callback. +message NexusOperationStartedEventAttributes { + // The ID of the `NEXUS_OPERATION_SCHEDULED` event this task corresponds to. + int64 scheduled_event_id = 1; + + // The operation ID returned by the Nexus handler in the response to the StartOperation request. + // This ID is used when canceling the operation. + // + // Deprecated: Renamed to operation_token. + string operation_id = 3 [deprecated = true]; + + // The request ID allocated at schedule time. + string request_id = 4; + + // The operation token returned by the Nexus handler in the response to the StartOperation request. + // This token is used when canceling the operation. + string operation_token = 5; +} + +// Nexus operation completed successfully. +message NexusOperationCompletedEventAttributes { + // The ID of the `NEXUS_OPERATION_SCHEDULED` event. Uniquely identifies this operation. + int64 scheduled_event_id = 1; + + // Serialized result of the Nexus operation. The response of the Nexus handler. + // Delivered either via a completion callback or as a response to a synchronous operation. + temporal.api.common.v1.Payload result = 2; + + // The request ID allocated at schedule time. + string request_id = 3; +} + +// Nexus operation failed. +message NexusOperationFailedEventAttributes { + // The ID of the `NEXUS_OPERATION_SCHEDULED` event. Uniquely identifies this operation. + int64 scheduled_event_id = 1; + + // Failure details. A NexusOperationFailureInfo wrapping an ApplicationFailureInfo. + temporal.api.failure.v1.Failure failure = 2; + + // The request ID allocated at schedule time. + string request_id = 3; +} + +// Nexus operation timed out. +message NexusOperationTimedOutEventAttributes { + // The ID of the `NEXUS_OPERATION_SCHEDULED` event. Uniquely identifies this operation. + int64 scheduled_event_id = 1; + + // Failure details. A NexusOperationFailureInfo wrapping a CanceledFailureInfo. + temporal.api.failure.v1.Failure failure = 2; + + // The request ID allocated at schedule time. + string request_id = 3; +} + +// Nexus operation completed as canceled. May or may not have been due to a cancellation request by the workflow. +message NexusOperationCanceledEventAttributes { + // The ID of the `NEXUS_OPERATION_SCHEDULED` event. Uniquely identifies this operation. + int64 scheduled_event_id = 1; + + // Cancellation details. + temporal.api.failure.v1.Failure failure = 2; + + // The request ID allocated at schedule time. + string request_id = 3; +} + +message NexusOperationCancelRequestedEventAttributes { + // The id of the `NEXUS_OPERATION_SCHEDULED` event this cancel request corresponds to. + int64 scheduled_event_id = 1; + + // The `WORKFLOW_TASK_COMPLETED` event that the corresponding RequestCancelNexusOperation command was reported + // with. + int64 workflow_task_completed_event_id = 2; +} + +message NexusOperationCancelRequestCompletedEventAttributes { + // The ID of the `NEXUS_OPERATION_CANCEL_REQUESTED` event. + int64 requested_event_id = 1; + + // The `WORKFLOW_TASK_COMPLETED` event that the corresponding RequestCancelNexusOperation command was reported + // with. + int64 workflow_task_completed_event_id = 2; + + // The id of the `NEXUS_OPERATION_SCHEDULED` event this cancel request corresponds to. + int64 scheduled_event_id = 3; +} + +message NexusOperationCancelRequestFailedEventAttributes { + // The ID of the `NEXUS_OPERATION_CANCEL_REQUESTED` event. + int64 requested_event_id = 1; + + // The `WORKFLOW_TASK_COMPLETED` event that the corresponding RequestCancelNexusOperation command was reported + // with. + int64 workflow_task_completed_event_id = 2; + + // Failure details. A NexusOperationFailureInfo wrapping a CanceledFailureInfo. + temporal.api.failure.v1.Failure failure = 3; + + // The id of the `NEXUS_OPERATION_SCHEDULED` event this cancel request corresponds to. + int64 scheduled_event_id = 4; +} + +// History events are the method by which Temporal SDKs advance (or recreate) workflow state. +// See the `EventType` enum for more info about what each event is for. +message HistoryEvent { + // Monotonically increasing event number, starts at 1. + int64 event_id = 1; + + google.protobuf.Timestamp event_time = 2; + + temporal.api.enums.v1.EventType event_type = 3; + + // Failover version of the event, used by the server for multi-cluster replication and history + // versioning. SDKs generally ignore this field. + int64 version = 4; + + // Identifier used by the service to order replication and transfer tasks associated with this + // event. SDKs generally ignore this field. + int64 task_id = 5; + + // Set to true when the SDK may ignore the event as it does not impact workflow state or + // information in any way that the SDK need be concerned with. If an SDK encounters an event + // type which it does not understand, it must error unless this is true. If it is true, it's + // acceptable for the event type and/or attributes to be uninterpretable. + bool worker_may_ignore = 300; + + // Metadata on the event. This is often carried over from commands and client calls. Most events + // won't have this information, and how this information is used is dependent upon the interface + // that reads it. + // + // Current well-known uses: + // * workflow_execution_started_event_attributes - summary and details from start workflow. + // * timer_started_event_attributes - summary represents an identifier for the timer for use by + // user interfaces. + temporal.api.sdk.v1.UserMetadata user_metadata = 301; + + // Links to related entities, such as the entity that started this event's workflow. + repeated temporal.api.common.v1.Link links = 302; + + // Server-computed authenticated caller identity associated with this event. + temporal.api.common.v1.Principal principal = 303; + + // Event group markers attached to this event. + repeated temporal.api.sdk.v1.EventGroupMarker event_group_markers = 304; + + // The event details. The type must match that in `event_type`. + oneof attributes { + WorkflowExecutionStartedEventAttributes workflow_execution_started_event_attributes = 6; + + WorkflowExecutionCompletedEventAttributes workflow_execution_completed_event_attributes = 7; + + WorkflowExecutionFailedEventAttributes workflow_execution_failed_event_attributes = 8; + + WorkflowExecutionTimedOutEventAttributes workflow_execution_timed_out_event_attributes = 9; + + WorkflowTaskScheduledEventAttributes workflow_task_scheduled_event_attributes = 10; + + WorkflowTaskStartedEventAttributes workflow_task_started_event_attributes = 11; + + WorkflowTaskCompletedEventAttributes workflow_task_completed_event_attributes = 12; + + WorkflowTaskTimedOutEventAttributes workflow_task_timed_out_event_attributes = 13; + + WorkflowTaskFailedEventAttributes workflow_task_failed_event_attributes = 14; + + ActivityTaskScheduledEventAttributes activity_task_scheduled_event_attributes = 15; + + ActivityTaskStartedEventAttributes activity_task_started_event_attributes = 16; + + ActivityTaskCompletedEventAttributes activity_task_completed_event_attributes = 17; + + ActivityTaskFailedEventAttributes activity_task_failed_event_attributes = 18; + + ActivityTaskTimedOutEventAttributes activity_task_timed_out_event_attributes = 19; + + TimerStartedEventAttributes timer_started_event_attributes = 20; + + TimerFiredEventAttributes timer_fired_event_attributes = 21; + + ActivityTaskCancelRequestedEventAttributes activity_task_cancel_requested_event_attributes = 22; + + ActivityTaskCanceledEventAttributes activity_task_canceled_event_attributes = 23; + + TimerCanceledEventAttributes timer_canceled_event_attributes = 24; + + MarkerRecordedEventAttributes marker_recorded_event_attributes = 25; + + WorkflowExecutionSignaledEventAttributes workflow_execution_signaled_event_attributes = 26; + + WorkflowExecutionTerminatedEventAttributes workflow_execution_terminated_event_attributes = 27; + + WorkflowExecutionCancelRequestedEventAttributes workflow_execution_cancel_requested_event_attributes = 28; + + WorkflowExecutionCanceledEventAttributes workflow_execution_canceled_event_attributes = 29; + + RequestCancelExternalWorkflowExecutionInitiatedEventAttributes request_cancel_external_workflow_execution_initiated_event_attributes = 30; + + RequestCancelExternalWorkflowExecutionFailedEventAttributes request_cancel_external_workflow_execution_failed_event_attributes = 31; + + ExternalWorkflowExecutionCancelRequestedEventAttributes external_workflow_execution_cancel_requested_event_attributes = 32; + + WorkflowExecutionContinuedAsNewEventAttributes workflow_execution_continued_as_new_event_attributes = 33; + + StartChildWorkflowExecutionInitiatedEventAttributes start_child_workflow_execution_initiated_event_attributes = 34; + + StartChildWorkflowExecutionFailedEventAttributes start_child_workflow_execution_failed_event_attributes = 35; + + ChildWorkflowExecutionStartedEventAttributes child_workflow_execution_started_event_attributes = 36; + + ChildWorkflowExecutionCompletedEventAttributes child_workflow_execution_completed_event_attributes = 37; + + ChildWorkflowExecutionFailedEventAttributes child_workflow_execution_failed_event_attributes = 38; + + ChildWorkflowExecutionCanceledEventAttributes child_workflow_execution_canceled_event_attributes = 39; + + ChildWorkflowExecutionTimedOutEventAttributes child_workflow_execution_timed_out_event_attributes = 40; + + ChildWorkflowExecutionTerminatedEventAttributes child_workflow_execution_terminated_event_attributes = 41; + + SignalExternalWorkflowExecutionInitiatedEventAttributes signal_external_workflow_execution_initiated_event_attributes = 42; + + SignalExternalWorkflowExecutionFailedEventAttributes signal_external_workflow_execution_failed_event_attributes = 43; + + ExternalWorkflowExecutionSignaledEventAttributes external_workflow_execution_signaled_event_attributes = 44; + + UpsertWorkflowSearchAttributesEventAttributes upsert_workflow_search_attributes_event_attributes = 45; + + WorkflowExecutionUpdateAcceptedEventAttributes workflow_execution_update_accepted_event_attributes = 46; + + WorkflowExecutionUpdateRejectedEventAttributes workflow_execution_update_rejected_event_attributes = 47; + + WorkflowExecutionUpdateCompletedEventAttributes workflow_execution_update_completed_event_attributes = 48; + + WorkflowPropertiesModifiedExternallyEventAttributes workflow_properties_modified_externally_event_attributes = 49; + + ActivityPropertiesModifiedExternallyEventAttributes activity_properties_modified_externally_event_attributes = 50; + + WorkflowPropertiesModifiedEventAttributes workflow_properties_modified_event_attributes = 51; + + WorkflowExecutionUpdateAdmittedEventAttributes workflow_execution_update_admitted_event_attributes = 52; + + NexusOperationScheduledEventAttributes nexus_operation_scheduled_event_attributes = 53; + + NexusOperationStartedEventAttributes nexus_operation_started_event_attributes = 54; + + NexusOperationCompletedEventAttributes nexus_operation_completed_event_attributes = 55; + + NexusOperationFailedEventAttributes nexus_operation_failed_event_attributes = 56; + + NexusOperationCanceledEventAttributes nexus_operation_canceled_event_attributes = 57; + + NexusOperationTimedOutEventAttributes nexus_operation_timed_out_event_attributes = 58; + + NexusOperationCancelRequestedEventAttributes nexus_operation_cancel_requested_event_attributes = 59; + + WorkflowExecutionOptionsUpdatedEventAttributes workflow_execution_options_updated_event_attributes = 60; + + NexusOperationCancelRequestCompletedEventAttributes nexus_operation_cancel_request_completed_event_attributes = 61; + + NexusOperationCancelRequestFailedEventAttributes nexus_operation_cancel_request_failed_event_attributes = 62; + + WorkflowExecutionPausedEventAttributes workflow_execution_paused_event_attributes = 63; + + WorkflowExecutionUnpausedEventAttributes workflow_execution_unpaused_event_attributes = 64; + + WorkflowExecutionTimeSkippingTransitionedEventAttributes workflow_execution_time_skipping_transitioned_event_attributes = 65; + } +} + +message History { + repeated HistoryEvent events = 1; +} diff --git a/temporal/api/namespace/v1/message.proto b/temporal/api/namespace/v1/message.proto new file mode 100644 index 000000000..a869ee463 --- /dev/null +++ b/temporal/api/namespace/v1/message.proto @@ -0,0 +1,170 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.namespace.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/enums/v1/namespace.proto"; + +option csharp_namespace = "Temporalio.Api.Namespace.V1"; +option go_package = "go.temporal.io/api/namespace/v1;namespace"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.namespace.v1"; +option ruby_package = "Temporalio::Api::Namespace::V1"; + +message NamespaceInfo { + string name = 1; + + temporal.api.enums.v1.NamespaceState state = 2; + + string description = 3; + + string owner_email = 4; + + // A key-value map for any customized purpose. + map data = 5; + + string id = 6; + + // All capabilities the namespace supports. + Capabilities capabilities = 7; + + // Namespace capability details. Should contain what features are enabled in a namespace. + message Capabilities { + // True if the namespace supports eager workflow start. + bool eager_workflow_start = 1; + + // True if the namespace supports sync update + bool sync_update = 2; + + // True if the namespace supports async update + bool async_update = 3; + + // True if the namespace supports worker heartbeats + bool worker_heartbeats = 4; + + // True if the namespace supports reported problems search attribute + bool reported_problems_search_attribute = 5; + + // True if the namespace supports pausing workflows + bool workflow_pause = 6; + + // True if the namespace supports standalone activities + bool standalone_activities = 7; + + // True if the namespace supports server-side completion of outstanding worker polls on shutdown. + // When enabled, the server will complete polls for workers that send WorkerInstanceKey in their + // poll requests and call ShutdownWorker with the same WorkerInstanceKey. The poll will return + // an empty response. When this flag is true, workers should allow polls to return gracefully + // rather than terminating any open polls on shutdown. + bool worker_poll_complete_on_shutdown = 8; + + // True if the namespace supports poller autoscaling + bool poller_autoscaling = 9; + + // True if the namespace supports worker commands (server-to-worker communication via control queues). + bool worker_commands = 10; + + // True if the namespace supports standalone Nexus operations. + bool standalone_nexus_operation = 11; + + // True if the namespace supports attaching callbacks on workflow updates + bool workflow_update_callbacks = 12; + + // When true, workers should use poller autoscaling by default unless explicitly configured otherwise. + bool poller_autoscaling_auto_enroll = 13; + + // True if the namespace supports pagination of `RespondWorkflowTaskCompleted` request. + bool workflow_task_completion_pagination = 14; + + // True if the namespace supports start delay for standalone activities. + bool standalone_activity_start_delay = 15; + + // True if the namespace supports batch operations for standalone activities. + bool standalone_activity_batch_operations = 16; + + // True if the namespace supports standalone activity operator commands. + bool standalone_activity_operator_commands = 17; + } + + // Namespace configured limits + Limits limits = 8; + + message Limits { + // Maximum size in bytes for payload fields in workflow history events + // (e.g., workflow/activity inputs and results, failure details, signal payloads). + // When exceeded, the server will reject the operation with an error. + int64 blob_size_limit_error = 1; + + // Maximum total memo size in bytes per workflow execution. + int64 memo_size_limit_error = 2; + + // Maximum total size in bytes of a single RespondWorkflowTaskCompleted request. + // Requests exceeding this fail the workflow task with + // WORKFLOW_TASK_FAILED_CAUSE_REQUEST_TOO_LARGE. 0 means no explicit limit. + int64 workflow_task_completion_size_limit_error = 3; + } + + // Whether scheduled workflows are supported on this namespace. This is only needed + // temporarily while the feature is experimental, so we can give it a high tag. + bool supports_schedules = 100; +} + +message NamespaceConfig { + google.protobuf.Duration workflow_execution_retention_ttl = 1; + + BadBinaries bad_binaries = 2; + + // If unspecified (ARCHIVAL_STATE_UNSPECIFIED) then default server configuration is used. + temporal.api.enums.v1.ArchivalState history_archival_state = 3; + + string history_archival_uri = 4; + + // If unspecified (ARCHIVAL_STATE_UNSPECIFIED) then default server configuration is used. + temporal.api.enums.v1.ArchivalState visibility_archival_state = 5; + + string visibility_archival_uri = 6; + + // Map from field name to alias. + map custom_search_attribute_aliases = 7; +} + +message BadBinaries { + map binaries = 1; +} + +message BadBinaryInfo { + string reason = 1; + + string operator = 2; + + google.protobuf.Timestamp create_time = 3; +} + +message UpdateNamespaceInfo { + string description = 1; + + string owner_email = 2; + + // A key-value map for any customized purpose. + // If data already exists on the namespace, + // this will merge with the existing key values. + map data = 3; + + // New namespace state, server will reject if transition is not allowed. + // Allowed transitions are: + // Registered -> [ Deleted | Deprecated | Handover ] + // Handover -> [ Registered ] + // Default is NAMESPACE_STATE_UNSPECIFIED which is do not change state. + temporal.api.enums.v1.NamespaceState state = 4; +} + +message NamespaceFilter { + // By default namespaces in NAMESPACE_STATE_DELETED state are not included. + // Setting include_deleted to true will include deleted namespaces. + // Note: Namespace is in NAMESPACE_STATE_DELETED state when it was deleted from the system but associated data is not deleted yet. + bool include_deleted = 1; +} diff --git a/temporal/api/nexus/v1/message.proto b/temporal/api/nexus/v1/message.proto new file mode 100644 index 000000000..f81482868 --- /dev/null +++ b/temporal/api/nexus/v1/message.proto @@ -0,0 +1,416 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.nexus.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/enums/v1/common.proto"; +import "temporal/api/enums/v1/nexus.proto"; +import "temporal/api/failure/v1/message.proto"; +import "temporal/api/sdk/v1/user_metadata.proto"; + +option csharp_namespace = "Temporalio.Api.Nexus.V1"; +option go_package = "go.temporal.io/api/nexus/v1;nexus"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.nexus.v1"; +option ruby_package = "Temporalio::Api::Nexus::V1"; + +// A general purpose failure message. +// See: https://github.com/nexus-rpc/api/blob/main/SPEC.md#failure +message Failure { + string message = 1; + + string stack_trace = 4; + + map metadata = 2; + + // UTF-8 encoded JSON serializable details. + bytes details = 3; + + Failure cause = 5; +} + +message HandlerError { + // See https://github.com/nexus-rpc/api/blob/main/SPEC.md#predefined-handler-errors. + string error_type = 1; + + Failure failure = 2; + + // Retry behavior, defaults to the retry behavior of the error type as defined in the spec. + temporal.api.enums.v1.NexusHandlerErrorRetryBehavior retry_behavior = 3; +} + +message UnsuccessfulOperationError { + // See https://github.com/nexus-rpc/api/blob/main/SPEC.md#operationinfo. + string operation_state = 1; + + Failure failure = 2; +} + +message Link { + // See https://github.com/nexus-rpc/api/blob/main/SPEC.md#links. + string url = 1; + + string type = 2; +} + +// A request to start an operation. +message StartOperationRequest { + // Name of service to start the operation in. + string service = 1; + + // Type of operation to start. + string operation = 2; + + // A request ID that can be used as an idempotentency key. + string request_id = 3; + + // Callback URL to call upon completion if the started operation is async. + string callback = 4; + + // Full request body from the incoming HTTP request. + temporal.api.common.v1.Payload payload = 5; + + // Header that is expected to be attached to the callback request when the operation completes. + map callback_header = 6; + + // Links contain caller information and can be attached to the operations started by the handler. + repeated Link links = 7; +} + +// A request to cancel an operation. +message CancelOperationRequest { + // Service name. + string service = 1; + + // Type of operation to cancel. + string operation = 2; + + // Operation ID as originally generated by a Handler. + // + // Deprecated. Renamed to operation_token. + string operation_id = 3 [deprecated = true]; + + // Operation token as originally generated by a Handler. + string operation_token = 4; +} + +// A Nexus request. +message Request { + message Capabilities { + // If set, handlers may use temporal.api.failure.v1.Failure instances to return failures to the server. + // This also allows handler and operation errors to have their own messages and stack traces. + bool temporal_failure_responses = 1; + } + + // Headers extracted from the original request in the Temporal frontend. + // When using Nexus over HTTP, this includes the request's HTTP headers ignoring multiple values. + map header = 1; + + // The timestamp when the request was scheduled in the frontend. + // (-- api-linter: core::0142::time-field-names=disabled + // aip.dev/not-precedent: Not following linter rules. --) + google.protobuf.Timestamp scheduled_time = 2; + + Capabilities capabilities = 100; + + oneof variant { + StartOperationRequest start_operation = 3; + + CancelOperationRequest cancel_operation = 4; + } + + // The endpoint this request was addressed to before forwarding to the worker. + // Supported from server version 1.30.0. + string endpoint = 10; +} + +// Response variant for StartOperationRequest. +message StartOperationResponse { + // An operation completed successfully. + message Sync { + temporal.api.common.v1.Payload payload = 1; + + repeated Link links = 2; + } + + // The operation will complete asynchronously. + // The returned ID can be used to reference this operation. + message Async { + // Deprecated. Renamed to operation_token. + string operation_id = 1 [deprecated = true]; + + repeated Link links = 2; + + string operation_token = 3; + } + + oneof variant { + Sync sync_success = 1; + + Async async_success = 2; + + // The operation completed unsuccessfully (failed or canceled). + // Deprecated. Use the failure variant instead. + UnsuccessfulOperationError operation_error = 3 [deprecated = true]; + + // The operation completed unsuccessfully (failed or canceled). + // Failure object must contain an ApplicationFailureInfo or CanceledFailureInfo object. + temporal.api.failure.v1.Failure failure = 4; + } +} + +// Response variant for CancelOperationRequest. +message CancelOperationResponse {} + +// 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; + } +} + +// A cluster-global binding from an endpoint ID to a target for dispatching incoming Nexus requests. +message Endpoint { + // Data version for this endpoint, incremented for every update issued via the UpdateNexusEndpoint API. + int64 version = 1; + + // Unique server-generated endpoint ID. + string id = 2; + + // Spec for the endpoint. + EndpointSpec spec = 3; + + // The date and time when the endpoint was created. + // (-- api-linter: core::0142::time-field-names=disabled + // aip.dev/not-precedent: Not following linter rules. --) + google.protobuf.Timestamp created_time = 4; + + // The date and time when the endpoint was last modified. + // Will not be set if the endpoint has never been modified. + // (-- api-linter: core::0142::time-field-names=disabled + // aip.dev/not-precedent: Not following linter rules. --) + google.protobuf.Timestamp last_modified_time = 5; + + // Server exposed URL prefix for invocation of operations on this endpoint. + // This doesn't include the protocol, hostname or port as the server does not know how it should be accessed + // publicly. The URL is stable in the face of endpoint renames. + string url_prefix = 6; +} + +// Contains mutable fields for an Endpoint. +message EndpointSpec { + // Endpoint name, unique for this cluster. Must match `[a-zA-Z_][a-zA-Z0-9_]*`. + // Renaming an endpoint breaks all workflow callers that reference this endpoint, causing operations to fail. + string name = 1; + + // Markdown description serialized as a single JSON string. + // If the Payload is encrypted, the UI and CLI may decrypt with the configured codec server endpoint. + // By default, the server enforces a limit of 20,000 bytes for this entire payload. + temporal.api.common.v1.Payload description = 2; + + // Target to route requests to. + EndpointTarget target = 3; +} + +// Target to route requests to. +message EndpointTarget { + // Target a worker polling on a Nexus task queue in a specific namespace. + message Worker { + // Namespace to route requests to. + string namespace = 1; + + // Nexus task queue to route requests to. + string task_queue = 2; + } + + // Target an external server by URL. + // At a later point, this will support providing credentials, in the meantime, an http.RoundTripper can be injected + // into the server to modify the request. + message External { + // URL to call. + string url = 1; + } + + oneof variant { + Worker worker = 1; + + External external = 2; + } +} + +// NexusOperationExecutionCancellationInfo contains the state of a Nexus operation cancellation. +message NexusOperationExecutionCancellationInfo { + // The time when cancellation was requested. + google.protobuf.Timestamp requested_time = 1; + + temporal.api.enums.v1.NexusOperationCancellationState state = 2; + + // The number of attempts made to deliver the cancel operation request. + // This number represents a minimum bound since the attempt is incremented after the request completes. + int32 attempt = 3; + + // The time when the last attempt completed. + google.protobuf.Timestamp last_attempt_complete_time = 4; + + // The last attempt's failure, if any. + temporal.api.failure.v1.Failure last_attempt_failure = 5; + + // The time when the next attempt is scheduled. + google.protobuf.Timestamp next_attempt_schedule_time = 6; + + // If the state is BLOCKED, blocked reason provides additional information. + string blocked_reason = 7; + + // A reason that may be specified in the CancelNexusOperationRequest. + string reason = 8; +} + +// Full current state of a standalone Nexus operation, as of the time of the request. +message NexusOperationExecutionInfo { + // Unique identifier of this Nexus operation within its namespace along with run ID (below). + string operation_id = 1; + + string run_id = 2; + + // Endpoint name, resolved to a URL via the cluster's endpoint registry. + string endpoint = 3; + + // Service name. + string service = 4; + + // Operation name. + string operation = 5; + + // A general status for this operation, indicates whether it is currently running or in one of the terminal statuses. + // Updated once when the operation is originally scheduled, and again when it reaches a terminal status. + temporal.api.enums.v1.NexusOperationExecutionStatus status = 6; + + // More detailed breakdown of NEXUS_OPERATION_EXECUTION_STATUS_RUNNING. + temporal.api.enums.v1.PendingNexusOperationState state = 7; + + // Schedule-to-close timeout for this operation. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 8; + + // Schedule-to-start timeout for this operation. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 9; + + // Start-to-close timeout for this operation. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 10; + + // The number of attempts made to deliver the start operation request. + // This number is approximate, it is incremented when a task is added to the history queue. + // In practice, there could be more attempts if a task is executed but fails to commit, or less attempts if a task + // was never executed. + int32 attempt = 11; + + // Time the operation was originally scheduled via a StartNexusOperation request. + google.protobuf.Timestamp schedule_time = 12; + + // Scheduled time + schedule to close timeout. + google.protobuf.Timestamp expiration_time = 13; + + // Time when the operation transitioned to a closed state. + google.protobuf.Timestamp close_time = 14; + + // The time when the last attempt completed. + google.protobuf.Timestamp last_attempt_complete_time = 15; + + // The last attempt's failure, if any. + temporal.api.failure.v1.Failure last_attempt_failure = 16; + + // The time when the next attempt is scheduled. + google.protobuf.Timestamp next_attempt_schedule_time = 17; + + // Elapsed time from schedule_time to now for running operations or to close_time for closed + // operations, including all attempts and backoff between attempts. + google.protobuf.Duration execution_duration = 18; + + NexusOperationExecutionCancellationInfo cancellation_info = 19; + + // If the state is BLOCKED, blocked reason provides additional information. + string blocked_reason = 20; + + // Server-generated request ID used as an idempotency token when submitting start requests to + // the handler. Distinct from the request_id in StartNexusOperationRequest, which is the + // caller-side idempotency key for the StartNexusOperation RPC itself. + string request_id = 21; + + // Operation token. Only set for asynchronous operations after a successful StartOperation call. + string operation_token = 22; + + // Incremented each time the operation's state is mutated in persistence. + int64 state_transition_count = 23; + + temporal.api.common.v1.SearchAttributes search_attributes = 24; + + // Header for context propagation and tracing purposes. + map nexus_header = 25; + + // Metadata for use by user interfaces to display the fixed as-of-start summary and details of the operation. + temporal.api.sdk.v1.UserMetadata user_metadata = 26; + + // Links attached by the handler of this operation on start or completion. + repeated temporal.api.common.v1.Link links = 27; + + // The identity of the client who started this operation. + string identity = 28; + + // Updated once on scheduled and once on terminal status. + int64 state_size_bytes = 29; +} + +// Limited Nexus operation information returned in the list response. +// When adding fields here, ensure that it is also present in NexusOperationExecutionInfo (note that it may already be present in +// NexusOperationExecutionInfo but not at the top-level). +message NexusOperationExecutionListInfo { + // A unique identifier of this operation within its namespace along with run ID (below). + string operation_id = 1; + + // The run ID of the standalone Nexus operation. + string run_id = 2; + + // Endpoint name. + string endpoint = 3; + + // Service name. + string service = 4; + + // Operation name. + string operation = 5; + + // Time the operation was originally scheduled via a StartNexusOperation request. + google.protobuf.Timestamp schedule_time = 6; + + // If the operation is in a terminal status, this field represents the time the operation transitioned to that status. + google.protobuf.Timestamp close_time = 7; + + // The status is updated once, when the operation is originally scheduled, and again when the operation reaches a terminal status. + temporal.api.enums.v1.NexusOperationExecutionStatus status = 8; + + // Search attributes from the start request. + temporal.api.common.v1.SearchAttributes search_attributes = 9; + + // Updated on terminal status. + int64 state_transition_count = 10; + + // The difference between close time and scheduled time. + // This field is only populated if the operation is closed. + google.protobuf.Duration execution_duration = 11; + + // Updated once on scheduled and once on terminal status. + int64 state_size_bytes = 12; +} diff --git a/temporal/api/nexusservices/workerservice/v1/request_response.proto b/temporal/api/nexusservices/workerservice/v1/request_response.proto new file mode 100644 index 000000000..da12acb53 --- /dev/null +++ b/temporal/api/nexusservices/workerservice/v1/request_response.proto @@ -0,0 +1,29 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.nexusservices.workerservice.v1; + +import "temporal/api/worker/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Nexusservices.Workerservice.V1"; +option go_package = "go.temporal.io/api/nexusservices/workerservice/v1;workerservice"; +option java_multiple_files = true; +option java_outer_classname = "RequestResponseProto"; +option java_package = "io.temporal.api.nexusservices.workerservice.v1"; +option ruby_package = "Temporalio::Api::Nexusservices::Workerservice::V1"; + +// (-- +// Internal Nexus service for server-to-worker communication. +// --) + +// Request payload for the "ExecuteCommands" Nexus operation. +message ExecuteCommandsRequest { + repeated temporal.api.worker.v1.WorkerCommand commands = 1; +} + +// Response payload for the "ExecuteCommands" Nexus operation. +// The results list must be 1:1 with the commands list in the request (same size and order). +message ExecuteCommandsResponse { + repeated temporal.api.worker.v1.WorkerCommandResult results = 1; +} diff --git a/temporal/api/operatorservice/v1/request_response.proto b/temporal/api/operatorservice/v1/request_response.proto new file mode 100644 index 000000000..bf74629fe --- /dev/null +++ b/temporal/api/operatorservice/v1/request_response.proto @@ -0,0 +1,195 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.operatorservice.v1; + +import "google/protobuf/duration.proto"; +import "temporal/api/enums/v1/common.proto"; +import "temporal/api/nexus/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.OperatorService.V1"; +option go_package = "go.temporal.io/api/operatorservice/v1;operatorservice"; +option java_multiple_files = true; +option java_outer_classname = "RequestResponseProto"; +option java_package = "io.temporal.api.operatorservice.v1"; +option ruby_package = "Temporalio::Api::OperatorService::V1"; + +// (-- Search Attribute --) + +message AddSearchAttributesRequest { + // Mapping between search attribute name and its IndexedValueType. + map search_attributes = 1; + + string namespace = 2; +} + +message AddSearchAttributesResponse {} + +message RemoveSearchAttributesRequest { + // Search attribute names to delete. + repeated string search_attributes = 1; + + string namespace = 2; +} + +message RemoveSearchAttributesResponse {} + +message ListSearchAttributesRequest { + string namespace = 1; +} + +message ListSearchAttributesResponse { + // Mapping between custom (user-registered) search attribute name to its IndexedValueType. + map custom_attributes = 1; + + // Mapping between system (predefined) search attribute name to its IndexedValueType. + map system_attributes = 2; + + // Mapping from the attribute name to the visibility storage native type. + map storage_schema = 3; +} + +message DeleteNamespaceRequest { + // Only one of namespace or namespace_id must be specified to identify namespace. + string namespace = 1; + + string namespace_id = 2; + + // If provided, the deletion of namespace info will be delayed for the given duration (0 means no delay). + // If not provided, the default delay configured in the cluster will be used. + google.protobuf.Duration namespace_delete_delay = 3; +} + +message DeleteNamespaceResponse { + // Temporary namespace name that is used during reclaim resources step. + string deleted_namespace = 1; +} + +message AddOrUpdateRemoteClusterRequest { + // Frontend Address is a cross cluster accessible address for gRPC traffic. This field is required. + string frontend_address = 1; + + // Flag to enable / disable the cross cluster connection. + bool enable_remote_cluster_connection = 2; + + // Frontend HTTP Address is a cross cluster accessible address for HTTP traffic. This field is optional. If not provided + // on update, the existing HTTP address will be removed. + string frontend_http_address = 3; + + // Controls whether replication streams are active. + bool enable_replication = 4; +} + +message AddOrUpdateRemoteClusterResponse {} + +message RemoveRemoteClusterRequest { + // Remote cluster name to be removed. + string cluster_name = 1; +} + +message RemoveRemoteClusterResponse {} + +message ListClustersRequest { + int32 page_size = 1; + + bytes next_page_token = 2; +} + +message ListClustersResponse { + // List of all cluster information + repeated ClusterMetadata clusters = 1; + + bytes next_page_token = 4; +} + +message ClusterMetadata { + // Name of the cluster name. + string cluster_name = 1; + + // Id of the cluster. + string cluster_id = 2; + + // gRPC address. + string address = 3; + + // HTTP address, if one exists. + string http_address = 7; + + // A unique failover version across all connected clusters. + int64 initial_failover_version = 4; + + // History service shard number. + int32 history_shard_count = 5; + + // A flag to indicate if a connection is active. + bool is_connection_enabled = 6; + + // A flag to indicate if replication is enabled. + bool is_replication_enabled = 8; +} + +message GetNexusEndpointRequest { + // Server-generated unique endpoint ID. + string id = 1; +} + +message GetNexusEndpointResponse { + temporal.api.nexus.v1.Endpoint endpoint = 1; +} + +message CreateNexusEndpointRequest { + // Endpoint definition to create. + temporal.api.nexus.v1.EndpointSpec spec = 1; +} + +message CreateNexusEndpointResponse { + // Data post acceptance. Can be used to issue additional updates to this record. + temporal.api.nexus.v1.Endpoint endpoint = 1; +} + +message UpdateNexusEndpointRequest { + // Server-generated unique endpoint ID. + string id = 1; + + // Data version for this endpoint. Must match current version. + int64 version = 2; + + temporal.api.nexus.v1.EndpointSpec spec = 3; +} + +message UpdateNexusEndpointResponse { + // Data post acceptance. Can be used to issue additional updates to this record. + temporal.api.nexus.v1.Endpoint endpoint = 1; +} + +message DeleteNexusEndpointRequest { + // Server-generated unique endpoint ID. + string id = 1; + + // Data version for this endpoint. Must match current version. + int64 version = 2; +} + +message DeleteNexusEndpointResponse {} + +message ListNexusEndpointsRequest { + int32 page_size = 1; + + // To get the next page, pass in `ListNexusEndpointsResponse.next_page_token` from the previous page's + // response, the token will be empty if there's no other page. + // Note: the last page may be empty if the total number of endpoints registered is a multiple of the page size. + bytes next_page_token = 2; + + // Name of the incoming endpoint to filter on - optional. Specifying this will result in zero or one results. + // (-- api-linter: core::203::field-behavior-required=disabled + // aip.dev/not-precedent: Not following linter rules. --) + string name = 3; +} + +message ListNexusEndpointsResponse { + // Token for getting the next page. + bytes next_page_token = 1; + + repeated temporal.api.nexus.v1.Endpoint endpoints = 2; +} diff --git a/temporal/api/operatorservice/v1/service.proto b/temporal/api/operatorservice/v1/service.proto new file mode 100644 index 000000000..6572d108b --- /dev/null +++ b/temporal/api/operatorservice/v1/service.proto @@ -0,0 +1,119 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.operatorservice.v1; + +import "google/api/annotations.proto"; +import "temporal/api/operatorservice/v1/request_response.proto"; + +option csharp_namespace = "Temporalio.Api.OperatorService.V1"; +option go_package = "go.temporal.io/api/operatorservice/v1;operatorservice"; +option java_multiple_files = true; +option java_outer_classname = "ServiceProto"; +option java_package = "io.temporal.api.operatorservice.v1"; +option ruby_package = "Temporalio::Api::OperatorService::V1"; + +// OperatorService API defines how Temporal SDKs and other clients interact with the Temporal server +// to perform administrative functions like registering a search attribute or a namespace. +// APIs in this file could be not compatible with Temporal Cloud, hence it's usage in SDKs should be limited by +// designated APIs that clearly state that they shouldn't be used by the main Application (Workflows & Activities) framework. +service OperatorService { + // (-- Search Attribute --) + + // AddSearchAttributes add custom search attributes. + // + // Returns ALREADY_EXISTS status code if a Search Attribute with any of the specified names already exists + // Returns INTERNAL status code with temporal.api.errordetails.v1.SystemWorkflowFailure in Error Details if registration process fails, + rpc AddSearchAttributes(AddSearchAttributesRequest) returns (AddSearchAttributesResponse); + + // RemoveSearchAttributes removes custom search attributes. + // + // Returns NOT_FOUND status code if a Search Attribute with any of the specified names is not registered + rpc RemoveSearchAttributes(RemoveSearchAttributesRequest) returns (RemoveSearchAttributesResponse); + + // ListSearchAttributes returns comprehensive information about search attributes. + rpc ListSearchAttributes(ListSearchAttributesRequest) returns (ListSearchAttributesResponse) { + option (google.api.http) = { + get: "/cluster/namespaces/{namespace}/search-attributes", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/search-attributes"}] + }; + } + + // DeleteNamespace synchronously deletes a namespace and asynchronously reclaims all namespace resources. + rpc DeleteNamespace(DeleteNamespaceRequest) returns (DeleteNamespaceResponse); + + // AddOrUpdateRemoteCluster adds or updates remote cluster. + rpc AddOrUpdateRemoteCluster(AddOrUpdateRemoteClusterRequest) returns (AddOrUpdateRemoteClusterResponse); + + // RemoveRemoteCluster removes remote cluster. + rpc RemoveRemoteCluster(RemoveRemoteClusterRequest) returns (RemoveRemoteClusterResponse); + + // ListClusters returns information about Temporal clusters. + rpc ListClusters(ListClustersRequest) returns (ListClustersResponse); + + // Get a registered Nexus endpoint by ID. The returned version can be used for optimistic updates. + rpc GetNexusEndpoint(GetNexusEndpointRequest) returns (GetNexusEndpointResponse) { + option (google.api.http) = { + get: "/cluster/nexus/endpoints/{id}", + additional_bindings: [ + {get: "/api/v1/nexus/endpoints/{id}"}] + }; + } + + // Create a Nexus endpoint. This will fail if an endpoint with the same name is already registered with a status of + // ALREADY_EXISTS. + // Returns the created endpoint with its initial version. You may use this version for subsequent updates. + rpc CreateNexusEndpoint(CreateNexusEndpointRequest) returns (CreateNexusEndpointResponse) { + option (google.api.http) = { + post: "/cluster/nexus/endpoints", + body: "*", + additional_bindings: [ + { + post: "/api/v1/nexus/endpoints", + body: "*" + } + ] + }; + } + + // Optimistically update a Nexus endpoint based on provided version as obtained via the `GetNexusEndpoint` or + // `ListNexusEndpointResponse` APIs. This will fail with a status of FAILED_PRECONDITION if the version does not + // match. + // Returns the updated endpoint with its updated version. You may use this version for subsequent updates. You don't + // need to increment the version yourself. The server will increment the version for you after each update. + rpc UpdateNexusEndpoint(UpdateNexusEndpointRequest) returns (UpdateNexusEndpointResponse) { + option (google.api.http) = { + post: "/cluster/nexus/endpoints/{id}/update", + body: "*", + additional_bindings: [ + { + post: "/api/v1/nexus/endpoints/{id}/update", + body: "*" + } + ] + }; + } + + // Delete an incoming Nexus service by ID. + rpc DeleteNexusEndpoint(DeleteNexusEndpointRequest) returns (DeleteNexusEndpointResponse) { + option (google.api.http) = { + delete: "/cluster/nexus/endpoints/{id}", + additional_bindings: [ + {delete: "/api/v1/nexus/endpoints/{id}"}] + }; + } + + // List all Nexus endpoints for the cluster, sorted by ID in ascending order. Set page_token in the request to the + // next_page_token field of the previous response to get the next page of results. An empty next_page_token + // indicates that there are no more results. During pagination, a newly added service with an ID lexicographically + // earlier than the previous page's last endpoint's ID may be missed. + rpc ListNexusEndpoints(ListNexusEndpointsRequest) returns (ListNexusEndpointsResponse) { + option (google.api.http) = { + get: "/cluster/nexus/endpoints", + additional_bindings: [ + {get: "/api/v1/nexus/endpoints"}] + }; + } +} diff --git a/temporal/api/protocol/v1/message.proto b/temporal/api/protocol/v1/message.proto new file mode 100644 index 000000000..10a43c9a3 --- /dev/null +++ b/temporal/api/protocol/v1/message.proto @@ -0,0 +1,38 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.protocol.v1; + +import "google/protobuf/any.proto"; + +option csharp_namespace = "Temporalio.Api.Protocol.V1"; +option go_package = "go.temporal.io/api/protocol/v1;protocol"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.protocol.v1"; +option ruby_package = "Temporalio::Api::Protocol::V1"; + +// (-- api-linter: core::0146::any=disabled +// aip.dev/not-precedent: We want runtime extensibility for the body field --) +message Message { + // An ID for this specific message. + string id = 1; + + // Identifies the specific instance of a protocol to which this message + // belongs. + string protocol_instance_id = 2; + + // The event ID or command ID after which this message can be delivered. The + // effects of history up to and including this event ID should be visible to + // the code that handles this message. Omit to opt out of sequencing. + oneof sequencing_id { + int64 event_id = 3; + + int64 command_index = 4; + } + + // The opaque data carried by this message. The protocol type can be + // extracted from the package name of the message carried inside the Any. + google.protobuf.Any body = 5; +} diff --git a/temporal/api/protometa/v1/annotations.proto b/temporal/api/protometa/v1/annotations.proto new file mode 100644 index 000000000..e45b64fd7 --- /dev/null +++ b/temporal/api/protometa/v1/annotations.proto @@ -0,0 +1,39 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.protometa.v1; + +import "google/protobuf/descriptor.proto"; + +option csharp_namespace = "Temporalio.Api.Protometa.V1"; +option go_package = "go.temporal.io/api/protometa/v1;protometa"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "io.temporal.api.protometa.v1"; +option ruby_package = "Temporalio::Api::Protometa::V1"; + +// RequestHeaderAnnotation allows specifying that field values from a request +// should be propagated as outbound headers. +// +// The value field supports template interpolation where field paths enclosed +// in braces will be replaced with the actual field values from the request. +// For example: +// value: "{workflow_execution.workflow_id}" +// value: "workflow-{workflow_execution.workflow_id}" +// value: "{namespace}/{workflow_execution.workflow_id}" +message RequestHeaderAnnotation { + // The name of the header to set (e.g., "temporal-resource-id") + string header = 1; + + // A template string that may contain field paths in braces. + // Field paths use dot notation to traverse nested messages. + // Example: "{workflow_execution.workflow_id}" + string value = 2; +} + +// Extension to add request-header annotations to RPC methods. +// Multiple headers can be set by repeating this option. +extend google.protobuf.MethodOptions { + repeated RequestHeaderAnnotation request_header = 7234001; +} diff --git a/temporal/api/query/v1/message.proto b/temporal/api/query/v1/message.proto new file mode 100644 index 000000000..914eb7fbb --- /dev/null +++ b/temporal/api/query/v1/message.proto @@ -0,0 +1,53 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.query.v1; + +import "temporal/api/common/v1/message.proto"; +import "temporal/api/enums/v1/query.proto"; +import "temporal/api/enums/v1/workflow.proto"; +import "temporal/api/failure/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Query.V1"; +option go_package = "go.temporal.io/api/query/v1;query"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.query.v1"; +option ruby_package = "Temporalio::Api::Query::V1"; + +// See https://docs.temporal.io/docs/concepts/queries/ +message WorkflowQuery { + // The workflow-author-defined identifier of the query. Typically a function name. + string query_type = 1; + + // Serialized arguments that will be provided to the query handler. + temporal.api.common.v1.Payloads query_args = 2; + + // Headers that were passed by the caller of the query and copied by temporal + // server into the workflow task. + temporal.api.common.v1.Header header = 3; +} + +// Answer to a `WorkflowQuery` +message WorkflowQueryResult { + // Did the query succeed or fail? + temporal.api.enums.v1.QueryResultType result_type = 1; + + // Set when the query succeeds with the results. + // Mutually exclusive with `error_message` and `failure`. + temporal.api.common.v1.Payloads answer = 2; + + // Mutually exclusive with `answer`. Set when the query fails. + // See also the newer `failure` field. + string error_message = 3; + + // The full reason for this query failure. This field is newer than `error_message` and can be encoded by the SDK's + // failure converter to support E2E encryption of messages and stack traces. + // Mutually exclusive with `answer`. Set when the query fails. + temporal.api.failure.v1.Failure failure = 4; +} + +message QueryRejected { + temporal.api.enums.v1.WorkflowExecutionStatus status = 1; +} diff --git a/temporal/api/replication/v1/message.proto b/temporal/api/replication/v1/message.proto new file mode 100644 index 000000000..731ef02a2 --- /dev/null +++ b/temporal/api/replication/v1/message.proto @@ -0,0 +1,35 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.replication.v1; + +import "google/protobuf/timestamp.proto"; +import "temporal/api/enums/v1/namespace.proto"; + +option csharp_namespace = "Temporalio.Api.Replication.V1"; +option go_package = "go.temporal.io/api/replication/v1;replication"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.replication.v1"; +option ruby_package = "Temporalio::Api::Replication::V1"; + +message ClusterReplicationConfig { + string cluster_name = 1; +} + +message NamespaceReplicationConfig { + string active_cluster_name = 1; + + repeated ClusterReplicationConfig clusters = 2; + + temporal.api.enums.v1.ReplicationState state = 3; +} + +// Represents a historical replication status of a Namespace +message FailoverStatus { + // Timestamp when the Cluster switched to the following failover_version + google.protobuf.Timestamp failover_time = 1; + + int64 failover_version = 2; +} diff --git a/temporal/api/rules/v1/message.proto b/temporal/api/rules/v1/message.proto new file mode 100644 index 000000000..f2fc27f16 --- /dev/null +++ b/temporal/api/rules/v1/message.proto @@ -0,0 +1,90 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.rules.v1; + +import "google/protobuf/timestamp.proto"; + +option csharp_namespace = "Temporalio.Api.Rules.V1"; +option go_package = "go.temporal.io/api/rules/v1;rules"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.rules.v1"; +option ruby_package = "Temporalio::Api::Rules::V1"; + +message WorkflowRuleAction { + message ActionActivityPause {} + + // Supported actions. + oneof variant { + ActionActivityPause activity_pause = 1; + } +} + +message WorkflowRuleSpec { + // The id of the new workflow rule. Must be unique within the namespace. + // Can be set by the user, and can have business meaning. + string id = 1; + + // Activity trigger will be triggered when an activity is about to start. + message ActivityStartingTrigger { + // Activity predicate is a SQL-like string filter parameter. + // It is used to match against workflow data. + // The following activity attributes are supported as part of the predicate: + // - ActivityType: An Activity Type is the mapping of a name to an Activity Definition.. + // - ActivityId: The ID of the activity. + // - ActivityAttempt: The number attempts of the activity. + // - BackoffInterval: The current amount of time between scheduled attempts of the activity. + // - ActivityStatus: The status of the activity. Can be one of "Scheduled", "Started", "Paused". + // - TaskQueue: The name of the task queue the workflow specified that the activity should run on. + // Activity predicate support the following operators: + // * =, !=, >, >=, <, <= + // * AND, OR, () + // * BETWEEN ... AND + // STARTS_WITH + string predicate = 1; + } + + // Specifies how the rule should be triggered and evaluated. + // Currently, only "activity start" type is supported. + oneof trigger { + ActivityStartingTrigger activity_start = 2; + } + + // Restricted Visibility query. + // This query is used to filter workflows in this namespace to which this rule should apply. + // It is applied to any running workflow each time a triggering event occurs, before the trigger predicate is evaluated. + // The following workflow attributes are supported: + // - WorkflowType + // - WorkflowId + // - StartTime + // - ExecutionStatus + string visibility_query = 3; + + // WorkflowRuleAction to be taken when the rule is triggered and predicate is matched. + repeated WorkflowRuleAction actions = 4; + + // Expiration time of the rule. After this time, the rule will be deleted. + // Can be empty if the rule should never expire. + google.protobuf.Timestamp expiration_time = 5; +} + +// WorkflowRule describes a rule that can be applied to any workflow in this namespace. +message WorkflowRule { + // Rule creation time. + google.protobuf.Timestamp create_time = 1; + + // Rule specification + WorkflowRuleSpec spec = 2; + + // Identity of the actor that created the rule + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: It is better reflect the intent this way, we will also have updated_by. --) + // (-- api-linter: core::0142::time-field-names=disabled + // aip.dev/not-precedent: Same as above. All other options sounds clumsy --) + string created_by_identity = 3; + + // Rule description. + string description = 4; +} diff --git a/temporal/api/schedule/v1/message.proto b/temporal/api/schedule/v1/message.proto new file mode 100644 index 000000000..4a57d1d69 --- /dev/null +++ b/temporal/api/schedule/v1/message.proto @@ -0,0 +1,434 @@ +// Generated from api_next. DO NOT EDIT. + +// (-- api-linter: core::0203::optional=disabled +// aip.dev/not-precedent: field_behavior annotation not available in our gogo fork --) +// (-- api-linter: core::0203::input-only=disabled +// aip.dev/not-precedent: field_behavior annotation not available in our gogo fork --) + +syntax = "proto3"; + +package temporal.api.schedule.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/enums/v1/schedule.proto"; +import "temporal/api/enums/v1/workflow.proto"; +import "temporal/api/workflow/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Schedule.V1"; +option go_package = "go.temporal.io/api/schedule/v1;schedule"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.schedule.v1"; +option ruby_package = "Temporalio::Api::Schedule::V1"; + +// CalendarSpec describes an event specification relative to the calendar, +// similar to a traditional cron specification, but with labeled fields. Each +// field can be one of: +// *: matches always +// x: matches when the field equals x +// x/y : matches when the field equals x+n*y where n is an integer +// x-z: matches when the field is between x and z inclusive +// w,x,y,...: matches when the field is one of the listed values +// Each x, y, z, ... is either a decimal integer, or a month or day of week name +// or abbreviation (in the appropriate fields). +// A timestamp matches if all fields match. +// Note that fields have different default values, for convenience. +// Note that the special case that some cron implementations have for treating +// day_of_month and day_of_week as "or" instead of "and" when both are set is +// not implemented. +// day_of_week can accept 0 or 7 as Sunday +// CalendarSpec gets compiled into StructuredCalendarSpec, which is what will be +// returned if you describe the schedule. +message CalendarSpec { + // Expression to match seconds. Default: 0 + string second = 1; + + // Expression to match minutes. Default: 0 + string minute = 2; + + // Expression to match hours. Default: 0 + string hour = 3; + + // Expression to match days of the month. Default: * + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: standard name of field --) + string day_of_month = 4; + + // Expression to match months. Default: * + string month = 5; + + // Expression to match years. Default: * + string year = 6; + + // Expression to match days of the week. Default: * + string day_of_week = 7; + + // Free-form comment describing the intention of this spec. + string comment = 8; +} + +// Range represents a set of integer values, used to match fields of a calendar +// time in StructuredCalendarSpec. If end < start, then end is interpreted as +// equal to start. This means you can use a Range with start set to a value, and +// end and step unset (defaulting to 0) to represent a single value. +message Range { + // Start of range (inclusive). + int32 start = 1; + + // End of range (inclusive). + int32 end = 2; + + // Step (optional, default 1). + int32 step = 3; +} + +// StructuredCalendarSpec describes an event specification relative to the +// calendar, in a form that's easy to work with programmatically. Each field can +// be one or more ranges. +// A timestamp matches if at least one range of each field matches the +// corresponding fields of the timestamp, except for year: if year is missing, +// that means all years match. For all fields besides year, at least one Range +// must be present to match anything. +// Relative expressions such as "last day of the month" or "third Monday" are not currently +// representable; callers must enumerate the concrete days they require. +message StructuredCalendarSpec { + // Match seconds (0-59) + repeated Range second = 1; + + // Match minutes (0-59) + repeated Range minute = 2; + + // Match hours (0-23) + repeated Range hour = 3; + + // Match days of the month (1-31) + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: standard name of field --) + repeated Range day_of_month = 4; + + // Match months (1-12) + repeated Range month = 5; + + // Match years. + repeated Range year = 6; + + // Match days of the week (0-6; 0 is Sunday). + repeated Range day_of_week = 7; + + // Free-form comment describing the intention of this spec. + string comment = 8; +} + +// IntervalSpec matches times that can be expressed as: +// epoch + n * interval + phase +// where n is an integer. +// phase defaults to zero if missing. interval is required. +// Both interval and phase must be non-negative and are truncated to the nearest +// second before any calculations. +// For example, an interval of 1 hour with phase of zero would match every hour, +// on the hour. The same interval but a phase of 19 minutes would match every +// xx:19:00. An interval of 28 days with phase zero would match +// 2022-02-17T00:00:00Z (among other times). The same interval with a phase of 3 +// days, 5 hours, and 23 minutes would match 2022-02-20T05:23:00Z instead. +message IntervalSpec { + google.protobuf.Duration interval = 1; + + google.protobuf.Duration phase = 2; +} + +// ScheduleSpec is a complete description of a set of absolute timestamps +// (possibly infinite) that an action should occur at. The meaning of a +// ScheduleSpec depends only on its contents and never changes, except that the +// definition of a time zone can change over time (most commonly, when daylight +// saving time policy changes for an area). To create a totally self-contained +// ScheduleSpec, use UTC or include timezone_data. +// +// For input, you can provide zero or more of: structured_calendar, calendar, +// cron_string, interval, and exclude_structured_calendar, and all of them will +// be used (the schedule will take action at the union of all of their times, +// minus the ones that match exclude_structured_calendar). +// +// On input, calendar and cron_string fields will be compiled into +// structured_calendar (and maybe interval and timezone_name), so if you +// Describe a schedule, you'll see only structured_calendar, interval, etc. +// +// If a spec has no matching times after the current time, then the schedule +// will be subject to automatic deletion (after several days). +message ScheduleSpec { + // Calendar-based specifications of times. + repeated StructuredCalendarSpec structured_calendar = 7; + + // cron_string holds a traditional cron specification as a string. It + // accepts 5, 6, or 7 fields, separated by spaces, and interprets them the + // same way as CalendarSpec. + // 5 fields: minute, hour, day_of_month, month, day_of_week + // 6 fields: minute, hour, day_of_month, month, day_of_week, year + // 7 fields: second, minute, hour, day_of_month, month, day_of_week, year + // If year is not given, it defaults to *. If second is not given, it + // defaults to 0. + // Shorthands @yearly, @monthly, @weekly, @daily, and @hourly are also + // accepted instead of the 5-7 time fields. + // Optionally, the string can be preceded by CRON_TZ= or + // TZ=, which will get copied to timezone_name. (There must + // not also be a timezone_name present.) + // Optionally "#" followed by a comment can appear at the end of the string. + // Note that the special case that some cron implementations have for + // treating day_of_month and day_of_week as "or" instead of "and" when both + // are set is not implemented. + // @every [/] is accepted and gets compiled into an + // IntervalSpec instead. and should be a decimal integer + // with a unit suffix s, m, h, or d. + repeated string cron_string = 8; + + // Calendar-based specifications of times. + repeated CalendarSpec calendar = 1; + + // Interval-based specifications of times. + repeated IntervalSpec interval = 2; + + // Any timestamps matching any of exclude_* will be skipped. + // Deprecated. Use exclude_structured_calendar. + repeated CalendarSpec exclude_calendar = 3 [deprecated = true]; + + repeated StructuredCalendarSpec exclude_structured_calendar = 9; + + // If start_time is set, any timestamps before start_time will be skipped. + // (Together, start_time and end_time make an inclusive interval.) + google.protobuf.Timestamp start_time = 4; + + // If end_time is set, any timestamps after end_time will be skipped. + google.protobuf.Timestamp end_time = 5; + + // All timestamps will be incremented by a random value from 0 to this + // amount of jitter. Default: 0 + google.protobuf.Duration jitter = 6; + + // Time zone to interpret all calendar-based specs in. + // + // If unset, defaults to UTC. We recommend using UTC for your application if + // at all possible, to avoid various surprising properties of time zones. + // + // Time zones may be provided by name, corresponding to names in the IANA + // time zone database (see https://www.iana.org/time-zones). The definition + // will be loaded by the Temporal server from the environment it runs in. + // + // If your application requires more control over the time zone definition + // used, it may pass in a complete definition in the form of a TZif file + // from the time zone database. If present, this will be used instead of + // loading anything from the environment. You are then responsible for + // updating timezone_data when the definition changes. + // + // Calendar spec matching is based on literal matching of the clock time + // with no special handling of DST: if you write a calendar spec that fires + // at 2:30am and specify a time zone that follows DST, that action will not + // be triggered on the day that has no 2:30am. Similarly, an action that + // fires at 1:30am will be triggered twice on the day that has two 1:30s. + // + // Also note that no actions are taken on leap-seconds (e.g. 23:59:60 UTC). + string timezone_name = 10; + + bytes timezone_data = 11; +} + +message SchedulePolicies { + // Policy for overlaps. + // Note that this can be changed after a schedule has taken some actions, + // and some changes might produce unintuitive results. In general, the later + // policy overrides the earlier policy. + temporal.api.enums.v1.ScheduleOverlapPolicy overlap_policy = 1; + + // Policy for catchups: + // If the Temporal server misses an action due to one or more components + // being down, and comes back up, the action will be run if the scheduled + // time is within this window from the current time. + // This value defaults to one year, and can't be less than 10 seconds. + google.protobuf.Duration catchup_window = 2; + + // If true, and a workflow run fails or times out, turn on "paused". + // This applies after retry policies: the full chain of retries must fail to + // trigger a pause here. + bool pause_on_failure = 3; + + // If true, and the action would start a workflow, a timestamp will not be + // appended to the scheduled workflow id. + bool keep_original_workflow_id = 4; +} + +message ScheduleAction { + oneof action { + // All fields of NewWorkflowExecutionInfo are valid except for: + // - workflow_id_reuse_policy + // - cron_schedule + // The workflow id of the started workflow may not match this exactly, + // it may have a timestamp appended for uniqueness. + temporal.api.workflow.v1.NewWorkflowExecutionInfo start_workflow = 1; + } +} + +message ScheduleActionResult { + // Time that the action was taken (according to the schedule, including jitter). + google.protobuf.Timestamp schedule_time = 1; + + // Time that the action was taken (real time). + google.protobuf.Timestamp actual_time = 2; + + // If action was start_workflow: + temporal.api.common.v1.WorkflowExecution start_workflow_result = 11; + + // If the action was start_workflow, this field will reflect an + // eventually-consistent view of the started workflow's status. + temporal.api.enums.v1.WorkflowExecutionStatus start_workflow_status = 12; +} + +message ScheduleState { + // Informative human-readable message with contextual notes, e.g. the reason + // a schedule is paused. The system may overwrite this message on certain + // conditions, e.g. when pause-on-failure happens. + string notes = 1; + + // If true, do not take any actions based on the schedule spec. + bool paused = 2; + + // If limited_actions is true, decrement remaining_actions after each + // action, and do not take any more scheduled actions if remaining_actions + // is zero. Actions may still be taken by explicit request (i.e. trigger + // immediately or backfill). Skipped actions (due to overlap policy) do not + // count against remaining actions. + // If a schedule has no more remaining actions, then the schedule will be + // subject to automatic deletion (after several days). + bool limited_actions = 3; + + int64 remaining_actions = 4; +} + +message TriggerImmediatelyRequest { + // If set, override overlap policy for this one request. + temporal.api.enums.v1.ScheduleOverlapPolicy overlap_policy = 1; + + // Timestamp used for the identity of the target workflow. + // If not set the default value is the current time. + google.protobuf.Timestamp scheduled_time = 2; +} + +message BackfillRequest { + // Time range to evaluate schedule in. Currently, this time range is + // exclusive on start_time and inclusive on end_time. (This is admittedly + // counterintuitive and it may change in the future, so to be safe, use a + // start time strictly before a scheduled time.) Also note that an action + // nominally scheduled in the interval but with jitter that pushes it after + // end_time will not be included. + google.protobuf.Timestamp start_time = 1; + + google.protobuf.Timestamp end_time = 2; + + // If set, override overlap policy for this request. + temporal.api.enums.v1.ScheduleOverlapPolicy overlap_policy = 3; +} + +message SchedulePatch { + // If set, trigger one action immediately. + TriggerImmediatelyRequest trigger_immediately = 1; + + // If set, runs though the specified time period(s) and takes actions as if that time + // passed by right now, all at once. The overlap policy can be overridden for the + // scope of the backfill. + repeated BackfillRequest backfill_request = 2; + + // If set, change the state to paused or unpaused (respectively) and set the + // notes field to the value of the string. + string pause = 3; + + string unpause = 4; +} + +message ScheduleInfo { + // Number of actions taken so far. + int64 action_count = 1; + + // Number of times a scheduled action was skipped due to missing the catchup window. + int64 missed_catchup_window = 2; + + // Number of skipped actions due to overlap. + int64 overlap_skipped = 3; + + // Number of dropped actions due to buffer limit. + int64 buffer_dropped = 10; + + // Number of actions in the buffer. The buffer holds the actions that cannot + // be immediately triggered (due to the overlap policy). These actions can be a result of + // the normal schedule or a backfill. + int64 buffer_size = 11; + + // Currently-running workflows started by this schedule. (There might be + // more than one if the overlap policy allows overlaps.) + // Note that the run_ids in here are the original execution run ids as + // started by the schedule. If the workflows retried, did continue-as-new, + // or were reset, they might still be running but with a different run_id. + repeated temporal.api.common.v1.WorkflowExecution running_workflows = 9; + + // Most recent ten actual action times (including manual triggers). + repeated ScheduleActionResult recent_actions = 4; + + // Next ten scheduled action times. + repeated google.protobuf.Timestamp future_action_times = 5; + + // Timestamps of schedule creation and last update. + google.protobuf.Timestamp create_time = 6; + + google.protobuf.Timestamp update_time = 7; + + // Deprecated. + string invalid_schedule_error = 8 [deprecated = true]; + + // Size of the schedule's internal state (including payloads) in bytes. + int64 state_size_bytes = 12; +} + +message Schedule { + ScheduleSpec spec = 1; + + ScheduleAction action = 2; + + SchedulePolicies policies = 3; + + ScheduleState state = 4; +} + +// ScheduleListInfo is an abbreviated set of values from Schedule and ScheduleInfo +// that's returned in ListSchedules. +message ScheduleListInfo { + // From spec: + // Some fields are dropped from this copy of spec: timezone_data + ScheduleSpec spec = 1; + + // From action: + // Action is a oneof field, but we need to encode this in JSON and oneof fields don't work + // well with JSON. If action is start_workflow, this is set: + temporal.api.common.v1.WorkflowType workflow_type = 2; + + // From state: + string notes = 3; + + bool paused = 4; + + // From info (maybe fewer entries): + repeated ScheduleActionResult recent_actions = 5; + + repeated google.protobuf.Timestamp future_action_times = 6; + + // Size of the schedule's internal state (including payloads) in bytes. + int64 state_size_bytes = 7; +} + +// ScheduleListEntry is returned by ListSchedules. +message ScheduleListEntry { + string schedule_id = 1; + + temporal.api.common.v1.Memo memo = 2; + + temporal.api.common.v1.SearchAttributes search_attributes = 3; + + ScheduleListInfo info = 4; +} diff --git a/temporal/api/sdk/v1/enhanced_stack_trace.proto b/temporal/api/sdk/v1/enhanced_stack_trace.proto new file mode 100644 index 000000000..8f2300d87 --- /dev/null +++ b/temporal/api/sdk/v1/enhanced_stack_trace.proto @@ -0,0 +1,76 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.sdk.v1; + +option csharp_namespace = "Temporalio.Api.Sdk.V1"; +option go_package = "go.temporal.io/api/sdk/v1;sdk"; +option java_multiple_files = true; +option java_outer_classname = "EnhancedStackTraceProto"; +option java_package = "io.temporal.api.sdk.v1"; +option ruby_package = "Temporalio::Api::Sdk::V1"; + +// Internal structure used to create worker stack traces with references to code. +message EnhancedStackTrace { + // Information pertaining to the SDK that the trace has been captured from. + StackTraceSDKInfo sdk = 1; + + // Mapping of file path to file contents. + map sources = 2; + + // Collection of stacks captured. + repeated StackTrace stacks = 3; +} + +// Information pertaining to the SDK that the trace has been captured from. +// (-- api-linter: core::0123::resource-annotation=disabled +// aip.dev/not-precedent: Naming SDK version is optional. --) +message StackTraceSDKInfo { + // Name of the SDK + string name = 1; + + // Version string of the SDK + string version = 2; +} + +// "Slice" of a file starting at line_offset -- a line offset and code fragment corresponding to the worker's stack. +message StackTraceFileSlice { + // Only used (possibly) to trim the file without breaking syntax highlighting. This is not optional, unlike + // the `line` property of a `StackTraceFileLocation`. + // (-- api-linter: core::0141::forbidden-types=disabled + // aip.dev/not-precedent: These really shouldn't have negative values. --) + uint32 line_offset = 1; + + // Slice of a file with the respective OS-specific line terminator. + string content = 2; +} + +// More specific location details of a file: its path, precise line and column numbers if applicable, and function name if available. +// In essence, a pointer to a location in a file +message StackTraceFileLocation { + // Path to source file (absolute or relative). + // If the paths are relative, ensure that they are all relative to the same root. + string file_path = 1; + + // Optional; If possible, SDK should send this -- this is required for displaying the code location. + // If not provided, set to -1. + int32 line = 2; + + // Optional; if possible, SDK should send this. + // If not provided, set to -1. + int32 column = 3; + + // Function name this line belongs to, if applicable. + // Used for falling back to stack trace view. + string function_name = 4; + + // Flag to communicate whether a location should be hidden by default in the stack view. + bool internal_code = 5; +} + +// Collection of FileLocation messages from a single stack. +message StackTrace { + // Collection of `FileLocation`s, each for a stack frame that comprise a stack trace. + repeated StackTraceFileLocation locations = 1; +} diff --git a/temporal/api/sdk/v1/event_group_marker.proto b/temporal/api/sdk/v1/event_group_marker.proto new file mode 100644 index 000000000..753c57b86 --- /dev/null +++ b/temporal/api/sdk/v1/event_group_marker.proto @@ -0,0 +1,67 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.sdk.v1; + +import "temporal/api/common/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Sdk.V1"; +option go_package = "go.temporal.io/api/sdk/v1;sdk"; +option java_multiple_files = true; +option java_outer_classname = "EventGroupMarkerProto"; +option java_package = "io.temporal.api.sdk.v1"; +option ruby_package = "Temporalio::Api::Sdk::V1"; + +message EventGroupMarker { + // What this Marker represents. The variant determines whether the Marker was + // created explicitly by user code (label) or implicitly by the SDK on inbound + // signals/events (inbound_event) or update handlers (inbound_update). + oneof variant { + Label label = 1; + + InboundEvent inbound_event = 2; + + InboundUpdate inbound_update = 3; + } + + // A user-defined short-form string value to be used as the group's label. + message Label { + // Opaque identifier assigned by the SDK. + string id = 1; + + // This payload should be a "json/plain"-encoded payload that is a single + // JSON string for use in user interfaces. User interface formatting may not + // apply to this text when used in "label" situations. The payload data + // section is limited to 400 bytes by default. + // + // Payload only needs to be set on the first use of a given Marker ID; + // further references to an existing Marker ID reuse existing attributes of + // the referenced Marker -- i.e. further label payloads are ignored. + // + // Note that it is valid to have distinct Markers (i.e. distinct Marker IDs) + // in a given workflow execution that carry the same label, provided that + // they have the distinct ID. + temporal.api.common.v1.Payload label = 2; + } + + // The event ID of an event in the present workflow that triggered implicit + // creation of this group Marker. + // + // The target event's type must be one of the following: + // - `WORKFLOW_EXECUTION_STARTED` + // - `WORKFLOW_EXECUTION_SIGNALED` + message InboundEvent { + int64 inbound_event_id = 1; + } + + // The identifier of an inbound Update (request.meta.update_id) + // whose handler triggered implicit creation of this group Marker. + // + // Used in place of `inbound_event_id` for Updates because the event ID of the + // UpdateAccepted history event is not known until the Workflow Task is + // completed and recorded by the server, which may be too late. + message InboundUpdate { + string inbound_update_id = 1; + } +} diff --git a/temporal/api/sdk/v1/external_storage.proto b/temporal/api/sdk/v1/external_storage.proto new file mode 100644 index 000000000..940d66042 --- /dev/null +++ b/temporal/api/sdk/v1/external_storage.proto @@ -0,0 +1,23 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.sdk.v1; + +option csharp_namespace = "Temporalio.Api.Sdk.V1"; +option go_package = "go.temporal.io/api/sdk/v1;sdk"; +option java_multiple_files = true; +option java_outer_classname = "ExternalStorageProto"; +option java_package = "io.temporal.api.sdk.v1"; +option ruby_package = "Temporalio::Api::Sdk::V1"; + +// ExternalStorageReference identifies a payload stored in an external storage system. +// It is used as a claim-check token, allowing the actual payload data to be retrieved +// from the named driver using the provided claim data. +message ExternalStorageReference { + // The name of the storage driver responsible for retrieving the payload. + string driver_name = 1; + + // Driver-specific key-value pairs that identify and provide access to the stored payload. + map claim_data = 2; +} diff --git a/temporal/api/sdk/v1/task_complete_metadata.proto b/temporal/api/sdk/v1/task_complete_metadata.proto new file mode 100644 index 000000000..0e9aaf033 --- /dev/null +++ b/temporal/api/sdk/v1/task_complete_metadata.proto @@ -0,0 +1,56 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.sdk.v1; + +option csharp_namespace = "Temporalio.Api.Sdk.V1"; +option go_package = "go.temporal.io/api/sdk/v1;sdk"; +option java_multiple_files = true; +option java_outer_classname = "TaskCompleteMetadataProto"; +option java_package = "io.temporal.api.sdk.v1"; +option ruby_package = "Temporalio::Api::Sdk::V1"; + +message WorkflowTaskCompletedMetadata { + // Internal flags used by the core SDK. SDKs using flags must comply with the following behavior: + // + // During replay: + // * If a flag is not recognized (value is too high or not defined), it must fail the workflow + // task. + // * If a flag is recognized, it is stored in a set of used flags for the run. Code checks for + // that flag during and after this WFT are allowed to assume that the flag is present. + // * If a code check for a flag does not find the flag in the set of used flags, it must take + // the branch corresponding to the absence of that flag. + // + // During non-replay execution of new WFTs: + // * The SDK is free to use all flags it knows about. It must record any newly-used (IE: not + // previously recorded) flags when completing the WFT. + // + // SDKs which are too old to even know about this field at all are considered to produce + // undefined behavior if they replay workflows which used this mechanism. + // + // (-- api-linter: core::0141::forbidden-types=disabled + // aip.dev/not-precedent: These really shouldn't have negative values. --) + repeated uint32 core_used_flags = 1; + + // Flags used by the SDK lang. No attempt is made to distinguish between different SDK languages + // here as processing a workflow with a different language than the one which authored it is + // already undefined behavior. See `core_used_patches` for more. + // + // (-- api-linter: core::0141::forbidden-types=disabled + // aip.dev/not-precedent: These really shouldn't have negative values. --) + repeated uint32 lang_used_flags = 2; + + // Name of the SDK that processed the task. This is usually something like "temporal-go" and is + // usually the same as client-name gRPC header. This should only be set if its value changed + // since the last time recorded on the workflow (or be set on the first task). + // + // (-- api-linter: core::0122::name-suffix=disabled + // aip.dev/not-precedent: We're ok with a name suffix here. --) + string sdk_name = 3; + + // Version of the SDK that processed the task. This is usually something like "1.20.0" and is + // usually the same as client-version gRPC header. This should only be set if its value changed + // since the last time recorded on the workflow (or be set on the first task). + string sdk_version = 4; +} diff --git a/temporal/api/sdk/v1/user_metadata.proto b/temporal/api/sdk/v1/user_metadata.proto new file mode 100644 index 000000000..da2b603f4 --- /dev/null +++ b/temporal/api/sdk/v1/user_metadata.proto @@ -0,0 +1,28 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.sdk.v1; + +import "temporal/api/common/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Sdk.V1"; +option go_package = "go.temporal.io/api/sdk/v1;sdk"; +option java_multiple_files = true; +option java_outer_classname = "UserMetadataProto"; +option java_package = "io.temporal.api.sdk.v1"; +option ruby_package = "Temporalio::Api::Sdk::V1"; + +// Information a user can set, often for use by user interfaces. +message UserMetadata { + // Short-form text that provides a summary. This payload should be a "json/plain"-encoded payload + // that is a single JSON string for use in user interfaces. User interface formatting may not + // apply to this text when used in "title" situations. The payload data section is limited to 400 + // bytes by default. + temporal.api.common.v1.Payload summary = 1; + + // Long-form text that provides details. This payload should be a "json/plain"-encoded payload + // that is a single JSON string for use in user interfaces. User interface formatting may apply to + // this text in common use. The payload data section is limited to 20000 bytes by default. + temporal.api.common.v1.Payload details = 2; +} diff --git a/temporal/api/sdk/v1/worker_config.proto b/temporal/api/sdk/v1/worker_config.proto new file mode 100644 index 000000000..8a6c8241a --- /dev/null +++ b/temporal/api/sdk/v1/worker_config.proto @@ -0,0 +1,39 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.sdk.v1; + +option csharp_namespace = "Temporalio.Api.Sdk.V1"; +option go_package = "go.temporal.io/api/sdk/v1;sdk"; +option java_multiple_files = true; +option java_outer_classname = "WorkerConfigProto"; +option java_package = "io.temporal.api.sdk.v1"; +option ruby_package = "Temporalio::Api::Sdk::V1"; + +message WorkerConfig { + message SimplePollerBehavior { + int32 max_pollers = 1; + } + + message AutoscalingPollerBehavior { + // At least this many poll calls will always be attempted (assuming slots are available). + // Cannot be zero. + int32 min_pollers = 1; + + // At most this many poll calls will ever be open at once. Must be >= `minimum`. + int32 max_pollers = 2; + + // This many polls will be attempted initially before scaling kicks in. Must be between + // `minimum` and `maximum`. + int32 initial_pollers = 3; + } + + int32 workflow_cache_size = 1; + + oneof poller_behavior { + SimplePollerBehavior simple_poller_behavior = 2; + + AutoscalingPollerBehavior autoscaling_poller_behavior = 3; + } +} diff --git a/temporal/api/sdk/v1/workflow_metadata.proto b/temporal/api/sdk/v1/workflow_metadata.proto new file mode 100644 index 000000000..31b41e9af --- /dev/null +++ b/temporal/api/sdk/v1/workflow_metadata.proto @@ -0,0 +1,53 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.sdk.v1; + +option csharp_namespace = "Temporalio.Api.Sdk.V1"; +option go_package = "go.temporal.io/api/sdk/v1;sdk"; +option java_multiple_files = true; +option java_outer_classname = "WorkflowMetadataProto"; +option java_package = "io.temporal.api.sdk.v1"; +option ruby_package = "Temporalio::Api::Sdk::V1"; + +// The name of the query to retrieve this information is `__temporal_workflow_metadata`. +message WorkflowMetadata { + // Metadata provided at declaration or creation time. + WorkflowDefinition definition = 1; + + // Current long-form details of the workflow's state. This is used by user interfaces to show + // long-form text. This text may be formatted by the user interface. + string current_details = 2; +} + +// (-- api-linter: core::0203::optional=disabled --) +message WorkflowDefinition { + // A name scoped by the task queue that maps to this workflow definition. + // If missing, this workflow is a dynamic workflow. + string type = 1; + + // Query definitions, sorted by name. + repeated WorkflowInteractionDefinition query_definitions = 2; + + // Signal definitions, sorted by name. + repeated WorkflowInteractionDefinition signal_definitions = 3; + + // Update definitions, sorted by name. + repeated WorkflowInteractionDefinition update_definitions = 4; +} + +// (-- api-linter: core::0123::resource-annotation=disabled +// aip.dev/not-precedent: The `name` field is optional. --) +// (-- api-linter: core::0203::optional=disabled --) +message WorkflowInteractionDefinition { + // An optional name for the handler. If missing, it represents + // a dynamic handler that processes any interactions not handled by others. + // There is at most one dynamic handler per workflow and interaction kind. + string name = 1; + + // An optional interaction description provided by the application. + // By convention, external tools may interpret its first part, + // i.e., ending with a line break, as a summary of the description. + string description = 2; +} diff --git a/temporal/api/taskqueue/v1/message.proto b/temporal/api/taskqueue/v1/message.proto new file mode 100644 index 000000000..dd3e4bfa8 --- /dev/null +++ b/temporal/api/taskqueue/v1/message.proto @@ -0,0 +1,402 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.taskqueue.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/deployment/v1/message.proto"; +import "temporal/api/enums/v1/task_queue.proto"; + +option csharp_namespace = "Temporalio.Api.TaskQueue.V1"; +option go_package = "go.temporal.io/api/taskqueue/v1;taskqueue"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.taskqueue.v1"; +option ruby_package = "Temporalio::Api::TaskQueue::V1"; + +// See https://docs.temporal.io/docs/concepts/task-queues/ +message TaskQueue { + string name = 1; + + // Default: TASK_QUEUE_KIND_NORMAL. + temporal.api.enums.v1.TaskQueueKind kind = 2; + + // Iff kind == TASK_QUEUE_KIND_STICKY, then this field contains the name of + // the normal task queue that the sticky worker is running on. + string normal_name = 3; +} + +// Only applies to activity task queues +message TaskQueueMetadata { + // Allows throttling dispatch of tasks from this queue + google.protobuf.DoubleValue max_tasks_per_second = 1; +} + +message TaskQueueVersioningInfo { + // Specifies which Deployment Version should receive new workflow executions and tasks of + // existing unversioned or AutoUpgrade workflows. + // Nil value represents all the unversioned workers (those with `UNVERSIONED` (or unspecified) `WorkerVersioningMode`.) + // Note: Current Version is overridden by the Ramping Version for a portion of traffic when ramp percentage + // is non-zero (see `ramping_deployment_version` and `ramping_version_percentage`). + temporal.api.deployment.v1.WorkerDeploymentVersion current_deployment_version = 7; + + // Deprecated. Use `current_deployment_version`. + string current_version = 1 [deprecated = true]; + + // When ramp percentage is non-zero, that portion of traffic is shifted from the Current Version to the Ramping Version. + // Must always be different from `current_deployment_version` unless both are nil. + // Nil value represents all the unversioned workers (those with `UNVERSIONED` (or unspecified) `WorkerVersioningMode`.) + // Note that it is possible to ramp from one Version to another Version, or from unversioned + // workers to a particular Version, or from a particular Version to unversioned workers. + temporal.api.deployment.v1.WorkerDeploymentVersion ramping_deployment_version = 9; + + // Deprecated. Use `ramping_deployment_version`. + string ramping_version = 2 [deprecated = true]; + + // Percentage of tasks that are routed to the Ramping Version instead of the Current Version. + // Valid range: [0, 100]. A 100% value means the Ramping Version is receiving full traffic but + // not yet "promoted" to be the Current Version, likely due to pending validations. + // A 0% value means the Ramping Version is receiving no traffic. + float ramping_version_percentage = 3; + + // Last time versioning information of this Task Queue changed. + google.protobuf.Timestamp update_time = 4; +} + +// Used for specifying versions the caller is interested in. +message TaskQueueVersionSelection { + // Include specific Build IDs. + repeated string build_ids = 1; + + // Include the unversioned queue. + bool unversioned = 2; + + // Include all active versions. A version is considered active if, in the last few minutes, + // it has had new tasks or polls, or it has been the subject of certain task queue API calls. + bool all_active = 3; +} + +message TaskQueueVersionInfo { + // Task Queue info per Task Type. Key is the numerical value of the temporal.api.enums.v1.TaskQueueType enum. + map types_info = 1; + + // Task Reachability is eventually consistent; there may be a delay until it converges to the most + // accurate value but it is designed in a way to take the more conservative side until it converges. + // For example REACHABLE is more conservative than CLOSED_WORKFLOWS_ONLY. + // + // Note: future activities who inherit their workflow's Build ID but not its Task Queue will not be + // accounted for reachability as server cannot know if they'll happen as they do not use + // assignment rules of their Task Queue. Same goes for Child Workflows or Continue-As-New Workflows + // who inherit the parent/previous workflow's Build ID but not its Task Queue. In those cases, make + // sure to query reachability for the parent/previous workflow's Task Queue as well. + temporal.api.enums.v1.BuildIdTaskReachability task_reachability = 2; +} + +message TaskQueueTypeInfo { + // Unversioned workers (with `useVersioning=false`) are reported in unversioned result even if they set a Build ID. + repeated PollerInfo pollers = 1; + + TaskQueueStats stats = 2; +} + +// TaskQueueStats contains statistics about task queue backlog and activity. +// +// For workflow task queue type, this result is partial because tasks sent to sticky queues are not included. Read +// comments above each metric to understand the impact of sticky queue exclusion on that metric accuracy. +message TaskQueueStats { + // The approximate number of tasks backlogged in this task queue. May count expired tasks but eventually + // converges to the right value. Can be relied upon for scaling decisions. + // + // Special note for workflow task queue type: this metric does not count sticky queue tasks. However, because + // those tasks only remain valid for a few seconds, the inaccuracy becomes less significant as the backlog size + // grows. + int64 approximate_backlog_count = 1; + + // Approximate age of the oldest task in the backlog based on the creation time of the task at the head of + // the queue. Can be relied upon for scaling decisions. + // + // Special note for workflow task queue type: this metric does not count sticky queue tasks. However, because + // those tasks only remain valid for a few seconds, they should not affect the result when backlog is older than + // few seconds. + google.protobuf.Duration approximate_backlog_age = 2; + + // The approximate tasks per second added to the task queue, averaging the last 30 seconds. These includes tasks + // whether or not they were added to/dispatched from the backlog or they were dispatched immediately without going + // to the backlog (sync-matched). + // + // The difference between `tasks_add_rate` and `tasks_dispatch_rate` is a reliable metric for the rate at which + // backlog grows/shrinks. + // + // Note: the actual tasks delivered to the workers may significantly be higher than the numbers reported by + // tasks_add_rate, because: + // - Tasks can be sent to workers without going to the task queue. This is called Eager dispatch. Eager dispatch is + // enable for activities by default in the latest SDKs. + // - Tasks going to Sticky queue are not accounted for. Note that, typically, only the first workflow task of each + // workflow goes to a normal queue, and the rest workflow tasks go to the Sticky queue associated with a specific + // worker instance. + float tasks_add_rate = 3; + + // The approximate tasks per second dispatched from the task queue, averaging the last 30 seconds. These includes + // tasks whether or not they were added to/dispatched from the backlog or they were dispatched immediately without + // going to the backlog (sync-matched). + // + // The difference between `tasks_add_rate` and `tasks_dispatch_rate` is a reliable metric for the rate at which + // backlog grows/shrinks. + // + // Note: the actual tasks delivered to the workers may significantly be higher than the numbers reported by + // tasks_dispatch_rate, because: + // - Tasks can be sent to workers without going to the task queue. This is called Eager dispatch. Eager dispatch is + // enable for activities by default in the latest SDKs. + // - Tasks going to Sticky queue are not accounted for. Note that, typically, only the first workflow task of each + // workflow goes to a normal queue, and the rest workflow tasks go to the Sticky queue associated with a specific + // worker instance. + float tasks_dispatch_rate = 4; + + // Whether rate limiting blocked any dispatches within the recent observation window (approximately + // 30 seconds). When true, adding more workers will not increase throughput — the bottleneck is the + // rate limit, not worker count. This field is useful for auto-scaling systems to avoid unnecessary + // scale-up. + bool rate_limiting_active = 5; +} + +// Deprecated. Use `InternalTaskQueueStatus`. This is kept until `DescribeTaskQueue` supports legacy behavior. +message TaskQueueStatus { + int64 backlog_count_hint = 1; + + int64 read_level = 2; + + int64 ack_level = 3; + + double rate_per_second = 4; + + TaskIdBlock task_id_block = 5; +} + +message TaskIdBlock { + int64 start_id = 1; + + int64 end_id = 2; +} + +message TaskQueuePartitionMetadata { + string key = 1; + + string owner_host_name = 2; +} + +message PollerInfo { + google.protobuf.Timestamp last_access_time = 1; + + string identity = 2; + + double rate_per_second = 3; + + // If a worker has opted into the worker versioning feature while polling, its capabilities will + // appear here. + // Deprecated. Replaced by deployment_options. + temporal.api.common.v1.WorkerVersionCapabilities worker_version_capabilities = 4 [deprecated = true]; + + // Worker deployment options that SDK sent to server. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 5; +} + +message StickyExecutionAttributes { + TaskQueue worker_task_queue = 1; + + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 2; +} + +// Used by the worker versioning APIs, represents an unordered set of one or more versions which are +// considered to be compatible with each other. Currently the versions are always worker build IDs. +message CompatibleVersionSet { + // All the compatible versions, unordered, except for the last element, which is considered the set "default". + repeated string build_ids = 1; +} + +// Reachability of tasks for a worker on a single task queue. +message TaskQueueReachability { + string task_queue = 1; + + // Task reachability for a worker in a single task queue. + // See the TaskReachability docstring for information about each enum variant. + // If reachability is empty, this worker is considered unreachable in this task queue. + repeated temporal.api.enums.v1.TaskReachability reachability = 2; +} + +// Reachability of tasks for a worker by build id, in one or more task queues. +message BuildIdReachability { + // A build id or empty if unversioned. + string build_id = 1; + + // Reachability per task queue. + repeated TaskQueueReachability task_queue_reachability = 2; +} + +message RampByPercentage { + // Acceptable range is [0,100). + float ramp_percentage = 1; +} + +// Assignment rules are applied to *new* Workflow and Activity executions at +// schedule time to assign them to a Build ID. +// +// Assignment rules will not be used in the following cases: +// - Child Workflows or Continue-As-New Executions who inherit their +// parent/previous Workflow's assigned Build ID (by setting the +// `inherit_build_id` flag - default behavior in SDKs when the same Task Queue +// is used.) +// - An Activity that inherits the assigned Build ID of its Workflow (by +// setting the `use_workflow_build_id` flag - default behavior in SDKs +// when the same Task Queue is used.) +// +// In absence of (applicable) redirect rules (`CompatibleBuildIdRedirectRule`s) +// the task will be dispatched to Workers of the Build ID determined by the +// assignment rules (or inherited). Otherwise, the final Build ID will be +// determined by the redirect rules. +// +// Once a Workflow completes its first Workflow Task in a particular Build ID it +// stays in that Build ID regardless of changes to assignment rules. Redirect +// rules can be used to move the workflow to another compatible Build ID. +// +// When using Worker Versioning on a Task Queue, in the steady state, +// there should typically be a single assignment rule to send all new executions +// to the latest Build ID. Existence of at least one such "unconditional" +// rule at all times is enforces by the system, unless the `force` flag is used +// by the user when replacing/deleting these rules (for exceptional cases). +// +// During a deployment, one or more additional rules can be added to assign a +// subset of the tasks to a new Build ID based on a "ramp percentage". +// +// When there are multiple assignment rules for a Task Queue, the rules are +// evaluated in order, starting from index 0. The first applicable rule will be +// applied and the rest will be ignored. +// +// In the event that no assignment rule is applicable on a task (or the Task +// Queue is simply not versioned), the tasks will be dispatched to an +// unversioned Worker. +message BuildIdAssignmentRule { + string target_build_id = 1; + + // If a ramp is provided, this rule will be applied only to a sample of + // tasks according to the provided percentage. + // This option can be used only on "terminal" Build IDs (the ones not used + // as source in any redirect rules). + oneof ramp { + // This ramp is useful for gradual Blue/Green deployments (and similar) + // where you want to send a certain portion of the traffic to the target + // Build ID. + RampByPercentage percentage_ramp = 3; + } +} + +// These rules apply to tasks assigned to a particular Build ID +// (`source_build_id`) to redirect them to another *compatible* Build ID +// (`target_build_id`). +// +// It is user's responsibility to ensure that the target Build ID is compatible +// with the source Build ID (e.g. by using the Patching API). +// +// Most deployments are not expected to need these rules, however following +// situations can greatly benefit from redirects: +// - Need to move long-running Workflow Executions from an old Build ID to a +// newer one. +// - Need to hotfix some broken or stuck Workflow Executions. +// +// In steady state, redirect rules are beneficial when dealing with old +// Executions ran on now-decommissioned Build IDs: +// - To redirecting the Workflow Queries to the current (compatible) Build ID. +// - To be able to Reset an old Execution so it can run on the current +// (compatible) Build ID. +// +// Redirect rules can be chained. +message CompatibleBuildIdRedirectRule { + string source_build_id = 1; + + // Target Build ID must be compatible with the Source Build ID; that is it + // must be able to process event histories made by the Source Build ID by + // using [Patching](https://docs.temporal.io/workflows#patching) or other + // means. + string target_build_id = 2; +} + +message TimestampedBuildIdAssignmentRule { + BuildIdAssignmentRule rule = 1; + + google.protobuf.Timestamp create_time = 2; +} + +message TimestampedCompatibleBuildIdRedirectRule { + CompatibleBuildIdRedirectRule rule = 1; + + google.protobuf.Timestamp create_time = 2; +} + +message PollerGroupInfo { + string id = 1; + + float weight = 2; +} + +// A versioned snapshot of the poller groups the client should use for future polls to a task +// queue. The version is monotonically increasing so that a client can ignore a snapshot that is +// older than the one it has already applied. +message PollerGroupsInfo { + // Monotonically increasing version of this snapshot. A client should ignore any snapshot whose + // version is not greater than the one it last applied. + int64 version = 1; + + // The weighted list of poller groups the client should use for future polls to this task queue. + repeated PollerGroupInfo poller_groups = 2; +} + +// Attached to task responses to give hints to the SDK about how it may adjust its number of +// pollers. +message PollerScalingDecision { + // How many poll requests to suggest should be added or removed, if any. As of now, server only + // scales up or down by 1. However, SDKs should allow for other values (while staying within + // defined min/max). + // + // The SDK is free to ignore this suggestion, EX: making more polls would not make sense because + // all slots are already occupied. + int32 poll_request_delta_suggestion = 1; +} + +message RateLimit { + // Zero is a valid rate limit. + float requests_per_second = 1; +} + +message ConfigMetadata { + // Reason for why the config was set. + string reason = 1; + + // Identity of the last updater. + // Set by the request's identity field. + string update_identity = 2; + + // Time of the last update. + google.protobuf.Timestamp update_time = 3; +} + +message RateLimitConfig { + RateLimit rate_limit = 1; + + ConfigMetadata metadata = 2; +} + +message TaskQueueConfig { + // Unless modified, this is the system-defined rate limit. + RateLimitConfig queue_rate_limit = 1; + + // If set, each individual fairness key will be limited to this rate, scaled by the weight of the fairness key. + RateLimitConfig fairness_keys_rate_limit_default = 2; + + // If set, overrides the fairness weights for the corresponding fairness keys. + map fairness_weight_overrides = 3; +} diff --git a/temporal/api/update/v1/message.proto b/temporal/api/update/v1/message.proto new file mode 100644 index 000000000..e552ba68e --- /dev/null +++ b/temporal/api/update/v1/message.proto @@ -0,0 +1,108 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.update.v1; + +import "temporal/api/common/v1/message.proto"; +import "temporal/api/enums/v1/update.proto"; +import "temporal/api/failure/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Update.V1"; +option go_package = "go.temporal.io/api/update/v1;update"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.update.v1"; +option ruby_package = "Temporalio::Api::Update::V1"; + +// Specifies client's intent to wait for Update results. +message WaitPolicy { + // Indicates the Update lifecycle stage that the Update must reach before + // API call is returned. + // NOTE: This field works together with API call timeout which is limited by + // server timeout (maximum wait time). If server timeout is expired before + // user specified timeout, API call returns even if specified stage is not reached. + temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage lifecycle_stage = 1; +} + +// The data needed by a client to refer to a previously invoked Workflow Update. +message UpdateRef { + temporal.api.common.v1.WorkflowExecution workflow_execution = 1; + + string update_id = 2; +} + +// The outcome of a Workflow Update: success or failure. +message Outcome { + oneof value { + temporal.api.common.v1.Payloads success = 1; + + temporal.api.failure.v1.Failure failure = 2; + } +} + +// Metadata about a Workflow Update. +message Meta { + // An ID with workflow-scoped uniqueness for this Update. + string update_id = 1; + + // A string identifying the agent that requested this Update. + string identity = 2; +} + +message Input { + // Headers that are passed with the Update from the requesting entity. + // These can include things like auth or tracing tokens. + temporal.api.common.v1.Header header = 1; + + // The name of the Update handler to invoke on the target Workflow. + string name = 2; + + // The arguments to pass to the named Update handler. + temporal.api.common.v1.Payloads args = 3; +} + +// The client request that triggers a Workflow Update. +message Request { + Meta meta = 1; + + Input input = 2; + + // The request ID of the request. + string request_id = 3; + + // Callbacks to be called by the server when this update reaches a terminal state. + repeated temporal.api.common.v1.Callback completion_callbacks = 4; + + // Links to be associated with this update. + repeated temporal.api.common.v1.Link links = 5; +} + +// An Update protocol message indicating that a Workflow Update has been rejected. +message Rejection { + string rejected_request_message_id = 1; + + int64 rejected_request_sequencing_event_id = 2; + + Request rejected_request = 3; + + temporal.api.failure.v1.Failure failure = 4; +} + +// An Update protocol message indicating that a Workflow Update has +// been accepted (i.e. passed the worker-side validation phase). +message Acceptance { + string accepted_request_message_id = 1; + + int64 accepted_request_sequencing_event_id = 2; + + Request accepted_request = 3; +} + +// An Update protocol message indicating that a Workflow Update has +// completed with the contained outcome. +message Response { + Meta meta = 1; + + Outcome outcome = 2; +} diff --git a/temporal/api/version/v1/message.proto b/temporal/api/version/v1/message.proto new file mode 100644 index 000000000..1d38f004d --- /dev/null +++ b/temporal/api/version/v1/message.proto @@ -0,0 +1,44 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.version.v1; + +import "google/protobuf/timestamp.proto"; +import "temporal/api/enums/v1/common.proto"; + +option csharp_namespace = "Temporalio.Api.Version.V1"; +option go_package = "go.temporal.io/api/version/v1;version"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.version.v1"; +option ruby_package = "Temporalio::Api::Version::V1"; + +// ReleaseInfo contains information about specific version of temporal. +message ReleaseInfo { + string version = 1; + + google.protobuf.Timestamp release_time = 2; + + string notes = 3; +} + +// Alert contains notification and severity. +message Alert { + string message = 1; + + temporal.api.enums.v1.Severity severity = 2; +} + +// VersionInfo contains details about current and recommended release versions as well as alerts and upgrade instructions. +message VersionInfo { + ReleaseInfo current = 1; + + ReleaseInfo recommended = 2; + + string instructions = 3; + + repeated Alert alerts = 4; + + google.protobuf.Timestamp last_update_time = 5; +} diff --git a/temporal/api/worker/v1/message.proto b/temporal/api/worker/v1/message.proto new file mode 100644 index 000000000..a89c068b4 --- /dev/null +++ b/temporal/api/worker/v1/message.proto @@ -0,0 +1,395 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.worker.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/deployment/v1/message.proto"; +import "temporal/api/enums/v1/common.proto"; + +option csharp_namespace = "Temporalio.Api.Worker.V1"; +option go_package = "go.temporal.io/api/worker/v1;worker"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.worker.v1"; +option ruby_package = "Temporalio::Api::Worker::V1"; + +message WorkerPollerInfo { + // Number of polling RPCs that are currently in flight. + int32 current_pollers = 1; + + google.protobuf.Timestamp last_successful_poll_time = 2; + + // Set true if the number of concurrent pollers is auto-scaled + bool is_autoscaling = 3; +} + +message WorkerSlotsInfo { + // Number of slots available for the worker to specific tasks. + // May be -1 if the upper bound is not known. + int32 current_available_slots = 1; + + // Number of slots used by the worker for specific tasks. + int32 current_used_slots = 2; + + // Kind of the slot supplier, which is used to determine how the slots are allocated. + // Possible values: "Fixed | ResourceBased | Custom String" + string slot_supplier_kind = 3; + + // Total number of tasks processed (completed both successfully and unsuccesfully, or any other way) + // by the worker since the worker started. This is a cumulative counter. + int32 total_processed_tasks = 4; + + // Total number of failed tasks processed by the worker so far. + int32 total_failed_tasks = 5; + + // Number of tasks processed in since the last heartbeat from the worker. + // This is a cumulative counter, and it is reset to 0 each time the worker sends a heartbeat. + // Contains both successful and failed tasks. + int32 last_interval_processed_tasks = 6; + + // Number of failed tasks processed since the last heartbeat from the worker. + int32 last_interval_failure_tasks = 7; +} + +// Holds everything needed to identify the worker host/process context +message WorkerHostInfo { + // Worker host identifier. + string host_name = 1; + + // Worker grouping identifier. A key to group workers that share the same client+namespace+process. + // This will be used to build the worker command nexus task queue name: + // "temporal-sys/worker-commands/{worker_grouping_key}" + string worker_grouping_key = 5; + + // Worker process identifier. This id only needs to be unique + // within one host (so using e.g. a unix pid would be appropriate). + string process_id = 2; + + // System used CPU as a float in the range [0.0, 1.0] where 1.0 is defined as all + // cores on the host pegged. + float current_host_cpu_usage = 3; + + // System used memory as a float in the range [0.0, 1.0] where 1.0 is defined as + // all available memory on the host is used. + float current_host_mem_usage = 4; +} + +// Worker info message, contains information about the worker and its current state. +// All information is provided by the worker itself. +// (-- api-linter: core::0140::prepositions=disabled +// aip.dev/not-precedent: Removing those words make names less clear. --) +message WorkerHeartbeat { + // Worker identifier, should be unique for the namespace. + // It is distinct from worker identity, which is not necessarily namespace-unique. + string worker_instance_key = 1; + + // Worker identity, set by the client, may not be unique. + // Usually host_name+(user group name)+process_id, but can be overwritten by the user. + string worker_identity = 2; + + // Worker host information. + WorkerHostInfo host_info = 3; + + // Task queue this worker is polling for tasks. + string task_queue = 4; + + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 5; + + string sdk_name = 6; + + string sdk_version = 7; + + // Worker status. Defined by SDK. + temporal.api.enums.v1.WorkerStatus status = 8; + + // Worker start time. + // It can be used to determine worker uptime. (current time - start time) + google.protobuf.Timestamp start_time = 9; + + // Timestamp of this heartbeat, coming from the worker. Worker should set it to "now". + // Note that this timestamp comes directly from the worker and is subject to workers' clock skew. + google.protobuf.Timestamp heartbeat_time = 10; + + // Elapsed time since the last heartbeat from the worker. + google.protobuf.Duration elapsed_since_last_heartbeat = 11; + + WorkerSlotsInfo workflow_task_slots_info = 12; + + WorkerSlotsInfo activity_task_slots_info = 13; + + WorkerSlotsInfo nexus_task_slots_info = 14; + + WorkerSlotsInfo local_activity_slots_info = 15; + + WorkerPollerInfo workflow_poller_info = 16; + + WorkerPollerInfo workflow_sticky_poller_info = 17; + + WorkerPollerInfo activity_poller_info = 18; + + WorkerPollerInfo nexus_poller_info = 19; + + // A Workflow Task found a cached Workflow Execution to run against. + int32 total_sticky_cache_hit = 20; + + // A Workflow Task did not find a cached Workflow execution to run against. + int32 total_sticky_cache_miss = 21; + + // Current cache size, expressed in number of Workflow Executions. + int32 current_sticky_cache_size = 22; + + // Plugins currently in use by this SDK. + repeated PluginInfo plugins = 23; + + // Storage drivers in use by this SDK. + repeated StorageDriverInfo drivers = 24; + + // Information about the environment this SDK is running in. + EnvironmentInfo environment = 25; +} + +// Detailed worker information. +message WorkerInfo { + WorkerHeartbeat worker_heartbeat = 1; +} + +// Limited worker information returned in the list response. +// When adding fields here, ensure that it is also added to WorkerInfo (as it carries the full worker information). +message WorkerListInfo { + // Worker identifier, should be unique for the namespace. + // It is distinct from worker identity, which is not necessarily namespace-unique. + string worker_instance_key = 1; + + // Worker identity, set by the client, may not be unique. + // Usually host_name+(user group name)+process_id, but can be overwritten by the user. + string worker_identity = 2; + + // Task queue this worker is polling for tasks. + string task_queue = 3; + + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 4; + + string sdk_name = 5; + + string sdk_version = 6; + + // Worker status. Defined by SDK. + temporal.api.enums.v1.WorkerStatus status = 7; + + // Worker start time. + // It can be used to determine worker uptime. (current time - start time) + google.protobuf.Timestamp start_time = 8; + + // Worker host identifier. + string host_name = 9; + + // Worker grouping identifier. A key to group workers that share the same client+namespace+process. + // This will be used to build the worker command nexus task queue name: + // "temporal-sys/worker-commands/{worker_grouping_key}" + string worker_grouping_key = 10; + + // Worker process identifier. This id only needs to be unique + // within one host (so using e.g. a unix pid would be appropriate). + string process_id = 11; + + // Plugins currently in use by this SDK. + repeated PluginInfo plugins = 12; + + // Storage drivers in use by this SDK. + repeated StorageDriverInfo drivers = 13; +} + +message PluginInfo { + // The name of the plugin, required. + string name = 1; + + // The version of the plugin, may be empty. + string version = 2; +} + +message StorageDriverInfo { + // The type of the driver, required. + string type = 1; +} + +message EnvironmentInfo { + message Runtime { + enum RuntimeType { + // Should never actually be set, exists to follow convention of having a default. + // SDKs should just leave `runtimes` empty if none can be determined. + RUNTIME_TYPE_UNSPECIFIED = 0; + + RUNTIME_TYPE_JVM = 1; + + RUNTIME_TYPE_CPYTHON = 2; + + RUNTIME_TYPE_NODE = 3; + + RUNTIME_TYPE_BUN = 4; + + RUNTIME_TYPE_CRUBY = 5; + + RUNTIME_TYPE_GO = 6; + + RUNTIME_TYPE_DOTNET_FRAMEWORK = 7; + + RUNTIME_TYPE_DOTNET_CORE = 8; + + RUNTIME_TYPE_NATIVE = 9; + + RUNTIME_TYPE_ROADRUNNER = 10; + } + + // The type of the runtime. + RuntimeType type = 1; + + // The version of the runtime, if obtainable. + string version = 2; + } + + message HostingEnvironment { + // What kind of hosting environment we're running in. This list is about what can actually be + // detected reliably and is unrelated to what SDKs can actually run in. + enum HostingEnvironmentType { + // Should never actually be set, exists to follow convention of having a default. + // SDKs should just leave `hosting_environments` empty if none can be determined. + HOSTING_ENVIRONMENT_TYPE_UNSPECIFIED = 0; + + // Should always be in the list if we're running inside a docker container + HOSTING_ENVIRONMENT_TYPE_DOCKER = 1; + + // Should always be in the list if we're running inside any k8s environment + HOSTING_ENVIRONMENT_TYPE_K8S = 2; + + // Detect via `AWS_LAMBDA_FUNCTION_NAME` + HOSTING_ENVIRONMENT_TYPE_AWS_LAMBDA = 3; + + // Detect via `ECS_CONTAINER_METADATA_URI_V4` or `ECS_CONTAINER_METADATA_URI` + HOSTING_ENVIRONMENT_TYPE_AWS_ECS = 4; + + // Detect via `K_SERVICE` + HOSTING_ENVIRONMENT_TYPE_GOOGLE_CLOUD_RUN = 6; + + // Detect via `GAE_SERVICE` + HOSTING_ENVIRONMENT_TYPE_GOOGLE_APP_ENGINE = 7; + + // Detect via `WEBSITE_SITE_NAME` + HOSTING_ENVIRONMENT_TYPE_AZURE_APP_SERVICE = 8; + + // Detect via `FUNCTIONS_EXTENSION_VERSION` + HOSTING_ENVIRONMENT_TYPE_AZURE_FUNCTIONS = 9; + + // Detect via `CONTAINER_APP_NAME` + HOSTING_ENVIRONMENT_TYPE_AZURE_CONTAINER_APPS = 10; + } + + // The type of hosting environment. + HostingEnvironmentType type = 1; + + // The version of the hosting environment, if obtainable. + string version = 2; + } + + enum Architecture { + ARCHITECTURE_UNSPECIFIED = 0; + + ARCHITECTURE_AMD64 = 1; + + ARCHITECTURE_ARM64 = 2; + } + + message Platform { + oneof variant { + LinuxPlatform linux = 1; + + MacOSPlatform macos = 2; + + WindowsPlatform windows = 3; + } + } + + message LinuxPlatform { + enum Libc { + LIBC_UNSPECIFIED = 0; + + LIBC_GLIBC = 1; + + LIBC_MUSL = 2; + } + + // The Linux kernel or distribution version, if obtainable. + string version = 1; + + // The architecture of the worker process. + Architecture architecture = 2; + + // The libc used by the worker process. + Libc libc = 3; + } + + message MacOSPlatform { + // The macOS version, if obtainable. + string version = 1; + + // The architecture of the worker process. + Architecture architecture = 2; + } + + message WindowsPlatform { + enum Crt { + CRT_UNSPECIFIED = 0; + + CRT_UCRT = 1; + + CRT_MSVCRT = 2; + + CRT_MINGW = 3; + + CRT_CYGWIN = 4; + } + + // The Windows version, if obtainable. + string version = 1; + + // The architecture of the worker process. + Architecture architecture = 2; + + // The C runtime used by the worker process, if obtainable. + Crt crt = 3; + } + + // The runtime(s) the SDK is operating in. + repeated Runtime runtimes = 1; + + // The hosting environment(s) the SDK is operating in. Repeated to allow for layering (ex: Docker inside k8s). + repeated HostingEnvironment hosting_environments = 2; + + // The platform the SDK is operating on. + Platform platform = 3; +} + +// A command sent from the server to a worker. +message WorkerCommand { + oneof type { + CancelActivityCommand cancel_activity = 1; + } +} + +// Cancel an activity if it is still running. Otherwise, do nothing. +message CancelActivityCommand { + bytes task_token = 1; +} + +// The result of executing a WorkerCommand. +message WorkerCommandResult { + oneof type { + CancelActivityResult cancel_activity = 1; + } +} + +// Result of a CancelActivityCommand. +// Treat both successful cancellation and no-op (activity is no longer running) as success. +message CancelActivityResult {} diff --git a/temporal/api/workflow/v1/message.proto b/temporal/api/workflow/v1/message.proto new file mode 100644 index 000000000..47aae63ef --- /dev/null +++ b/temporal/api/workflow/v1/message.proto @@ -0,0 +1,860 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.workflow.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/activity/v1/message.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/deployment/v1/message.proto"; +import "temporal/api/enums/v1/common.proto"; +import "temporal/api/enums/v1/event_type.proto"; +import "temporal/api/enums/v1/workflow.proto"; +import "temporal/api/failure/v1/message.proto"; +import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api/taskqueue/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.Workflow.V1"; +option go_package = "go.temporal.io/api/workflow/v1;workflow"; +option java_multiple_files = true; +option java_outer_classname = "MessageProto"; +option java_package = "io.temporal.api.workflow.v1"; +option ruby_package = "Temporalio::Api::Workflow::V1"; + +// Hold basic information about a workflow execution. +// This structure is a part of visibility, and thus contain a limited subset of information. +message WorkflowExecutionInfo { + temporal.api.common.v1.WorkflowExecution execution = 1; + + temporal.api.common.v1.WorkflowType type = 2; + + google.protobuf.Timestamp start_time = 3; + + google.protobuf.Timestamp close_time = 4; + + temporal.api.enums.v1.WorkflowExecutionStatus status = 5; + + int64 history_length = 6; + + string parent_namespace_id = 7; + + temporal.api.common.v1.WorkflowExecution parent_execution = 8; + + google.protobuf.Timestamp execution_time = 9; + + temporal.api.common.v1.Memo memo = 10; + + temporal.api.common.v1.SearchAttributes search_attributes = 11; + + ResetPoints auto_reset_points = 12; + + string task_queue = 13; + + int64 state_transition_count = 14; + + int64 history_size_bytes = 15; + + // If set, the most recent worker version stamp that appeared in a workflow task completion + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + temporal.api.common.v1.WorkerVersionStamp most_recent_worker_version_stamp = 16 [deprecated = true]; + + // Workflow execution duration is defined as difference between close time and execution time. + // This field is only populated if the workflow is closed. + google.protobuf.Duration execution_duration = 17; + + // Contains information about the root workflow execution. + // The root workflow execution is defined as follows: + // 1. A workflow without parent workflow is its own root workflow. + // 2. A workflow that has a parent workflow has the same root workflow as its parent workflow. + // Note: workflows continued as new or reseted may or may not have parents, check examples below. + // + // Examples: + // Scenario 1: Workflow W1 starts child workflow W2, and W2 starts child workflow W3. + // - The root workflow of all three workflows is W1. + // Scenario 2: Workflow W1 starts child workflow W2, and W2 continued as new W3. + // - The root workflow of all three workflows is W1. + // Scenario 3: Workflow W1 continued as new W2. + // - The root workflow of W1 is W1 and the root workflow of W2 is W2. + // Scenario 4: Workflow W1 starts child workflow W2, and W2 is reseted, creating W3 + // - The root workflow of all three workflows is W1. + // Scenario 5: Workflow W1 is reseted, creating W2. + // - The root workflow of W1 is W1 and the root workflow of W2 is W2. + temporal.api.common.v1.WorkflowExecution root_execution = 18; + + // The currently assigned build ID for this execution. Presence of this value means worker versioning is used + // for this execution. Assigned build ID is selected based on Worker Versioning Assignment Rules + // when the first workflow task of the execution is scheduled. If the first workflow task fails and is scheduled + // again, the assigned build ID may change according to the latest versioning rules. + // Assigned build ID can also change in the middle of a execution if Compatible Redirect Rules are applied to + // this execution. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + string assigned_build_id = 19 [deprecated = true]; + + // Build ID inherited from a previous/parent execution. If present, assigned_build_id will be set to this, instead + // of using the assignment rules. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + string inherited_build_id = 20 [deprecated = true]; + + // The first run ID in the execution chain. + // Executions created via the following operations are considered to be in the same chain + // - ContinueAsNew + // - Workflow Retry + // - Workflow Reset + // - Cron Schedule + string first_run_id = 21; + + // Absent value means the workflow execution is not versioned. When present, the execution might + // be versioned or unversioned, depending on `versioning_info.behavior` and `versioning_info.versioning_override`. + // Experimental. Versioning info is experimental and might change in the future. + WorkflowExecutionVersioningInfo versioning_info = 22; + + // The name of Worker Deployment that completed the most recent workflow task. + string worker_deployment_name = 23; + + // Priority metadata + temporal.api.common.v1.Priority priority = 24; + + // Total size in bytes of all external payloads referenced in workflow history. + int64 external_payload_size_bytes = 25; + + // Count of external payloads referenced in workflow history. + int64 external_payload_count = 26; +} + +// Holds all the extra information about workflow execution that is not part of Visibility. +message WorkflowExecutionExtendedInfo { + // Workflow execution expiration time is defined as workflow start time plus expiration timeout. + // Workflow start time may change after workflow reset. + google.protobuf.Timestamp execution_expiration_time = 1; + + // Workflow run expiration time is defined as current workflow run start time plus workflow run timeout. + google.protobuf.Timestamp run_expiration_time = 2; + + // indicates if the workflow received a cancel request + bool cancel_requested = 3; + + // Last workflow reset time. Nil if the workflow was never reset. + google.protobuf.Timestamp last_reset_time = 4; + + // Original workflow start time. + google.protobuf.Timestamp original_start_time = 5; + + // Reset Run ID points to the new run when this execution is reset. If the execution is reset multiple times, it points to the latest run. + string reset_run_id = 6; + + // Request ID information (eg: history event information associated with the request ID). + // Note: It only contains request IDs from StartWorkflowExecution requests, including indirect + // calls (eg: if SignalWithStartWorkflowExecution starts a new workflow, then the request ID is + // used in the StartWorkflowExecution request). + map request_id_infos = 7; + + // Information about the workflow execution pause operation. + WorkflowExecutionPauseInfo pause_info = 8; + + // Information about time skipping of the workflow execution. + // If the execution has never enabled time skipping, it will be nil. + temporal.api.common.v1.TimeSkippingInfo time_skipping_info = 9; +} + +// Holds all the information about worker versioning for a particular workflow execution. +// Experimental. Versioning info is experimental and might change in the future. +message WorkflowExecutionVersioningInfo { + // Versioning behavior determines how the server should treat this execution when workers are + // upgraded. When present it means this workflow execution is versioned; UNSPECIFIED means + // unversioned. See the comments in `VersioningBehavior` enum for more info about different + // behaviors. + // + // Child workflows or CaN executions **inherit** their parent/previous run's effective Versioning + // Behavior and Version (except when the new execution runs on a task queue not belonging to the + // same deployment version as the parent/previous run's task queue). The first workflow task will + // be dispatched according to the inherited behavior (or to the current version of the task-queue's + // deployment in the case of AutoUpgrade.) After completion of their first workflow task the + // Deployment Version and Behavior of the execution will update according to configuration on the worker. + // + // Note that `behavior` is overridden by `versioning_override` if the latter is present. + temporal.api.enums.v1.VersioningBehavior behavior = 1; + + // The worker deployment that completed the last workflow task of this workflow execution. Must + // be present if `behavior` is set. Absent value means no workflow task is completed, or the + // last workflow task was completed by an unversioned worker. Unversioned workers may still send + // a deployment value which will be stored here, so the right way to check if an execution is + // versioned if an execution is versioned or not is via the `behavior` field. + // Note that `deployment` is overridden by `versioning_override` if the latter is present. + // Deprecated. Use `deployment_version`. + temporal.api.deployment.v1.Deployment deployment = 2 [deprecated = true]; + + // Deprecated. Use `deployment_version`. + string version = 5 [deprecated = true]; + + // The Worker Deployment Version that completed the last workflow task of this workflow execution. + // An absent value means no workflow task is completed, or the workflow is unversioned. + // If present, and `behavior` is UNSPECIFIED, the last task of this workflow execution was completed + // by a worker that is not using versioning but _is_ passing Deployment Name and Build ID. + // + // Child workflows or CaN executions **inherit** their parent/previous run's effective Versioning + // Behavior and Version (except when the new execution runs on a task queue not belonging to the + // same deployment version as the parent/previous run's task queue). The first workflow task will + // be dispatched according to the inherited behavior (or to the current version of the task-queue's + // deployment in the case of AutoUpgrade.) After completion of their first workflow task the + // Deployment Version and Behavior of the execution will update according to configuration on the worker. + // + // Note that if `versioning_override.behavior` is PINNED then `versioning_override.pinned_version` + // will override this value. + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 7; + + // Present if user has set an execution-specific versioning override. This override takes + // precedence over SDK-sent `behavior` (and `version` when override is PINNED). An + // override can be set when starting a new execution, as well as afterwards by calling the + // `UpdateWorkflowExecutionOptions` API. + // Pinned overrides are automatically inherited by child workflows, continue-as-new workflows, + // workflow retries, and cron workflows. + VersioningOverride versioning_override = 3; + + // When present, indicates the workflow is transitioning to a different deployment. Can + // indicate one of the following transitions: unversioned -> versioned, versioned -> versioned + // on a different deployment, or versioned -> unversioned. + // Not applicable to workflows with PINNED behavior. + // When a workflow with AUTO_UPGRADE behavior creates a new workflow task, it will automatically + // start a transition to the task queue's current deployment if the task queue's current + // deployment is different from the workflow's deployment. + // If the AUTO_UPGRADE workflow is stuck due to backlogged activity or workflow tasks, those + // tasks will be redirected to the task queue's current deployment. As soon as a poller from + // that deployment is available to receive the task, the workflow will automatically start a + // transition to that deployment and continue execution there. + // A deployment transition can only exist while there is a pending or started workflow task. + // Once the pending workflow task completes on the transition's target deployment, the + // transition completes and the workflow's `deployment` and `behavior` fields are updated per + // the worker's task completion response. + // Pending activities will not start new attempts during a transition. Once the transition is + // completed, pending activities will start their next attempt on the new deployment. + // Deprecated. Use version_transition. + DeploymentTransition deployment_transition = 4 [deprecated = true]; + + // When present, indicates the workflow is transitioning to a different deployment version + // (which may belong to the same deployment name or another). Can indicate one of the following + // transitions: unversioned -> versioned, versioned -> versioned + // on a different deployment version, or versioned -> unversioned. + // Not applicable to workflows with PINNED behavior. + // When a workflow with AUTO_UPGRADE behavior creates a new workflow task, it will automatically + // start a transition to the task queue's current version if the task queue's current version is + // different from the workflow's current deployment version. + // If the AUTO_UPGRADE workflow is stuck due to backlogged activity or workflow tasks, those + // tasks will be redirected to the task queue's current version. As soon as a poller from + // that deployment version is available to receive the task, the workflow will automatically + // start a transition to that version and continue execution there. + // A version transition can only exist while there is a pending or started workflow task. + // Once the pending workflow task completes on the transition's target version, the + // transition completes and the workflow's `behavior`, and `deployment_version` fields are updated per the + // worker's task completion response. + // Pending activities will not start new attempts during a transition. Once the transition is + // completed, pending activities will start their next attempt on the new version. + DeploymentVersionTransition version_transition = 6; + + // Monotonic counter reflecting the latest routing decision for this workflow execution. + // Used for staleness detection between history and matching when dispatching tasks to workers. + // Incremented when a workflow execution routes to a new deployment version, which happens + // when a worker of the new deployment version completes a workflow task. + // Note: Pinned tasks and sticky tasks send a value of 0 for this field since these tasks do not + // face the problem of inconsistent dispatching that arises from eventual consistency between + // task queues and their partitions. + int64 revision_number = 8; + + // Experimental. + // If this workflow is the result of a continue-as-new, this field is set to the initial_versioning_behavior + // specified in that command. + // Only used for the initial task of this run and the initial task of any retries of this run. + // Not passed to children or to future continue-as-new. + // + // Note: In the first release of Upgrade-on-CaN, when the only ContinueAsNewVersioningBehavior was AutoUpgrade, + // a non-empty InheritedAutoUpgradeInfo meant that the workflow should start as AutoUpgrade. So for compatibility + // with ContinueAsNew history commands generated during that time, know that an UNSPECIFIED value here is equivalent + // to ContinueAsNewVersioningBehaviorAutoUpgrade if the behavior of the workflow is AutoUpgrade. + temporal.api.enums.v1.ContinueAsNewVersioningBehavior continue_as_new_initial_versioning_behavior = 9; +} + +// Holds information about ongoing transition of a workflow execution from one deployment to another. +// Deprecated. Use DeploymentVersionTransition. +message DeploymentTransition { + // The target deployment of the transition. Null means a so-far-versioned workflow is + // transitioning to unversioned workers. + temporal.api.deployment.v1.Deployment deployment = 1; +} + +// Holds information about ongoing transition of a workflow execution from one worker +// deployment version to another. +// Experimental. Might change in the future. +message DeploymentVersionTransition { + // Deprecated. Use `deployment_version`. + string version = 1 [deprecated = true]; + + // The target Version of the transition. + // If nil, a so-far-versioned workflow is transitioning to unversioned workers. + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 2; +} + +message WorkflowExecutionConfig { + temporal.api.taskqueue.v1.TaskQueue task_queue = 1; + + google.protobuf.Duration workflow_execution_timeout = 2; + + google.protobuf.Duration workflow_run_timeout = 3; + + google.protobuf.Duration default_workflow_task_timeout = 4; + + // User metadata provided on start workflow. + temporal.api.sdk.v1.UserMetadata user_metadata = 5; +} + +message PendingActivityInfo { + string activity_id = 1; + + temporal.api.common.v1.ActivityType activity_type = 2; + + temporal.api.enums.v1.PendingActivityState state = 3; + + temporal.api.common.v1.Payloads heartbeat_details = 4; + + google.protobuf.Timestamp last_heartbeat_time = 5; + + google.protobuf.Timestamp last_started_time = 6; + + int32 attempt = 7; + + int32 maximum_attempts = 8; + + google.protobuf.Timestamp scheduled_time = 9; + + google.protobuf.Timestamp expiration_time = 10; + + temporal.api.failure.v1.Failure last_failure = 11; + + string last_worker_identity = 12; + + // Absence of `assigned_build_id` generally means this task is on an "unversioned" task queue. + // In rare cases, it can also mean that the task queue is versioned but we failed to write activity's + // independently-assigned build ID to the database. This case heals automatically once the task is dispatched. + // Deprecated. This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + oneof assigned_build_id { + // Deprecated. When present, it means this activity is assigned to the build ID of its workflow. + google.protobuf.Empty use_workflow_build_id = 13 [deprecated = true]; + + // Deprecated. This means the activity is independently versioned and not bound to the build ID of its workflow. + // The activity will use the build id in this field instead. + // If the task fails and is scheduled again, the assigned build ID may change according to the latest versioning + // rules. + string last_independently_assigned_build_id = 14 [deprecated = true]; + } + + // Deprecated. The version stamp of the worker to whom this activity was most recently dispatched + // This field should be cleaned up when versioning-2 API is removed. [cleanup-experimental-wv] + temporal.api.common.v1.WorkerVersionStamp last_worker_version_stamp = 15 [deprecated = true]; + + // The time activity will wait until the next retry. + // If activity is currently running it will be next retry interval if activity failed. + // If activity is currently waiting it will be current retry interval. + // If there will be no retry it will be null. + google.protobuf.Duration current_retry_interval = 16; + + // The time when the last activity attempt was completed. If activity has not been completed yet then it will be null. + google.protobuf.Timestamp last_attempt_complete_time = 17; + + // Next time when activity will be scheduled. + // If activity is currently scheduled or started it will be null. + google.protobuf.Timestamp next_attempt_schedule_time = 18; + + // Indicates if activity is paused. + bool paused = 19; + + // The deployment this activity was dispatched to most recently. Present only if the activity + // was dispatched to a versioned worker. + // Deprecated. Use `last_deployment_version`. + temporal.api.deployment.v1.Deployment last_deployment = 20 [deprecated = true]; + + // The Worker Deployment Version this activity was dispatched to most recently. + // Deprecated. Use `last_deployment_version`. + string last_worker_deployment_version = 21 [deprecated = true]; + + // The Worker Deployment Version this activity was dispatched to most recently. + // If nil, the activity has not yet been dispatched or was last dispatched to an unversioned worker. + temporal.api.deployment.v1.WorkerDeploymentVersion last_deployment_version = 25; + + // Priority metadata. If this message is not present, or any fields are not + // present, they inherit the values from the workflow. + temporal.api.common.v1.Priority priority = 22; + + message PauseInfo { + // The time when the activity was paused. + google.protobuf.Timestamp pause_time = 1; + + message Manual { + // The identity of the actor that paused the activity. + string identity = 1; + + // Reason for pausing the activity. + string reason = 2; + } + + message Rule { + // The rule that paused the activity. + string rule_id = 1; + + // The identity of the actor that created the rule. + string identity = 2; + + // Reason why rule was created. Populated from rule description. + string reason = 3; + } + + oneof paused_by { + // activity was paused by the manual intervention + Manual manual = 2; + + // activity was paused by the rule + Rule rule = 4; + } + } + + PauseInfo pause_info = 23; + + // Current activity options. May be different from the one used to start the activity. + temporal.api.activity.v1.ActivityOptions activity_options = 24; +} + +message PendingChildExecutionInfo { + string workflow_id = 1; + + string run_id = 2; + + string workflow_type_name = 3; + + int64 initiated_id = 4; + + // Default: PARENT_CLOSE_POLICY_TERMINATE. + temporal.api.enums.v1.ParentClosePolicy parent_close_policy = 5; +} + +message PendingWorkflowTaskInfo { + temporal.api.enums.v1.PendingWorkflowTaskState state = 1; + + google.protobuf.Timestamp scheduled_time = 2; + + // original_scheduled_time is the scheduled time of the first workflow task during workflow task heartbeat. + // Heartbeat workflow task is done by RespondWorkflowTaskComplete with ForceCreateNewWorkflowTask == true and no command + // In this case, OriginalScheduledTime won't change. Then when current time - original_scheduled_time exceeds + // some threshold, the workflow task will be forced timeout. + google.protobuf.Timestamp original_scheduled_time = 3; + + google.protobuf.Timestamp started_time = 4; + + int32 attempt = 5; +} + +message ResetPoints { + repeated ResetPointInfo points = 1; +} + +// ResetPointInfo records the workflow event id that is the first one processed by a given +// build id or binary checksum. A new reset point will be created if either build id or binary +// checksum changes (although in general only one or the other will be used at a time). +message ResetPointInfo { + // Worker build id. + string build_id = 7; + + // Deprecated. A worker binary version identifier. + string binary_checksum = 1 [deprecated = true]; + + // The first run ID in the execution chain that was touched by this worker build. + string run_id = 2; + + // Event ID of the first WorkflowTaskCompleted event processed by this worker build. + int64 first_workflow_task_completed_id = 3; + + google.protobuf.Timestamp create_time = 4; + + // (-- api-linter: core::0214::resource-expiry=disabled + // aip.dev/not-precedent: TTL is not defined for ResetPointInfo. --) + // The time that the run is deleted due to retention. + google.protobuf.Timestamp expire_time = 5; + + // false if the reset point has pending childWFs/reqCancels/signalExternals. + bool resettable = 6; +} + +// NewWorkflowExecutionInfo is a shared message that encapsulates all the +// required arguments to starting a workflow in different contexts. +message NewWorkflowExecutionInfo { + string workflow_id = 1; + + temporal.api.common.v1.WorkflowType workflow_type = 2; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 3; + + // Serialized arguments to the workflow. + temporal.api.common.v1.Payloads input = 4; + + // Total workflow execution timeout including retries and continue as new. + google.protobuf.Duration workflow_execution_timeout = 5; + + // Timeout of a single workflow run. + google.protobuf.Duration workflow_run_timeout = 6; + + // Timeout of a single workflow task. + google.protobuf.Duration workflow_task_timeout = 7; + + // Default: WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE. + temporal.api.enums.v1.WorkflowIdReusePolicy workflow_id_reuse_policy = 8; + + // The retry policy for the workflow. Will never exceed `workflow_execution_timeout`. + temporal.api.common.v1.RetryPolicy retry_policy = 9; + + // See https://docs.temporal.io/docs/content/what-is-a-temporal-cron-job/ + string cron_schedule = 10; + + temporal.api.common.v1.Memo memo = 11; + + temporal.api.common.v1.SearchAttributes search_attributes = 12; + + temporal.api.common.v1.Header header = 13; + + // Metadata on the workflow if it is started. This is carried over to the WorkflowExecutionConfig + // for use by user interfaces to display the fixed as-of-start summary and details of the + // workflow. + temporal.api.sdk.v1.UserMetadata user_metadata = 14; + + // If set, takes precedence over the Versioning Behavior sent by the SDK on Workflow Task completion. + // To unset the override after the workflow is running, use UpdateWorkflowExecutionOptions. + VersioningOverride versioning_override = 15; + + // Priority metadata + temporal.api.common.v1.Priority priority = 16; +} + +// CallbackInfo contains the state of an attached workflow callback. +message CallbackInfo { + // Trigger for when the workflow is closed. + message WorkflowClosed {} + + // Trigger for when a workflow update is completed. + message UpdateWorkflowExecutionCompleted { + string update_id = 1; + } + + message Trigger { + oneof variant { + WorkflowClosed workflow_closed = 1; + + UpdateWorkflowExecutionCompleted update_workflow_execution_completed = 2; + } + } + + // Information on how this callback should be invoked (e.g. its URL and type). + temporal.api.common.v1.Callback callback = 1; + + // Trigger for this callback. + Trigger trigger = 2; + + // The time when the callback was registered. + google.protobuf.Timestamp registration_time = 3; + + temporal.api.enums.v1.CallbackState state = 4; + + // The number of attempts made to deliver the callback. + // This number represents a minimum bound since the attempt is incremented after the callback request completes. + int32 attempt = 5; + + // The time when the last attempt completed. + google.protobuf.Timestamp last_attempt_complete_time = 6; + + // The last attempt's failure, if any. + temporal.api.failure.v1.Failure last_attempt_failure = 7; + + // The time when the next attempt is scheduled. + google.protobuf.Timestamp next_attempt_schedule_time = 8; + + // If the state is BLOCKED, blocked reason provides additional information. + string blocked_reason = 9; +} + +// PendingNexusOperationInfo contains the state of a pending Nexus operation. +message PendingNexusOperationInfo { + // Endpoint name. + // Resolved to a URL via the cluster's endpoint registry. + string endpoint = 1; + + // Service name. + string service = 2; + + // Operation name. + string operation = 3; + + // Operation ID. Only set for asynchronous operations after a successful StartOperation call. + // + // Deprecated. Renamed to operation_token. + string operation_id = 4 [deprecated = true]; + + // Schedule-to-close timeout for this operation. + // This is the only timeout settable by a workflow. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 5; + + // The time when the operation was scheduled. + google.protobuf.Timestamp scheduled_time = 6; + + temporal.api.enums.v1.PendingNexusOperationState state = 7; + + // The number of attempts made to deliver the start operation request. + // This number is approximate, it is incremented when a task is added to the history queue. + // In practice, there could be more attempts if a task is executed but fails to commit, or less attempts if a task + // was never executed. + int32 attempt = 8; + + // The time when the last attempt completed. + google.protobuf.Timestamp last_attempt_complete_time = 9; + + // The last attempt's failure, if any. + temporal.api.failure.v1.Failure last_attempt_failure = 10; + + // The time when the next attempt is scheduled. + google.protobuf.Timestamp next_attempt_schedule_time = 11; + + NexusOperationCancellationInfo cancellation_info = 12; + + // The event ID of the NexusOperationScheduled event. Can be used to correlate an operation in the + // DescribeWorkflowExecution response with workflow history. + int64 scheduled_event_id = 13; + + // If the state is BLOCKED, blocked reason provides additional information. + string blocked_reason = 14; + + // Operation token. Only set for asynchronous operations after a successful StartOperation call. + string operation_token = 15; + + // Schedule-to-start timeout for this operation. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 16; + + // Start-to-close timeout for this operation. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 17; +} + +// NexusOperationCancellationInfo contains the state of a nexus operation cancellation. +message NexusOperationCancellationInfo { + // The time when cancellation was requested. + google.protobuf.Timestamp requested_time = 1; + + temporal.api.enums.v1.NexusOperationCancellationState state = 2; + + // The number of attempts made to deliver the cancel operation request. + // This number represents a minimum bound since the attempt is incremented after the request completes. + int32 attempt = 3; + + // The time when the last attempt completed. + google.protobuf.Timestamp last_attempt_complete_time = 4; + + // The last attempt's failure, if any. + temporal.api.failure.v1.Failure last_attempt_failure = 5; + + // The time when the next attempt is scheduled. + google.protobuf.Timestamp next_attempt_schedule_time = 6; + + // If the state is BLOCKED, blocked reason provides additional information. + string blocked_reason = 7; +} + +message WorkflowExecutionOptions { + // If set, takes precedence over the Versioning Behavior sent by the SDK on Workflow Task completion. + VersioningOverride versioning_override = 1; + + // If set, overrides the workflow's priority sent by the SDK. + temporal.api.common.v1.Priority priority = 2; + + // The time-skipping configuration for this workflow execution. + // When `fast_forward` is set, time will be fast-forwarded to a future point relative + // to the current workflow timestamp. Each call takes effect, even if + // `fast_forward` is set to the same duration, since the target time is recalculated + // from the current timestamp on every call. + // + // This field must be updated as a whole; updating individual sub-fields is not supported. + // When setting the update mask in `UpdateWorkflowExecutionOptionsRequest`, + // `BatchOperationUpdateWorkflowExecutionOptions`, etc., use a mask that covers the entire field. + temporal.api.common.v1.TimeSkippingConfig time_skipping_config = 3; +} + +// Used to override the versioning behavior (and pinned deployment version, if applicable) of a +// specific workflow execution. If set, this override takes precedence over worker-sent values. +// See `WorkflowExecutionInfo.VersioningInfo` for more information. +// +// To remove the override, call `UpdateWorkflowExecutionOptions` with a null +// `VersioningOverride`, and use the `update_mask` to indicate that it should be mutated. +// +// Pinned behavior overrides are automatically inherited by child workflows, workflow retries, continue-as-new +// workflows, and cron workflows. +message VersioningOverride { + // Indicates whether to override the workflow to be AutoUpgrade or Pinned. + oneof override { + // Override the workflow to have Pinned behavior. This is a sticky override: + // Workflow Tasks continue to route according to this override until it is + // explicitly removed. + PinnedOverride pinned = 3; + + // Override the workflow to have AutoUpgrade behavior. + bool auto_upgrade = 4; + + // Override Workflow Task routing to a specific Worker Deployment Version until + // one Workflow Task completes there. After completion, the workflow execution's + // Versioning Behavior and Deployment Version come from the worker's completion + // response. + // (-- api-linter: core::0142::time-field-type=disabled + // aip.dev/not-precedent: one_time describes one-time routing semantics, not a timestamp or duration. --) + OneTimeOverride one_time = 5; + } + + // Required. + // Deprecated. Use `override`. + temporal.api.enums.v1.VersioningBehavior behavior = 1 [deprecated = true]; + + // Required if behavior is `PINNED`. Must be null if behavior is `AUTO_UPGRADE`. + // Identifies the worker deployment to pin the workflow to. + // Deprecated. Use `override.pinned.version`. + temporal.api.deployment.v1.Deployment deployment = 2 [deprecated = true]; + + // Required if behavior is `PINNED`. Must be absent if behavior is not `PINNED`. + // Identifies the worker deployment version to pin the workflow to, in the format + // ".". + // Deprecated. Use `override.pinned.version`. + string pinned_version = 9 [deprecated = true]; + + message PinnedOverride { + // Defaults to PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED. + // See `PinnedOverrideBehavior` for details. + PinnedOverrideBehavior behavior = 1; + + // Specifies the Worker Deployment Version to pin this workflow to. + // Required if the target workflow is not already pinned to a version. + // + // If omitted and the target workflow is already pinned, the effective + // pinned version will be the existing pinned version. + // + // If omitted and the target workflow is not pinned, the override request + // will be rejected with a PreconditionFailed error. + temporal.api.deployment.v1.WorkerDeploymentVersion version = 2; + } + + // Routes Workflow Tasks for this execution to `target_deployment_version` + // until a Workflow Task completes on that version, then clears the override. + // + // This does not force the workflow's normal Versioning Behavior to become + // Pinned. After the Workflow Task completes on `target_deployment_version`, + // the workflow execution's normal Versioning Behavior and Deployment Version + // are taken from the worker's completion response. + // + // Example: if an execution is one-time moved from version X to version Y, and + // version Z later becomes current: + // - if worker Y reports Pinned, the execution stays on Y; + // - if worker Y reports AutoUpgrade, the execution routes to Z on a future + // Workflow Task; + // - if worker Y reports Pinned and the workflow uses upgrade-on-continue-as-new, + // the current run stays on Y and the execution can route to Z after + // continue-as-new. + // + // If no Workflow Task completes on `target_deployment_version`, this override + // remains pending. + message OneTimeOverride { + // Required. Worker Deployment Version to receive the one-time Workflow Task. + temporal.api.deployment.v1.WorkerDeploymentVersion target_deployment_version = 1; + } + + enum PinnedOverrideBehavior { + // Unspecified. + PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED = 0; + + // Override workflow behavior to be Pinned. + PINNED_OVERRIDE_BEHAVIOR_PINNED = 1; + } +} + +// When StartWorkflowExecution uses the conflict policy WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING and +// there is already an existing running workflow, OnConflictOptions defines actions to be taken on +// the existing running workflow. In this case, it will create a WorkflowExecutionOptionsUpdatedEvent +// history event in the running workflow with the changes requested in this object. +message OnConflictOptions { + // Attaches the request ID to the running workflow. + bool attach_request_id = 1; + + // Attaches the completion callbacks to the running workflow. + bool attach_completion_callbacks = 2; + + // Attaches the links to the WorkflowExecutionOptionsUpdatedEvent history event. + bool attach_links = 3; +} + +// RequestIdInfo contains details of a request ID. +message RequestIdInfo { + // The event type of the history event generated by the request. + temporal.api.enums.v1.EventType event_type = 1; + + // The event id of the history event generated by the request. It's possible the event ID is not + // known (unflushed buffered event). In this case, the value will be zero or a negative value, + // representing an invalid ID. + int64 event_id = 2; + + // Indicate if the request is still buffered. If so, the event ID is not known and its value + // will be an invalid event ID. + bool buffered = 3; +} + +// PostResetOperation represents an operation to be performed on the new workflow execution after a workflow reset. +message PostResetOperation { + // SignalWorkflow represents sending a signal after a workflow reset. + // Keep the parameter in sync with temporal.api.workflowservice.v1.SignalWorkflowExecutionRequest. + message SignalWorkflow { + // The workflow author-defined name of the signal to send to the workflow. + string signal_name = 1; + + // Serialized value(s) to provide with the signal. + temporal.api.common.v1.Payloads input = 2; + + // Headers that are passed with the signal to the processing workflow. + temporal.api.common.v1.Header header = 3; + + // Links to be associated with the WorkflowExecutionSignaled event. + repeated temporal.api.common.v1.Link links = 4; + } + + // UpdateWorkflowOptions represents updating workflow execution options after a workflow reset. + // Keep the parameters in sync with temporal.api.workflowservice.v1.UpdateWorkflowExecutionOptionsRequest. + message UpdateWorkflowOptions { + // Update Workflow options that were originally specified via StartWorkflowExecution. Partial updates are accepted and controlled by update_mask. + WorkflowExecutionOptions workflow_execution_options = 1; + + // Controls which fields from `workflow_execution_options` will be applied. + // To unset a field, set it to null and use the update mask to indicate that it should be mutated. + google.protobuf.FieldMask update_mask = 2; + } + + oneof variant { + SignalWorkflow signal_workflow = 1; + + UpdateWorkflowOptions update_workflow_options = 2; + } +} + +// WorkflowExecutionPauseInfo contains the information about a workflow execution pause. +message WorkflowExecutionPauseInfo { + // The identity of the client who paused the workflow execution. + string identity = 1; + + // The time when the workflow execution was paused. + google.protobuf.Timestamp paused_time = 2; + + // The reason for pausing the workflow execution. + string reason = 3; +} diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto new file mode 100644 index 000000000..c6bac03b9 --- /dev/null +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -0,0 +1,4285 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.workflowservice.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/activity/v1/message.proto"; +import "temporal/api/batch/v1/message.proto"; +import "temporal/api/command/v1/message.proto"; +import "temporal/api/common/v1/message.proto"; +import "temporal/api/compute/v1/config.proto"; +import "temporal/api/deployment/v1/message.proto"; +import "temporal/api/enums/v1/activity.proto"; +import "temporal/api/enums/v1/batch_operation.proto"; +import "temporal/api/enums/v1/common.proto"; +import "temporal/api/enums/v1/deployment.proto"; +import "temporal/api/enums/v1/failed_cause.proto"; +import "temporal/api/enums/v1/namespace.proto"; +import "temporal/api/enums/v1/nexus.proto"; +import "temporal/api/enums/v1/query.proto"; +import "temporal/api/enums/v1/reset.proto"; +import "temporal/api/enums/v1/task_queue.proto"; +import "temporal/api/enums/v1/time_skipping.proto"; +import "temporal/api/enums/v1/update.proto"; +import "temporal/api/enums/v1/workflow.proto"; +import "temporal/api/failure/v1/message.proto"; +import "temporal/api/filter/v1/message.proto"; +import "temporal/api/history/v1/message.proto"; +import "temporal/api/namespace/v1/message.proto"; +import "temporal/api/nexus/v1/message.proto"; +import "temporal/api/protocol/v1/message.proto"; +import "temporal/api/query/v1/message.proto"; +import "temporal/api/replication/v1/message.proto"; +import "temporal/api/rules/v1/message.proto"; +import "temporal/api/schedule/v1/message.proto"; +import "temporal/api/sdk/v1/task_complete_metadata.proto"; +import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api/sdk/v1/worker_config.proto"; +import "temporal/api/taskqueue/v1/message.proto"; +import "temporal/api/update/v1/message.proto"; +import "temporal/api/version/v1/message.proto"; +import "temporal/api/worker/v1/message.proto"; +import "temporal/api/workflow/v1/message.proto"; + +option csharp_namespace = "Temporalio.Api.WorkflowService.V1"; +option go_package = "go.temporal.io/api/workflowservice/v1;workflowservice"; +option java_multiple_files = true; +option java_outer_classname = "RequestResponseProto"; +option java_package = "io.temporal.api.workflowservice.v1"; +option ruby_package = "Temporalio::Api::WorkflowService::V1"; + +message RegisterNamespaceRequest { + string namespace = 1; + + string description = 2; + + string owner_email = 3; + + google.protobuf.Duration workflow_execution_retention_period = 4; + + repeated temporal.api.replication.v1.ClusterReplicationConfig clusters = 5; + + string active_cluster_name = 6; + + // A key-value map for any customized purpose. + map data = 7; + + string security_token = 8; + + bool is_global_namespace = 9; + + // If unspecified (ARCHIVAL_STATE_UNSPECIFIED) then default server configuration is used. + temporal.api.enums.v1.ArchivalState history_archival_state = 10; + + string history_archival_uri = 11; + + // If unspecified (ARCHIVAL_STATE_UNSPECIFIED) then default server configuration is used. + temporal.api.enums.v1.ArchivalState visibility_archival_state = 12; + + string visibility_archival_uri = 13; +} + +message RegisterNamespaceResponse {} + +message ListNamespacesRequest { + int32 page_size = 1; + + bytes next_page_token = 2; + + temporal.api.namespace.v1.NamespaceFilter namespace_filter = 3; +} + +message ListNamespacesResponse { + repeated DescribeNamespaceResponse namespaces = 1; + + bytes next_page_token = 2; +} + +message DescribeNamespaceRequest { + string namespace = 1; + + string id = 2; + + // If true, the server may serve the response from an eventually-consistent + // source instead of reading through to persistence. Defaults to false, + // which preserves read-after-write consistency. SDKs should set this when + // fetching namespace capabilities on worker/client startup. + bool weak_consistency = 3; +} + +message DescribeNamespaceResponse { + temporal.api.namespace.v1.NamespaceInfo namespace_info = 1; + + temporal.api.namespace.v1.NamespaceConfig config = 2; + + temporal.api.replication.v1.NamespaceReplicationConfig replication_config = 3; + + int64 failover_version = 4; + + bool is_global_namespace = 5; + + // Contains the historical state of failover_versions for the cluster, truncated to contain only the last N + // states to ensure that the list does not grow unbounded. + repeated temporal.api.replication.v1.FailoverStatus failover_history = 6; + + // Deprecated. Use `poller_groups_info` instead, which carries a version so the client can + // ignore stale updates. + // The initial info that client should use for poller group assignment. This information is + // updated through poll response. Client is supposed to use the info received in the latest + // poll response. + repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 7 [deprecated = true]; + + // The initial, versioned info that client should use for poller group assignment. This + // information is updated through poll responses. Client is supposed to use the info with the + // highest version it has received. + temporal.api.taskqueue.v1.PollerGroupsInfo poller_groups_info = 8; +} + +message UpdateNamespaceRequest { + string namespace = 1; + + temporal.api.namespace.v1.UpdateNamespaceInfo update_info = 2; + + temporal.api.namespace.v1.NamespaceConfig config = 3; + + temporal.api.replication.v1.NamespaceReplicationConfig replication_config = 4; + + string security_token = 5; + + string delete_bad_binary = 6; + + // promote local namespace to global namespace. Ignored if namespace is already global namespace. + bool promote_namespace = 7; +} + +message UpdateNamespaceResponse { + temporal.api.namespace.v1.NamespaceInfo namespace_info = 1; + + temporal.api.namespace.v1.NamespaceConfig config = 2; + + temporal.api.replication.v1.NamespaceReplicationConfig replication_config = 3; + + int64 failover_version = 4; + + bool is_global_namespace = 5; +} + +// Deprecated. +message DeprecateNamespaceRequest { + string namespace = 1; + + string security_token = 2; +} + +// Deprecated. +message DeprecateNamespaceResponse {} + +message StartWorkflowExecutionRequest { + string namespace = 1; + + string workflow_id = 2; + + temporal.api.common.v1.WorkflowType workflow_type = 3; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 4; + + // Serialized arguments to the workflow. These are passed as arguments to the workflow function. + temporal.api.common.v1.Payloads input = 5; + + // Total workflow execution timeout including retries and continue as new. + google.protobuf.Duration workflow_execution_timeout = 6; + + // Timeout of a single workflow run. + google.protobuf.Duration workflow_run_timeout = 7; + + // Timeout of a single workflow task. + google.protobuf.Duration workflow_task_timeout = 8; + + // The identity of the client who initiated this request + string identity = 9; + + // A unique identifier for this start request. Typically UUIDv4. + string request_id = 10; + + // Defines whether to allow re-using the workflow id from a previously *closed* workflow. + // The default policy is WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE. + // + // See `workflow_id_conflict_policy` for handling a workflow id duplication with a *running* workflow. + temporal.api.enums.v1.WorkflowIdReusePolicy workflow_id_reuse_policy = 11; + + // Defines how to resolve a workflow id conflict with a *running* workflow. + // The default policy is WORKFLOW_ID_CONFLICT_POLICY_FAIL. + // + // See `workflow_id_reuse_policy` for handling a workflow id duplication with a *closed* workflow. + temporal.api.enums.v1.WorkflowIdConflictPolicy workflow_id_conflict_policy = 22; + + // The retry policy for the workflow. Will never exceed `workflow_execution_timeout`. + temporal.api.common.v1.RetryPolicy retry_policy = 12; + + // See https://docs.temporal.io/docs/content/what-is-a-temporal-cron-job/ + string cron_schedule = 13; + + temporal.api.common.v1.Memo memo = 14; + + temporal.api.common.v1.SearchAttributes search_attributes = 15; + + temporal.api.common.v1.Header header = 16; + + // Request to get the first workflow task inline in the response bypassing matching service and worker polling. + // If set to `true` the caller is expected to have a worker available and capable of processing the task. + // The returned task will be marked as started and is expected to be completed by the specified + // `workflow_task_timeout`. + bool request_eager_execution = 17; + + // These values will be available as ContinuedFailure and LastCompletionResult in the + // WorkflowExecutionStarted event and through SDKs. The are currently only used by the + // server itself (for the schedules feature) and are not intended to be exposed in + // StartWorkflowExecution. + temporal.api.failure.v1.Failure continued_failure = 18; + + temporal.api.common.v1.Payloads last_completion_result = 19; + + // Time to wait before making the first workflow task available for dispatch. Cannot be used with `cron_schedule`. + // If the workflow gets a signal before the delay, a workflow task will be made available for dispatch and the rest + // of the delay will be ignored. + google.protobuf.Duration workflow_start_delay = 20; + + // Callbacks to be called by the server when this workflow reaches a terminal state. + // If the workflow continues-as-new, these callbacks will be carried over to the new execution. + // Callback addresses must be whitelisted in the server's dynamic configuration. + repeated temporal.api.common.v1.Callback completion_callbacks = 21; + + // Metadata on the workflow if it is started. This is carried over to the WorkflowExecutionInfo + // for use by user interfaces to display the fixed as-of-start summary and details of the + // workflow. + temporal.api.sdk.v1.UserMetadata user_metadata = 23; + + // Links to be associated with the workflow. + repeated temporal.api.common.v1.Link links = 24; + + // If set, takes precedence over the Versioning Behavior sent by the SDK on Workflow Task completion. + // To unset the override after the workflow is running, use UpdateWorkflowExecutionOptions. + temporal.api.workflow.v1.VersioningOverride versioning_override = 25; + + // Defines actions to be done to the existing running workflow when the conflict policy + // WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING is used. If not set (ie., nil value) or set to a + // empty object (ie., all options with default value), it won't do anything to the existing + // running workflow. If set, it will add a history event to the running workflow. + temporal.api.workflow.v1.OnConflictOptions on_conflict_options = 26; + + // Priority metadata + temporal.api.common.v1.Priority priority = 27; + + // Deployment Options of the worker who will process the eager task. Passed when `request_eager_execution=true`. + temporal.api.deployment.v1.WorkerDeploymentOptions eager_worker_deployment_options = 28; + + // Time-skipping configuration. If not set, time skipping is disabled. + temporal.api.common.v1.TimeSkippingConfig time_skipping_config = 29; +} + +message StartWorkflowExecutionResponse { + // The run id of the workflow that was started - or used (via WorkflowIdConflictPolicy USE_EXISTING). + string run_id = 1; + + // If the workflow was started as a result of a de-dupe, this field will contain the run id of the first execution in the chain. + string first_execution_run_id = 6; + + // If true, a new workflow was started. + bool started = 3; + + // Current execution status of the workflow. Typically remains WORKFLOW_EXECUTION_STATUS_RUNNING + // unless a de-dupe occurs or in specific scenarios handled within the ExecuteMultiOperation (refer to its docs). + temporal.api.enums.v1.WorkflowExecutionStatus status = 5; + + // When `request_eager_execution` is set on the `StartWorkflowExecutionRequest`, the server - if supported - will + // return the first workflow task to be eagerly executed. + // The caller is expected to have a worker available to process the task. + PollWorkflowTaskQueueResponse eager_workflow_task = 2; + + // Link to the workflow event. + temporal.api.common.v1.Link link = 4; +} + +message GetWorkflowExecutionHistoryRequest { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution execution = 2; + + int32 maximum_page_size = 3; + + // If a `GetWorkflowExecutionHistoryResponse` or a `PollWorkflowTaskQueueResponse` had one of + // these, it should be passed here to fetch the next page. + bytes next_page_token = 4; + + // If set to true, the RPC call will not resolve until there is a new event which matches + // the `history_event_filter_type`, or a timeout is hit. + bool wait_new_event = 5; + + // Filter returned events such that they match the specified filter type. + // Default: HISTORY_EVENT_FILTER_TYPE_ALL_EVENT. + temporal.api.enums.v1.HistoryEventFilterType history_event_filter_type = 6; + + bool skip_archival = 7; +} + +message GetWorkflowExecutionHistoryResponse { + temporal.api.history.v1.History history = 1; + + // Raw history is an alternate representation of history that may be returned if configured on + // the frontend. This is not supported by all SDKs. Either this or `history` will be set. + repeated temporal.api.common.v1.DataBlob raw_history = 2; + + // Will be set if there are more history events than were included in this response + bytes next_page_token = 3; + + bool archived = 4; +} + +message GetWorkflowExecutionHistoryReverseRequest { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution execution = 2; + + int32 maximum_page_size = 3; + + bytes next_page_token = 4; +} + +message GetWorkflowExecutionHistoryReverseResponse { + temporal.api.history.v1.History history = 1; + + // Will be set if there are more history events than were included in this response + bytes next_page_token = 3; +} + +message PollWorkflowTaskQueueRequest { + string namespace = 1; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 2; + + // Unless this is the first poll, the client must pass one of the poller group IDs received in + // `poller_group_infos` of the last the PollWorkflowTaskQueueResponse according to the + // instructions. If not set, the poll is routed randomly which can cause it to be blocked + // without receiving a task while the queue actually has tasks in another server location. + string poller_group_id = 10; + + // The identity of the worker/client who is polling this task queue + string identity = 3; + + // A unique key for this worker instance, used for tracking worker lifecycle. + // This is guaranteed to be unique, whereas identity is not guaranteed to be unique. + string worker_instance_key = 8; + + // A dedicated per-worker Nexus task queue on which the server sends control + // tasks (e.g. activity cancellation) to this specific worker instance. + string worker_control_task_queue = 9; + + // Deprecated. Use deployment_options instead. + // Each worker process should provide an ID unique to the specific set of code it is running + // "checksum" in this field name isn't very accurate, it should be though of as an id. + string binary_checksum = 4 [deprecated = true]; + + // Deprecated. Use deployment_options instead. + // Information about this worker's build identifier and if it is choosing to use the versioning + // feature. See the `WorkerVersionCapabilities` docstring for more. + temporal.api.common.v1.WorkerVersionCapabilities worker_version_capabilities = 5 [deprecated = true]; + + // Worker deployment options that user has set in the worker. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 6; + + reserved 7; + + reserved "worker_heartbeat"; +} + +message PollWorkflowTaskQueueResponse { + // A unique identifier for this task + bytes task_token = 1; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + temporal.api.common.v1.WorkflowType workflow_type = 3; + + // The last workflow task started event which was processed by some worker for this execution. + // Will be zero if no task has ever started. + int64 previous_started_event_id = 4; + + // The id of the most recent workflow task started event, which will have been generated as a + // result of this poll request being served. Will be zero if the task + // does not contain any events which would advance history (no new WFT started). + // Currently this can happen for queries. + int64 started_event_id = 5; + + // Starting at 1, the number of attempts to complete this task by any worker. + int32 attempt = 6; + + // A hint that there are more tasks already present in this task queue + // partition. Can be used to prioritize draining a sticky queue. + // + // Specifically, the returned number is the number of tasks remaining in + // the in-memory buffer for this partition, which is currently capped at + // 1000. Because sticky queues only have one partition, this number is + // more useful when draining them. Normal queues, typically having more than one + // partition, will return a number representing only some portion of the + // overall backlog. Subsequent RPCs may not hit the same partition as + // this call. + int64 backlog_count_hint = 7; + + // The history for this workflow, which will either be complete or partial. Partial histories + // are sent to workers who have signaled that they are using a sticky queue when completing + // a workflow task. + temporal.api.history.v1.History history = 8; + + // Will be set if there are more history events than were included in this response. Such events + // should be fetched via `GetWorkflowExecutionHistory`. + bytes next_page_token = 9; + + // Legacy queries appear in this field. The query must be responded to via + // `RespondQueryTaskCompleted`. If the workflow is already closed (queries are permitted on + // closed workflows) then the `history` field will be populated with the entire history. It + // may also be populated if this task originates on a non-sticky queue. + temporal.api.query.v1.WorkflowQuery query = 10; + + // The task queue this task originated from, which will always be the original non-sticky name + // for the queue, even if this response came from polling a sticky queue. + temporal.api.taskqueue.v1.TaskQueue workflow_execution_task_queue = 11; + + // When this task was scheduled by the server + google.protobuf.Timestamp scheduled_time = 12; + + // When the current workflow task started event was generated, meaning the current attempt. + google.protobuf.Timestamp started_time = 13; + + // Queries that should be executed after applying the history in this task. Responses should be + // attached to `RespondWorkflowTaskCompletedRequest::query_results` + map queries = 14; + + // Protocol messages piggybacking on a WFT as a transport + repeated temporal.api.protocol.v1.Message messages = 15; + + // Server-advised information the SDK may use to adjust its poller count. + temporal.api.taskqueue.v1.PollerScalingDecision poller_scaling_decision = 16; + + // This poller group ID identifies the owner of the workflow task awaiting for query response. + // Corresponding RespondQueryTaskCompleted should pass this value for proper routing. + string poller_group_id = 17; + + // Deprecated. Use `poller_groups_info` instead, which carries a version so the client can + // ignore stale updates. + // The weighted list of poller groups IDs that client should use for future polls to this task + // queue. Client is expected to: + // 1. Maintain minimum number of pollers no less than the number of groups. + // 2. Try to assign the next poll to a group without any pending polls, + // 3. If every group has some pending polls, assign the next poll to a group randomly + // according to the weights. + repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 18 [deprecated = true]; + + // The weighted, versioned list of poller groups IDs that client should use for future polls to + // this task queue. Client should ignore this if it has already applied a snapshot with a + // version greater than or equal to `poller_groups_info.version`. Client is expected to: + // 1. Maintain minimum number of pollers no less than the number of groups. + // 2. Try to assign the next poll to a group without any pending polls, + // 3. If every group has some pending polls, assign the next poll to a group randomly + // according to the weights. + temporal.api.taskqueue.v1.PollerGroupsInfo poller_groups_info = 19; +} + +message RespondWorkflowTaskCompletedRequest { + // The task token as received in `PollWorkflowTaskQueueResponse` + bytes task_token = 1; + + // A list of commands generated when driving the workflow code in response to the new task + repeated temporal.api.command.v1.Command commands = 2; + + // The identity of the worker/client + string identity = 3; + + // May be set by workers to indicate that the worker desires future tasks to be provided with + // incremental history on a sticky queue. + temporal.api.taskqueue.v1.StickyExecutionAttributes sticky_attributes = 4; + + // If set, the worker wishes to immediately receive the next workflow task as a response to + // this completion. This can save on polling round-trips. + bool return_new_workflow_task = 5; + + // Can be used to *force* creation of a new workflow task, even if no commands have resolved or + // one would not otherwise have been generated. This is used when the worker knows it is doing + // something useful, but cannot complete it within the workflow task timeout. Local activities + // which run for longer than the task timeout being the prime example. + bool force_create_new_workflow_task = 6; + + // Deprecated. Use `deployment_options` instead. + // Worker process' unique binary id + string binary_checksum = 7 [deprecated = true]; + + // Responses to the `queries` field in the task being responded to + map query_results = 8; + + string namespace = 9; + + // Resource ID for routing. Contains the workflow ID from the original task. + string resource_id = 18; + + // Version info of the worker who processed this task. This message's `build_id` field should + // always be set by SDKs. Workers opting into versioning will also set the `use_versioning` + // field to true. See message docstrings for more. + // Deprecated. Use `deployment_options` and `versioning_behavior` instead. + temporal.api.common.v1.WorkerVersionStamp worker_version_stamp = 10 [deprecated = true]; + + // Protocol messages piggybacking on a WFT as a transport + repeated temporal.api.protocol.v1.Message messages = 11; + + // Data the SDK wishes to record for itself, but server need not interpret, and does not + // directly impact workflow state. + temporal.api.sdk.v1.WorkflowTaskCompletedMetadata sdk_metadata = 12; + + // Local usage data collected for metering + temporal.api.common.v1.MeteringMetadata metering_metadata = 13; + + // All capabilities the SDK supports. + Capabilities capabilities = 14; + + // Deployment info of the worker that completed this task. Must be present if user has set + // `WorkerDeploymentOptions` regardless of versioning being enabled or not. + // Deprecated. Replaced with `deployment_options`. + temporal.api.deployment.v1.Deployment deployment = 15 [deprecated = true]; + + // Versioning behavior of this workflow execution as set on the worker that completed this task. + // UNSPECIFIED means versioning is not enabled in the worker. + temporal.api.enums.v1.VersioningBehavior versioning_behavior = 16; + + // Worker deployment options that user has set in the worker. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 17; + + // A unique key for this worker instance, used for tracking worker lifecycle. + // This is guaranteed to be unique, whereas identity is not guaranteed to be unique. + string worker_instance_key = 19; + + // A dedicated per-worker Nexus task queue on which the server sends control + // tasks (e.g. activity cancellation) to this specific worker instance. + string worker_control_task_queue = 20; + + // 0-indexed page number when the workflow task completion is split across multiple + // requests ("pages"). 0 for single-page requests. May only be set to non-zero value + // when the namespace capability workflow_task_completion_pagination is true. + int32 page_number = 21; + + // True for non-final pages of a paginated workflow task completion. The final page's + // `page_number` tells the server how many intermediate pages (0..page_number-1) preceded it. + // May only be used when the namespace capability workflow_task_completion_pagination is true. + bool intermediate_page = 22; + + // SDK capability details. + message Capabilities { + // True if the SDK can handle speculative workflow task with command events. If true, the + // server may choose, at its discretion, to discard a speculative workflow task even if that + // speculative task included command events the SDK had not previously processed. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "with" used to describe the workflow task. --) + bool discard_speculative_workflow_task_with_events = 1; + } +} + +message RespondWorkflowTaskCompletedResponse { + // See `RespondWorkflowTaskCompletedResponse::return_new_workflow_task` + PollWorkflowTaskQueueResponse workflow_task = 1; + + // See `ScheduleActivityTaskCommandAttributes::request_eager_execution` + repeated PollActivityTaskQueueResponse activity_tasks = 2; + + // If non zero, indicates the server has discarded the workflow task that was being responded to. + // Will be the event ID of the last workflow task started event in the history before the new workflow task. + // Server is only expected to discard a workflow task if it could not have modified the workflow state. + int64 reset_history_event_id = 3; +} + +message RespondWorkflowTaskFailedRequest { + // The task token as received in `PollWorkflowTaskQueueResponse` + bytes task_token = 1; + + // Why did the task fail? It's important to note that many of the variants in this enum cannot + // apply to worker responses. See the type's doc for more. + temporal.api.enums.v1.WorkflowTaskFailedCause cause = 2; + + // Failure details + temporal.api.failure.v1.Failure failure = 3; + + // The identity of the worker/client + string identity = 4; + + // Deprecated. Use `deployment_options` instead. + // Worker process' unique binary id + string binary_checksum = 5 [deprecated = true]; + + string namespace = 6; + + // Resource ID for routing. Contains the workflow ID from the original task. + string resource_id = 11; + + // Protocol messages piggybacking on a WFT as a transport + repeated temporal.api.protocol.v1.Message messages = 7; + + // Version info of the worker who processed this task. This message's `build_id` field should + // always be set by SDKs. Workers opting into versioning will also set the `use_versioning` + // field to true. See message docstrings for more. + // Deprecated. Use `deployment_options` instead. + temporal.api.common.v1.WorkerVersionStamp worker_version = 8 [deprecated = true]; + + // Deployment info of the worker that completed this task. Must be present if user has set + // `WorkerDeploymentOptions` regardless of versioning being enabled or not. + // Deprecated. Replaced with `deployment_options`. + temporal.api.deployment.v1.Deployment deployment = 9 [deprecated = true]; + + // Worker deployment options that user has set in the worker. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 10; +} + +message RespondWorkflowTaskFailedResponse {} + +message PollActivityTaskQueueRequest { + string namespace = 1; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 2; + + // Unless this is the first poll, the client must pass one of the poller group IDs received in + // `poller_group_infos` of the last the PollActivityTaskQueueResponse according to the + // instructions. If not set, the poll is routed randomly which can cause it to be blocked + // without receiving a task while the queue actually has tasks in another server location. + string poller_group_id = 10; + + // The identity of the worker/client + string identity = 3; + + // A unique key for this worker instance, used for tracking worker lifecycle. + // This is guaranteed to be unique, whereas identity is not guaranteed to be unique. + string worker_instance_key = 8; + + // A dedicated per-worker Nexus task queue on which the server sends control + // tasks (e.g. activity cancellation) to this specific worker instance. + string worker_control_task_queue = 9; + + temporal.api.taskqueue.v1.TaskQueueMetadata task_queue_metadata = 4; + + // Information about this worker's build identifier and if it is choosing to use the versioning + // feature. See the `WorkerVersionCapabilities` docstring for more. + // Deprecated. Replaced by deployment_options. + temporal.api.common.v1.WorkerVersionCapabilities worker_version_capabilities = 5 [deprecated = true]; + + // Worker deployment options that user has set in the worker. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 6; + + reserved 7; + + reserved "worker_heartbeat"; +} + +message PollActivityTaskQueueResponse { + // A unique identifier for this task + bytes task_token = 1; + + // The namespace of the activity. If this is a workflow activity then this is the namespace of + // the workflow also. If this is a standalone activity then the name of this field is + // misleading, but retained for compatibility with workflow activities. + string workflow_namespace = 2; + + // Type of the requesting workflow (if this is a workflow activity). + temporal.api.common.v1.WorkflowType workflow_type = 3; + + // Execution info of the requesting workflow (if this is a workflow activity) + temporal.api.common.v1.WorkflowExecution workflow_execution = 4; + + temporal.api.common.v1.ActivityType activity_type = 5; + + // The autogenerated or user specified identifier of this activity. Can be used to complete the + // activity via `RespondActivityTaskCompletedById`. May be re-used as long as the last usage + // has resolved, but unique IDs for every activity invocation is a good idea. + // Note that only a workflow activity ID may be autogenerated. + string activity_id = 6; + + // Headers specified by the scheduling workflow. Commonly used to propagate contextual info + // from the workflow to its activities. For example, tracing contexts. + temporal.api.common.v1.Header header = 7; + + // Arguments to the activity invocation + temporal.api.common.v1.Payloads input = 8; + + // Details of the last heartbeat that was recorded for this activity as of the time this task + // was delivered. + temporal.api.common.v1.Payloads heartbeat_details = 9; + + // When was this task first scheduled + google.protobuf.Timestamp scheduled_time = 10; + + // When was this task attempt scheduled + google.protobuf.Timestamp current_attempt_scheduled_time = 11; + + // When was this task started (this attempt) + google.protobuf.Timestamp started_time = 12; + + // Starting at 1, the number of attempts to perform this activity + int32 attempt = 13; + + // First scheduled -> final result reported timeout + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 14; + + // Current attempt start -> final result reported timeout + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 15; + + // Window within which the activity must report a heartbeat, or be timed out. + google.protobuf.Duration heartbeat_timeout = 16; + + // This is the retry policy the service uses which may be different from the one provided + // (or not) during activity scheduling. The service can override the provided one if some + // values are not specified or exceed configured system limits. + temporal.api.common.v1.RetryPolicy retry_policy = 17; + + // Server-advised information the SDK may use to adjust its poller count. + temporal.api.taskqueue.v1.PollerScalingDecision poller_scaling_decision = 18; + + // Priority metadata + temporal.api.common.v1.Priority priority = 19; + + // The run ID of the activity execution, only set for standalone activities. + string activity_run_id = 20; + + // The weighted list of poller groups IDs that client should use for future polls to this task + // queue. Client is expected to: + // 1. Maintain minimum number of pollers no less than the number of groups. + // 2. Try to assign the next poll to a group without any pending polls, + // 3. If every group has some pending polls, assign the next poll to a group randomly + // according to the weights. + repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 21 [deprecated = true]; + + // The weighted, versioned list of poller groups IDs that client should use for future polls to + // this task queue. Client should ignore this if it has already applied a snapshot with a + // version greater than or equal to `poller_groups_info.version`. Client is expected to: + // 1. Maintain minimum number of pollers no less than the number of groups. + // 2. Try to assign the next poll to a group without any pending polls, + // 3. If every group has some pending polls, assign the next poll to a group randomly + // according to the weights. + temporal.api.taskqueue.v1.PollerGroupsInfo poller_groups_info = 22; +} + +message RecordActivityTaskHeartbeatRequest { + // The task token as received in `PollActivityTaskQueueResponse` + bytes task_token = 1; + + // Arbitrary data, of which the most recent call is kept, to store for this activity + temporal.api.common.v1.Payloads details = 2; + + // The identity of the worker/client + string identity = 3; + + string namespace = 4; + + // Resource ID for routing. Contains the workflow ID or activity ID for standalone activities. + string resource_id = 5; +} + +message RecordActivityTaskHeartbeatResponse { + // Will be set to true if the activity has been asked to cancel itself. The SDK should then + // notify the activity of cancellation if it is still running. + bool cancel_requested = 1; + + // Will be set to true if the activity is paused. + bool activity_paused = 2; + + // Will be set to true if the activity was reset. + // Applies only to the current run. + bool activity_reset = 3; +} + +message RecordActivityTaskHeartbeatByIdRequest { + // Namespace of the workflow which scheduled this activity + string namespace = 1; + + // Id of the workflow which scheduled this activity, leave empty to target a standalone activity + string workflow_id = 2; + + // For a workflow activity - the run ID of the workflow which scheduled this activity. + // For a standalone activity - the run ID of the activity. + string run_id = 3; + + // Id of the activity we're heartbeating + string activity_id = 4; + + // Arbitrary data, of which the most recent call is kept, to store for this activity + temporal.api.common.v1.Payloads details = 5; + + // The identity of the worker/client + string identity = 6; + + // Resource ID for routing. Contains "workflow:workflow_id" or "activity:activity_id" for standalone activities. + string resource_id = 7; +} + +message RecordActivityTaskHeartbeatByIdResponse { + // Will be set to true if the activity has been asked to cancel itself. The SDK should then + // notify the activity of cancellation if it is still running. + bool cancel_requested = 1; + + // Will be set to true if the activity is paused. + bool activity_paused = 2; + + // Will be set to true if the activity was reset. + // Applies only to the current run. + bool activity_reset = 3; +} + +message RespondActivityTaskCompletedRequest { + // The task token as received in `PollActivityTaskQueueResponse` + bytes task_token = 1; + + // The result of successfully executing the activity + temporal.api.common.v1.Payloads result = 2; + + // The identity of the worker/client + string identity = 3; + + string namespace = 4; + + // Resource ID for routing. Contains the workflow ID or activity ID for standalone activities. + string resource_id = 8; + + // Version info of the worker who processed this task. This message's `build_id` field should + // always be set by SDKs. Workers opting into versioning will also set the `use_versioning` + // field to true. See message docstrings for more. + // Deprecated. Use `deployment_options` instead. + temporal.api.common.v1.WorkerVersionStamp worker_version = 5 [deprecated = true]; + + // Deployment info of the worker that completed this task. Must be present if user has set + // `WorkerDeploymentOptions` regardless of versioning being enabled or not. + // Deprecated. Replaced with `deployment_options`. + temporal.api.deployment.v1.Deployment deployment = 6 [deprecated = true]; + + // Worker deployment options that user has set in the worker. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 7; +} + +message RespondActivityTaskCompletedResponse {} + +message RespondActivityTaskCompletedByIdRequest { + // Namespace of the workflow which scheduled this activity + string namespace = 1; + + // Id of the workflow which scheduled this activity, leave empty to target a standalone activity + string workflow_id = 2; + + // For a workflow activity - the run ID of the workflow which scheduled this activity. + // For a standalone activity - the run ID of the activity. + string run_id = 3; + + // Id of the activity to complete + string activity_id = 4; + + // The serialized result of activity execution + temporal.api.common.v1.Payloads result = 5; + + // The identity of the worker/client + string identity = 6; + + // Resource ID for routing. Contains "workflow:workflow_id" or "activity:activity_id" for standalone activities. + string resource_id = 7; +} + +message RespondActivityTaskCompletedByIdResponse {} + +message RespondActivityTaskFailedRequest { + // The task token as received in `PollActivityTaskQueueResponse` + bytes task_token = 1; + + // Detailed failure information + temporal.api.failure.v1.Failure failure = 2; + + // The identity of the worker/client + string identity = 3; + + string namespace = 4; + + // Resource ID for routing. Contains the workflow ID or activity ID for standalone activities. + string resource_id = 9; + + // Additional details to be stored as last activity heartbeat + temporal.api.common.v1.Payloads last_heartbeat_details = 5; + + // Version info of the worker who processed this task. This message's `build_id` field should + // always be set by SDKs. Workers opting into versioning will also set the `use_versioning` + // field to true. See message docstrings for more. + // Deprecated. Use `deployment_options` instead. + temporal.api.common.v1.WorkerVersionStamp worker_version = 6 [deprecated = true]; + + // Deployment info of the worker that completed this task. Must be present if user has set + // `WorkerDeploymentOptions` regardless of versioning being enabled or not. + // Deprecated. Replaced with `deployment_options`. + temporal.api.deployment.v1.Deployment deployment = 7 [deprecated = true]; + + // Worker deployment options that user has set in the worker. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 8; +} + +message RespondActivityTaskFailedResponse { + // Server validation failures could include + // last_heartbeat_details payload is too large, request failure is too large + repeated temporal.api.failure.v1.Failure failures = 1; +} + +message RespondActivityTaskFailedByIdRequest { + // Namespace of the workflow which scheduled this activity + string namespace = 1; + + // Id of the workflow which scheduled this activity, leave empty to target a standalone activity + string workflow_id = 2; + + // For a workflow activity - the run ID of the workflow which scheduled this activity. + // For a standalone activity - the run ID of the activity. + string run_id = 3; + + // Id of the activity to fail + string activity_id = 4; + + // Detailed failure information + temporal.api.failure.v1.Failure failure = 5; + + // The identity of the worker/client + string identity = 6; + + // Additional details to be stored as last activity heartbeat + temporal.api.common.v1.Payloads last_heartbeat_details = 7; + + // Resource ID for routing. Contains "workflow:workflow_id" or "activity:activity_id" for standalone activities. + string resource_id = 8; +} + +message RespondActivityTaskFailedByIdResponse { + // Server validation failures could include + // last_heartbeat_details payload is too large, request failure is too large + repeated temporal.api.failure.v1.Failure failures = 1; +} + +message RespondActivityTaskCanceledRequest { + // The task token as received in `PollActivityTaskQueueResponse` + bytes task_token = 1; + + // Serialized additional information to attach to the cancellation + temporal.api.common.v1.Payloads details = 2; + + // The identity of the worker/client + string identity = 3; + + string namespace = 4; + + // Resource ID for routing. Contains the workflow ID or activity ID for standalone activities. + string resource_id = 8; + + // Version info of the worker who processed this task. This message's `build_id` field should + // always be set by SDKs. Workers opting into versioning will also set the `use_versioning` + // field to true. See message docstrings for more. + // Deprecated. Use `deployment_options` instead. + temporal.api.common.v1.WorkerVersionStamp worker_version = 5 [deprecated = true]; + + // Deployment info of the worker that completed this task. Must be present if user has set + // `WorkerDeploymentOptions` regardless of versioning being enabled or not. + // Deprecated. Replaced with `deployment_options`. + temporal.api.deployment.v1.Deployment deployment = 6 [deprecated = true]; + + // Worker deployment options that user has set in the worker. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 7; +} + +message RespondActivityTaskCanceledResponse {} + +message RespondActivityTaskCanceledByIdRequest { + // Namespace of the workflow which scheduled this activity + string namespace = 1; + + // Id of the workflow which scheduled this activity, leave empty to target a standalone activity + string workflow_id = 2; + + // For a workflow activity - the run ID of the workflow which scheduled this activity. + // For a standalone activity - the run ID of the activity. + string run_id = 3; + + // Id of the activity to confirm is cancelled + string activity_id = 4; + + // Serialized additional information to attach to the cancellation + temporal.api.common.v1.Payloads details = 5; + + // The identity of the worker/client + string identity = 6; + + // Worker deployment options that user has set in the worker. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 7; + + // Resource ID for routing. Contains "workflow:workflow_id" or "activity:activity_id" for standalone activities. + string resource_id = 8; +} + +message RespondActivityTaskCanceledByIdResponse {} + +message RequestCancelWorkflowExecutionRequest { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + // The identity of the worker/client + string identity = 3; + + // Used to de-dupe cancellation requests + string request_id = 4; + + // If set, this call will error if the most recent (if no run id is set on + // `workflow_execution`), or specified (if it is) workflow execution is not part of the same + // execution chain as this id. + string first_execution_run_id = 5; + + // Reason for requesting the cancellation + string reason = 6; + + // Links to be associated with the WorkflowExecutionCanceled event. + repeated temporal.api.common.v1.Link links = 7; +} + +message RequestCancelWorkflowExecutionResponse {} + +// Keep the parameters in sync with: +// - temporal.api.batch.v1.BatchOperationSignal. +// - temporal.api.workflow.v1.PostResetOperation.SignalWorkflow. +message SignalWorkflowExecutionRequest { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + // The workflow author-defined name of the signal to send to the workflow + string signal_name = 3; + + // Serialized value(s) to provide with the signal + temporal.api.common.v1.Payloads input = 4; + + // The identity of the worker/client + string identity = 5; + + // Used to de-dupe sent signals + string request_id = 6; + + // Deprecated. + string control = 7 [deprecated = true]; + + // Headers that are passed with the signal to the processing workflow. + // These can include things like auth or tracing tokens. + temporal.api.common.v1.Header header = 8; + + reserved 9; + + // Links to be associated with the WorkflowExecutionSignaled event. + repeated temporal.api.common.v1.Link links = 10; +} + +message SignalWorkflowExecutionResponse { + // Link to be associated with the WorkflowExecutionSignaled event. + // Added on the response to propagate the backlink. + // Available from Temporal server 1.31 and up. + temporal.api.common.v1.Link link = 1; +} + +message SignalWithStartWorkflowExecutionRequest { + string namespace = 1; + + string workflow_id = 2; + + temporal.api.common.v1.WorkflowType workflow_type = 3; + + // The task queue to start this workflow on, if it will be started + temporal.api.taskqueue.v1.TaskQueue task_queue = 4; + + // Serialized arguments to the workflow. These are passed as arguments to the workflow function. + temporal.api.common.v1.Payloads input = 5; + + // Total workflow execution timeout including retries and continue as new + google.protobuf.Duration workflow_execution_timeout = 6; + + // Timeout of a single workflow run + google.protobuf.Duration workflow_run_timeout = 7; + + // Timeout of a single workflow task + google.protobuf.Duration workflow_task_timeout = 8; + + // The identity of the worker/client + string identity = 9; + + // Used to de-dupe signal w/ start requests + string request_id = 10; + + // Defines whether to allow re-using the workflow id from a previously *closed* workflow. + // The default policy is WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE. + // + // See `workflow_id_reuse_policy` for handling a workflow id duplication with a *running* workflow. + temporal.api.enums.v1.WorkflowIdReusePolicy workflow_id_reuse_policy = 11; + + // Defines how to resolve a workflow id conflict with a *running* workflow. + // The default policy is WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING. + // Note that WORKFLOW_ID_CONFLICT_POLICY_FAIL is an invalid option. + // + // See `workflow_id_reuse_policy` for handling a workflow id duplication with a *closed* workflow. + temporal.api.enums.v1.WorkflowIdConflictPolicy workflow_id_conflict_policy = 22; + + // The workflow author-defined name of the signal to send to the workflow + string signal_name = 12; + + // Serialized value(s) to provide with the signal + temporal.api.common.v1.Payloads signal_input = 13; + + // Deprecated. + string control = 14 [deprecated = true]; + + // Retry policy for the workflow + temporal.api.common.v1.RetryPolicy retry_policy = 15; + + // See https://docs.temporal.io/docs/content/what-is-a-temporal-cron-job/ + string cron_schedule = 16; + + temporal.api.common.v1.Memo memo = 17; + + temporal.api.common.v1.SearchAttributes search_attributes = 18; + + temporal.api.common.v1.Header header = 19; + + // Time to wait before making the first workflow task available for dispatch. Cannot be used with `cron_schedule`. + // Note that the signal will be delivered with the first workflow task. If the workflow gets + // another SignalWithStartWorkflow before the delay a workflow task will be made available for dispatch immediately + // and the rest of the delay period will be ignored, even if that request also had a delay. + // Signal via SignalWorkflowExecution will not unblock the workflow. + google.protobuf.Duration workflow_start_delay = 20; + + reserved 21; + + // Metadata on the workflow if it is started. This is carried over to the WorkflowExecutionInfo + // for use by user interfaces to display the fixed as-of-start summary and details of the + // workflow. + temporal.api.sdk.v1.UserMetadata user_metadata = 23; + + // Links to be associated with the WorkflowExecutionStarted and WorkflowExecutionSignaled events. + repeated temporal.api.common.v1.Link links = 24; + + // If set, takes precedence over the Versioning Behavior sent by the SDK on Workflow Task completion. + // To unset the override after the workflow is running, use UpdateWorkflowExecutionOptions. + temporal.api.workflow.v1.VersioningOverride versioning_override = 25; + + // Priority metadata + temporal.api.common.v1.Priority priority = 26; + + // Time-skipping configuration. If not set, time skipping is disabled. + temporal.api.common.v1.TimeSkippingConfig time_skipping_config = 27; +} + +message SignalWithStartWorkflowExecutionResponse { + // The run id of the workflow that was started - or just signaled, if it was already running. + string run_id = 1; + + // If the workflow was started as a result of a de-dupe, this field will contain the run id of the first execution in the chain. + string first_execution_run_id = 4; + + // If true, a new workflow was started. + bool started = 2; + + // Link to be associated with the WorkflowExecutionSignaled event. + // Added on the response to propagate the backlink. + // Available from Temporal server 1.31 and up. + temporal.api.common.v1.Link signal_link = 3; +} + +message ResetWorkflowExecutionRequest { + string namespace = 1; + + // The workflow to reset. If this contains a run ID then the workflow will be reset back to the + // provided event ID in that run. Otherwise it will be reset to the provided event ID in the + // current run. In all cases the current run will be terminated and a new run started. + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + string reason = 3; + + // The id of a `WORKFLOW_TASK_COMPLETED`,`WORKFLOW_TASK_TIMED_OUT`, `WORKFLOW_TASK_FAILED`, or + // `WORKFLOW_TASK_STARTED` event to reset to. + int64 workflow_task_finish_event_id = 4; + + // Used to de-dupe reset requests + string request_id = 5; + + // Deprecated. Use `options`. + // Default: RESET_REAPPLY_TYPE_SIGNAL + temporal.api.enums.v1.ResetReapplyType reset_reapply_type = 6 [deprecated = true]; + + // Event types not to be reapplied + repeated temporal.api.enums.v1.ResetReapplyExcludeType reset_reapply_exclude_types = 7; + + // Operations to perform after the workflow has been reset. These operations will be applied + // to the *new* run of the workflow execution in the order they are provided. + // All operations are applied to the workflow before the first new workflow task is generated + repeated temporal.api.workflow.v1.PostResetOperation post_reset_operations = 8; + + // The identity of the worker/client + string identity = 9; +} + +message ResetWorkflowExecutionResponse { + string run_id = 1; +} + +message TerminateWorkflowExecutionRequest { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + string reason = 3; + + // Serialized additional information to attach to the termination event + temporal.api.common.v1.Payloads details = 4; + + // The identity of the worker/client + string identity = 5; + + // If set, this call will error if the most recent (if no run id is set on + // `workflow_execution`), or specified (if it is) workflow execution is not part of the same + // execution chain as this id. + string first_execution_run_id = 6; + + // Links to be associated with the WorkflowExecutionTerminated event. + repeated temporal.api.common.v1.Link links = 7; +} + +message TerminateWorkflowExecutionResponse {} + +message DeleteWorkflowExecutionRequest { + string namespace = 1; + + // Workflow Execution to delete. If run_id is not specified, the latest one is used. + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; +} + +message DeleteWorkflowExecutionResponse {} + +message ListOpenWorkflowExecutionsRequest { + string namespace = 1; + + int32 maximum_page_size = 2; + + bytes next_page_token = 3; + + temporal.api.filter.v1.StartTimeFilter start_time_filter = 4; + + oneof filters { + temporal.api.filter.v1.WorkflowExecutionFilter execution_filter = 5; + + temporal.api.filter.v1.WorkflowTypeFilter type_filter = 6; + } +} + +message ListOpenWorkflowExecutionsResponse { + repeated temporal.api.workflow.v1.WorkflowExecutionInfo executions = 1; + + bytes next_page_token = 2; +} + +message ListClosedWorkflowExecutionsRequest { + string namespace = 1; + + int32 maximum_page_size = 2; + + bytes next_page_token = 3; + + temporal.api.filter.v1.StartTimeFilter start_time_filter = 4; + + oneof filters { + temporal.api.filter.v1.WorkflowExecutionFilter execution_filter = 5; + + temporal.api.filter.v1.WorkflowTypeFilter type_filter = 6; + + temporal.api.filter.v1.StatusFilter status_filter = 7; + } +} + +message ListClosedWorkflowExecutionsResponse { + repeated temporal.api.workflow.v1.WorkflowExecutionInfo executions = 1; + + bytes next_page_token = 2; +} + +message ListWorkflowExecutionsRequest { + string namespace = 1; + + int32 page_size = 2; + + bytes next_page_token = 3; + + string query = 4; +} + +message ListWorkflowExecutionsResponse { + repeated temporal.api.workflow.v1.WorkflowExecutionInfo executions = 1; + + bytes next_page_token = 2; +} + +message ListArchivedWorkflowExecutionsRequest { + string namespace = 1; + + int32 page_size = 2; + + bytes next_page_token = 3; + + string query = 4; +} + +message ListArchivedWorkflowExecutionsResponse { + repeated temporal.api.workflow.v1.WorkflowExecutionInfo executions = 1; + + bytes next_page_token = 2; +} + +// Deprecated: Use with `ListWorkflowExecutions`. +message ScanWorkflowExecutionsRequest { + string namespace = 1; + + int32 page_size = 2; + + bytes next_page_token = 3; + + string query = 4; +} + +// Deprecated: Use with `ListWorkflowExecutions`. +message ScanWorkflowExecutionsResponse { + repeated temporal.api.workflow.v1.WorkflowExecutionInfo executions = 1; + + bytes next_page_token = 2; +} + +message CountWorkflowExecutionsRequest { + string namespace = 1; + + string query = 2; +} + +message CountWorkflowExecutionsResponse { + // If `query` is not grouping by any field, the count is an approximate number + // of workflows that matches the query. + // If `query` is grouping by a field, the count is simply the sum of the counts + // of the groups returned in the response. This number can be smaller than the + // total number of workflows matching the query. + int64 count = 1; + + // `groups` contains the groups if the request is grouping by a field. + // The list might not be complete, and the counts of each group is approximate. + repeated AggregationGroup groups = 2; + + message AggregationGroup { + repeated temporal.api.common.v1.Payload group_values = 1; + + int64 count = 2; + } +} + +message GetSearchAttributesRequest {} + +message GetSearchAttributesResponse { + map keys = 1; +} + +message RespondQueryTaskCompletedRequest { + bytes task_token = 1; + + temporal.api.enums.v1.QueryResultType completed_type = 2; + + // The result of the query. + // Mutually exclusive with `error_message` and `failure`. Set when the query succeeds. + temporal.api.common.v1.Payloads query_result = 3; + + // A plain error message that must be set if completed_type is QUERY_RESULT_TYPE_FAILED. + // SDKs should also fill in the more complete `failure` field to provide the full context and + // support encryption of failure information. + // `error_message` will be duplicated if the `failure` field is present to support callers + // that pre-date the addition of that field, regardless of whether or not a custom failure + // converter is used. + // Mutually exclusive with `query_result`. Set when the query fails. + string error_message = 4; + + reserved 5; + + string namespace = 6; + + // The full reason for this query failure. This field is newer than `error_message` and can be + // encoded by the SDK's failure converter to support E2E encryption of messages and stack + // traces. + // Mutually exclusive with `query_result`. Set when the query fails. + temporal.api.failure.v1.Failure failure = 7; + + // Why did the task fail? It's important to note that many of the variants in this enum cannot + // apply to worker responses. See the type's doc for more. + temporal.api.enums.v1.WorkflowTaskFailedCause cause = 8; + + // Client must forward the poller_group_id received in PollWorkflowTaskQueueResponse for proper + // routing of the response. + string poller_group_id = 9; +} + +message RespondQueryTaskCompletedResponse {} + +message ResetStickyTaskQueueRequest { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution execution = 2; +} + +message ResetStickyTaskQueueResponse {} + +message ShutdownWorkerRequest { + string namespace = 1; + + // sticky_task_queue may not always be populated. We want to ensure all workers + // send a shutdown request to update worker state for heartbeating, as well + // as cancel pending poll calls early, instead of waiting for timeouts. + string sticky_task_queue = 2; + + string identity = 3; + + string reason = 4; + + temporal.api.worker.v1.WorkerHeartbeat worker_heartbeat = 5; + + // Technically this is also sent in the WorkerHeartbeat, but + // since worker heartbeating can be turned off, this needs + // to be a separate, top-level field. + string worker_instance_key = 6; + + // Task queue name the worker is polling on. This allows server to cancel + // all outstanding poll RPC calls from SDK. This avoids a race condition that + // can lead to tasks being lost. + string task_queue = 7; + + // Task queue types that help server cancel outstanding poll RPC + // calls from SDK. This avoids a race condition that can lead to tasks being lost. + repeated temporal.api.enums.v1.TaskQueueType task_queue_types = 8; +} + +message ShutdownWorkerResponse {} + +message QueryWorkflowRequest { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution execution = 2; + + temporal.api.query.v1.WorkflowQuery query = 3; + + // QueryRejectCondition can used to reject the query if workflow state does not satisfy condition. + // Default: QUERY_REJECT_CONDITION_NONE. + temporal.api.enums.v1.QueryRejectCondition query_reject_condition = 4; +} + +message QueryWorkflowResponse { + temporal.api.common.v1.Payloads query_result = 1; + + temporal.api.query.v1.QueryRejected query_rejected = 2; + + // Holds the link to the Workflow execution that processed the Query. + temporal.api.common.v1.Link link = 3; +} + +message DescribeWorkflowExecutionRequest { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution execution = 2; +} + +message DescribeWorkflowExecutionResponse { + temporal.api.workflow.v1.WorkflowExecutionConfig execution_config = 1; + + temporal.api.workflow.v1.WorkflowExecutionInfo workflow_execution_info = 2; + + repeated temporal.api.workflow.v1.PendingActivityInfo pending_activities = 3; + + repeated temporal.api.workflow.v1.PendingChildExecutionInfo pending_children = 4; + + temporal.api.workflow.v1.PendingWorkflowTaskInfo pending_workflow_task = 5; + + repeated temporal.api.workflow.v1.CallbackInfo callbacks = 6; + + repeated temporal.api.workflow.v1.PendingNexusOperationInfo pending_nexus_operations = 7; + + temporal.api.workflow.v1.WorkflowExecutionExtendedInfo workflow_extended_info = 8; +} + +// (-- api-linter: core::0203::optional=disabled +// aip.dev/not-precedent: field_behavior annotation not available in our gogo fork --) +message DescribeTaskQueueRequest { + string namespace = 1; + + // Sticky queues are not supported in deprecated ENHANCED mode. + temporal.api.taskqueue.v1.TaskQueue task_queue = 2; + + // If unspecified (TASK_QUEUE_TYPE_UNSPECIFIED), then default value (TASK_QUEUE_TYPE_WORKFLOW) will be used. + // Only supported in default mode (use `task_queue_types` in ENHANCED mode instead). + temporal.api.enums.v1.TaskQueueType task_queue_type = 3; + + // Report stats for the requested task queue type(s). + bool report_stats = 8; + + // Report Task Queue Config + bool report_config = 11; + + // Deprecated, use `report_stats` instead. + // If true, the task queue status will be included in the response. + bool include_task_queue_status = 4 [deprecated = true]; + + // Deprecated. ENHANCED mode is also being deprecated. + // Select the API mode to use for this request: DEFAULT mode (if unset) or ENHANCED mode. + // Consult the documentation for each field to understand which mode it is supported in. + temporal.api.enums.v1.DescribeTaskQueueMode api_mode = 5 [deprecated = true]; + + // Deprecated (as part of the ENHANCED mode deprecation). + // Optional. If not provided, the result for the default Build ID will be returned. The default Build ID is the one + // mentioned in the first unconditional Assignment Rule. If there is no default Build ID, the result for the + // unversioned queue will be returned. + // (-- api-linter: core::0140::prepositions --) + temporal.api.taskqueue.v1.TaskQueueVersionSelection versions = 6 [deprecated = true]; + + // Deprecated (as part of the ENHANCED mode deprecation). + // Task queue types to report info about. If not specified, all types are considered. + repeated temporal.api.enums.v1.TaskQueueType task_queue_types = 7 [deprecated = true]; + + // Deprecated (as part of the ENHANCED mode deprecation). + // Report list of pollers for requested task queue types and versions. + bool report_pollers = 9 [deprecated = true]; + + // Deprecated (as part of the ENHANCED mode deprecation). + // Report task reachability for the requested versions and all task types (task reachability is not reported + // per task type). + bool report_task_reachability = 10 [deprecated = true]; +} + +message DescribeTaskQueueResponse { + repeated temporal.api.taskqueue.v1.PollerInfo pollers = 1; + + // Statistics for the task queue. + // Only set if `report_stats` is set on the request. + temporal.api.taskqueue.v1.TaskQueueStats stats = 5; + + // Task queue stats breakdown by priority key. Only contains actively used priority keys. + // Only set if `report_stats` is set on the request. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "by" is used to clarify the keys and values. --) + map stats_by_priority_key = 8; + + // Specifies which Worker Deployment Version(s) Server routes this Task Queue's tasks to. + // When not present, it means the tasks are routed to Unversioned workers (workers with + // UNVERSIONED or unspecified WorkerVersioningMode.) + // Task Queue Versioning info is updated indirectly by calling SetWorkerDeploymentCurrentVersion + // and SetWorkerDeploymentRampingVersion on Worker Deployments. + // Note: This information is not relevant to Pinned workflow executions and their activities as + // they are always routed to their Pinned Deployment Version. However, new workflow executions + // are typically not Pinned until they complete their first task (unless they are started with + // a Pinned VersioningOverride or are Child Workflows of a Pinned parent). + temporal.api.taskqueue.v1.TaskQueueVersioningInfo versioning_info = 4; + + // Only populated if report_task_queue_config is set to true. + temporal.api.taskqueue.v1.TaskQueueConfig config = 6; + + message EffectiveRateLimit { + // The effective rate limit for the task queue. + float requests_per_second = 1; + + // Source of the RateLimit Configuration,which can be one of the following values: + // - SOURCE_API: The rate limit that is set via the TaskQueueConfig api. + // - SOURCE_WORKER: The rate limit is the value set using the workerOptions in TaskQueueActivitiesPerSecond. + // - SOURCE_SYSTEM: The rate limit is the default value set by the system + temporal.api.enums.v1.RateLimitSource rate_limit_source = 2; + } + + EffectiveRateLimit effective_rate_limit = 7; + + // Deprecated. + // Status of the task queue. Only populated when `include_task_queue_status` is set to true in the request. + temporal.api.taskqueue.v1.TaskQueueStatus task_queue_status = 2 [deprecated = true]; + + // Deprecated. + // Only returned in ENHANCED mode. + // This map contains Task Queue information for each Build ID. Empty string as key value means unversioned. + map versions_info = 3 [deprecated = true]; +} + +message GetClusterInfoRequest {} + +// GetClusterInfoResponse contains information about Temporal cluster. +message GetClusterInfoResponse { + // Key is client name i.e "temporal-go", "temporal-java", or "temporal-cli". + // Value is ranges of supported versions of this client i.e ">1.1.1 <=1.4.0 || ^5.0.0". + map supported_clients = 1; + + string server_version = 2; + + string cluster_id = 3; + + temporal.api.version.v1.VersionInfo version_info = 4; + + string cluster_name = 5; + + int32 history_shard_count = 6; + + string persistence_store = 7; + + string visibility_store = 8; + + int64 initial_failover_version = 9; + + int64 failover_version_increment = 10; +} + +message GetSystemInfoRequest {} + +message GetSystemInfoResponse { + // Version of the server. + string server_version = 1; + + // All capabilities the system supports. + Capabilities capabilities = 2; + + // System capability details. + message Capabilities { + // True if signal and query headers are supported. + bool signal_and_query_header = 1; + + // True if internal errors are differentiated from other types of errors for purposes of + // retrying non-internal errors. + // + // When unset/false, clients retry all failures. When true, clients should only retry + // non-internal errors. + bool internal_error_differentiation = 2; + + // True if RespondActivityTaskFailed API supports including heartbeat details + bool activity_failure_include_heartbeat = 3; + + // Supports scheduled workflow features. + bool supports_schedules = 4; + + // True if server uses protos that include temporal.api.failure.v1.Failure.encoded_attributes + bool encoded_failure_attributes = 5; + + // True if server supports dispatching Workflow and Activity tasks based on a worker's build_id + // (see: + // https://github.com/temporalio/proposals/blob/a123af3b559f43db16ea6dd31870bfb754c4dc5e/versioning/worker-versions.md) + bool build_id_based_versioning = 6; + + // True if server supports upserting workflow memo + bool upsert_memo = 7; + + // True if server supports eager workflow task dispatching for the StartWorkflowExecution API + bool eager_workflow_start = 8; + + // True if the server knows about the sdk metadata field on WFT completions and will record + // it in history + bool sdk_metadata = 9; + + // True if the server supports count group by execution status + // (-- api-linter: core::0140::prepositions=disabled --) + bool count_group_by_execution_status = 10; + + // True if the server supports Nexus operations. + // This flag is dependent both on server version and for Nexus to be enabled via server configuration. + bool nexus = 11; + + // True if the server supports server-scaled deployments. + // This flag is dependent both on server version and for server-scaled deployments + // to be enabled via server configuration. + bool server_scaled_deployments = 12; + + // True if the server supports the Cloud Run compute provider for + // server-scaled deployments. Dependent on server version and the + // provider being enabled via server configuration. + bool server_scaled_provider_cloud_run = 13; + } +} + +message ListTaskQueuePartitionsRequest { + string namespace = 1; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 2; +} + +message ListTaskQueuePartitionsResponse { + repeated temporal.api.taskqueue.v1.TaskQueuePartitionMetadata activity_task_queue_partitions = 1; + + repeated temporal.api.taskqueue.v1.TaskQueuePartitionMetadata workflow_task_queue_partitions = 2; +} + +// (-- api-linter: core::0203::optional=disabled +// aip.dev/not-precedent: field_behavior annotation not available in our gogo fork --) +message CreateScheduleRequest { + // The namespace the schedule should be created in. + string namespace = 1; + + // The id of the new schedule. + string schedule_id = 2; + + // The schedule spec, policies, action, and initial state. + temporal.api.schedule.v1.Schedule schedule = 3; + + // Optional initial patch (e.g. to run the action once immediately). + temporal.api.schedule.v1.SchedulePatch initial_patch = 4; + + // The identity of the client who initiated this request. + string identity = 5; + + // A unique identifier for this create request for idempotence. Typically UUIDv4. + string request_id = 6; + + // Memo and search attributes to attach to the schedule itself. + temporal.api.common.v1.Memo memo = 7; + + temporal.api.common.v1.SearchAttributes search_attributes = 8; +} + +message CreateScheduleResponse { + bytes conflict_token = 1; +} + +message DescribeScheduleRequest { + // The namespace of the schedule to describe. + string namespace = 1; + + // The id of the schedule to describe. + string schedule_id = 2; +} + +message DescribeScheduleResponse { + // The complete current schedule details. This may not match the schedule as + // created because: + // - some types of schedule specs may get compiled into others (e.g. + // CronString into StructuredCalendarSpec) + // - some unspecified fields may be replaced by defaults + // - some fields in the state are modified automatically + // - the schedule may have been modified by UpdateSchedule or PatchSchedule + temporal.api.schedule.v1.Schedule schedule = 1; + + // Extra schedule state info. + temporal.api.schedule.v1.ScheduleInfo info = 2; + + // The memo and search attributes that the schedule was created with. + temporal.api.common.v1.Memo memo = 3; + + temporal.api.common.v1.SearchAttributes search_attributes = 4; + + // This value can be passed back to UpdateSchedule to ensure that the + // schedule was not modified between a Describe and an Update, which could + // lead to lost updates and other confusion. + bytes conflict_token = 5; +} + +message UpdateScheduleRequest { + // The namespace of the schedule to update. + string namespace = 1; + + // The id of the schedule to update. + string schedule_id = 2; + + // The new schedule. The four main fields of the schedule (spec, action, + // policies, state) are replaced completely by the values in this message. + temporal.api.schedule.v1.Schedule schedule = 3; + + // This can be the value of conflict_token from a DescribeScheduleResponse, + // which will cause this request to fail if the schedule has been modified + // between the Describe and this Update. + // If missing, the schedule will be updated unconditionally. + bytes conflict_token = 4; + + // The identity of the client who initiated this request. + string identity = 5; + + // A unique identifier for this update request for idempotence. Typically UUIDv4. + string request_id = 6; + + // Schedule search attributes to be updated. + // Do not set this field if you do not want to update the search attributes. + // A non-null empty object will set the search attributes to an empty map. + // Note: you cannot only update the search attributes with `UpdateScheduleRequest`, + // you must also set the `schedule` field; otherwise, it will unset the schedule. + temporal.api.common.v1.SearchAttributes search_attributes = 7; + + // Schedule memo to replace. If set, replaces the entire memo. + // Do not set this field if you do not want to update the memo. + // A non-null empty object will clear the memo. + temporal.api.common.v1.Memo memo = 8; +} + +message UpdateScheduleResponse {} + +message PatchScheduleRequest { + // The namespace of the schedule to patch. + string namespace = 1; + + // The id of the schedule to patch. + string schedule_id = 2; + + temporal.api.schedule.v1.SchedulePatch patch = 3; + + // The identity of the client who initiated this request. + string identity = 4; + + // A unique identifier for this update request for idempotence. Typically UUIDv4. + string request_id = 5; +} + +message PatchScheduleResponse {} + +message ListScheduleMatchingTimesRequest { + // The namespace of the schedule to query. + string namespace = 1; + + // The id of the schedule to query. + string schedule_id = 2; + + // Time range to query. + google.protobuf.Timestamp start_time = 3; + + google.protobuf.Timestamp end_time = 4; +} + +message ListScheduleMatchingTimesResponse { + repeated google.protobuf.Timestamp start_time = 1; +} + +message DeleteScheduleRequest { + // The namespace of the schedule to delete. + string namespace = 1; + + // The id of the schedule to delete. + string schedule_id = 2; + + // The identity of the client who initiated this request. + string identity = 3; +} + +message DeleteScheduleResponse {} + +message ListSchedulesRequest { + // The namespace to list schedules in. + string namespace = 1; + + // How many to return at once. + int32 maximum_page_size = 2; + + // Token to get the next page of results. + bytes next_page_token = 3; + + // Query to filter schedules. + string query = 4; +} + +message ListSchedulesResponse { + repeated temporal.api.schedule.v1.ScheduleListEntry schedules = 1; + + bytes next_page_token = 2; +} + +message CountSchedulesRequest { + string namespace = 1; + + // Visibility query, see https://docs.temporal.io/list-filter for the syntax. + string query = 2; +} + +message CountSchedulesResponse { + // If `query` is not grouping by any field, the count is an approximate number + // of schedules that match the query. + // If `query` is grouping by a field, the count is simply the sum of the counts + // of the groups returned in the response. This number can be smaller than the + // total number of schedules matching the query. + int64 count = 1; + + // Contains the groups if the request is grouping by a field. + // The list might not be complete, and the counts of each group is approximate. + repeated AggregationGroup groups = 2; + + message AggregationGroup { + repeated temporal.api.common.v1.Payload group_values = 1; + + int64 count = 2; + } +} + +// [cleanup-wv-pre-release] +message UpdateWorkerBuildIdCompatibilityRequest { + message AddNewCompatibleVersion { + // A new id to be added to an existing compatible set. + string new_build_id = 1; + + // A build id which must already exist in the version sets known by the task queue. The new + // id will be stored in the set containing this id, marking it as compatible with + // the versions within. + string existing_compatible_build_id = 2; + + // When set, establishes the compatible set being targeted as the overall default for the + // queue. If a different set was the current default, the targeted set will replace it as + // the new default. + bool make_set_default = 3; + } + + message MergeSets { + // A build ID in the set whose default will become the merged set default + string primary_set_build_id = 1; + + // A build ID in the set which will be merged into the primary set + string secondary_set_build_id = 2; + } + + string namespace = 1; + + // Must be set, the task queue to apply changes to. Because all workers on a given task queue + // must have the same set of workflow & activity implementations, there is no reason to specify + // a task queue type here. + string task_queue = 2; + + oneof operation { + // A new build id. This operation will create a new set which will be the new overall + // default version for the queue, with this id as its only member. This new set is + // incompatible with all previous sets/versions. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: In makes perfect sense here. --) + string add_new_build_id_in_new_default_set = 3; + + // Adds a new id to an existing compatible set, see sub-message definition for more. + AddNewCompatibleVersion add_new_compatible_build_id = 4; + + // Promote an existing set to be the current default (if it isn't already) by targeting + // an existing build id within it. This field's value is the extant build id. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: Names are hard. --) + string promote_set_by_build_id = 5; + + // Promote an existing build id within some set to be the current default for that set. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: Within makes perfect sense here. --) + string promote_build_id_within_set = 6; + + // Merge two existing sets together, thus declaring all build IDs in both sets compatible + // with one another. The primary set's default will become the default for the merged set. + // This is useful if you've accidentally declared a new ID as incompatible you meant to + // declare as compatible. The unusual case of incomplete replication during failover could + // also result in a split set, which this operation can repair. + MergeSets merge_sets = 7; + } +} + +// [cleanup-wv-pre-release] +message UpdateWorkerBuildIdCompatibilityResponse { + reserved 1; + + reserved "version_set_id"; +} + +// [cleanup-wv-pre-release] +message GetWorkerBuildIdCompatibilityRequest { + string namespace = 1; + + // Must be set, the task queue to interrogate about worker id compatibility. + string task_queue = 2; + + // Limits how many compatible sets will be returned. Specify 1 to only return the current + // default major version set. 0 returns all sets. + int32 max_sets = 3; +} + +// [cleanup-wv-pre-release] +message GetWorkerBuildIdCompatibilityResponse { + // Major version sets, in order from oldest to newest. The last element of the list will always + // be the current default major version. IE: New workflows will target the most recent version + // in that version set. + // + // There may be fewer sets returned than exist, if the request chose to limit this response. + repeated temporal.api.taskqueue.v1.CompatibleVersionSet major_version_sets = 1; +} + +// (-- api-linter: core::0134::request-mask-required=disabled +// aip.dev/not-precedent: UpdateNamespace RPC doesn't follow Google API format. --) +// (-- api-linter: core::0134::request-resource-required=disabled +// aip.dev/not-precedent: GetWorkerBuildIdCompatibilityRequest RPC doesn't follow Google API format. --) +// [cleanup-wv-pre-release] +message UpdateWorkerVersioningRulesRequest { + // Inserts the rule to the list of assignment rules for this Task Queue. + // The rules are evaluated in order, starting from index 0. The first + // applicable rule will be applied and the rest will be ignored. + message InsertBuildIdAssignmentRule { + // Use this option to insert the rule in a particular index. By + // default, the new rule is inserted at the beginning of the list + // (index 0). If the given index is too larger the rule will be + // inserted at the end of the list. + int32 rule_index = 1; + + temporal.api.taskqueue.v1.BuildIdAssignmentRule rule = 2; + } + + // Replaces the assignment rule at a given index. + message ReplaceBuildIdAssignmentRule { + int32 rule_index = 1; + + temporal.api.taskqueue.v1.BuildIdAssignmentRule rule = 2; + + // By default presence of one unconditional rule is enforced, otherwise + // the replace operation will be rejected. Set `force` to true to + // bypass this validation. An unconditional assignment rule: + // - Has no hint filter + // - Has no ramp + bool force = 3; + } + + message DeleteBuildIdAssignmentRule { + int32 rule_index = 1; + + // By default presence of one unconditional rule is enforced, otherwise + // the delete operation will be rejected. Set `force` to true to + // bypass this validation. An unconditional assignment rule: + // - Has no hint filter + // - Has no ramp + bool force = 2; + } + + // Adds the rule to the list of redirect rules for this Task Queue. There + // can be at most one redirect rule for each distinct Source Build ID. + message AddCompatibleBuildIdRedirectRule { + temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule rule = 1; + } + + // Replaces the routing rule with the given source Build ID. + message ReplaceCompatibleBuildIdRedirectRule { + temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule rule = 1; + } + + message DeleteCompatibleBuildIdRedirectRule { + string source_build_id = 1; + } + + // This command is intended to be used to complete the rollout of a Build + // ID and cleanup unnecessary rules possibly created during a gradual + // rollout. Specifically, this command will make the following changes + // atomically: + // 1. Adds an assignment rule (with full ramp) for the target Build ID at + // the end of the list. + // 2. Removes all previously added assignment rules to the given target + // Build ID (if any). + // 3. Removes any fully-ramped assignment rule for other Build IDs. + message CommitBuildId { + string target_build_id = 1; + + // To prevent committing invalid Build IDs, we reject the request if no + // pollers has been seen recently for this Build ID. Use the `force` + // option to disable this validation. + bool force = 2; + } + + string namespace = 1; + + string task_queue = 2; + + // A valid conflict_token can be taken from the previous + // ListWorkerVersioningRulesResponse or UpdateWorkerVersioningRulesResponse. + // An invalid token will cause this request to fail, ensuring that if the rules + // for this Task Queue have been modified between the previous and current + // operation, the request will fail instead of causing an unpredictable mutation. + bytes conflict_token = 3; + + oneof operation { + InsertBuildIdAssignmentRule insert_assignment_rule = 4; + + ReplaceBuildIdAssignmentRule replace_assignment_rule = 5; + + DeleteBuildIdAssignmentRule delete_assignment_rule = 6; + + AddCompatibleBuildIdRedirectRule add_compatible_redirect_rule = 7; + + ReplaceCompatibleBuildIdRedirectRule replace_compatible_redirect_rule = 8; + + DeleteCompatibleBuildIdRedirectRule delete_compatible_redirect_rule = 9; + + CommitBuildId commit_build_id = 10; + } +} + +// [cleanup-wv-pre-release] +message UpdateWorkerVersioningRulesResponse { + repeated temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule assignment_rules = 1; + + repeated temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule compatible_redirect_rules = 2; + + // This value can be passed back to UpdateWorkerVersioningRulesRequest to + // ensure that the rules were not modified between the two updates, which + // could lead to lost updates and other confusion. + bytes conflict_token = 3; +} + +// [cleanup-wv-pre-release] +message GetWorkerVersioningRulesRequest { + string namespace = 1; + + string task_queue = 2; +} + +// [cleanup-wv-pre-release] +message GetWorkerVersioningRulesResponse { + repeated temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule assignment_rules = 1; + + repeated temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule compatible_redirect_rules = 2; + + // This value can be passed back to UpdateWorkerVersioningRulesRequest to + // ensure that the rules were not modified between this List and the Update, + // which could lead to lost updates and other confusion. + bytes conflict_token = 3; +} + +// [cleanup-wv-pre-release] +// Deprecated. Use `DescribeTaskQueue`. +message GetWorkerTaskReachabilityRequest { + string namespace = 1; + + // Build ids to retrieve reachability for. An empty string will be interpreted as an unversioned worker. + // The number of build ids that can be queried in a single API call is limited. + // Open source users can adjust this limit by setting the server's dynamic config value for + // `limit.reachabilityQueryBuildIds` with the caveat that this call can strain the visibility store. + repeated string build_ids = 2; + + // Task queues to retrieve reachability for. Leave this empty to query for all task queues associated with given + // build ids in the namespace. + // Must specify at least one task queue if querying for an unversioned worker. + // The number of task queues that the server will fetch reachability information for is limited. + // See the `GetWorkerTaskReachabilityResponse` documentation for more information. + repeated string task_queues = 3; + + // Type of reachability to query for. + // `TASK_REACHABILITY_NEW_WORKFLOWS` is always returned in the response. + // Use `TASK_REACHABILITY_EXISTING_WORKFLOWS` if your application needs to respond to queries on closed workflows. + // Otherwise, use `TASK_REACHABILITY_OPEN_WORKFLOWS`. Default is `TASK_REACHABILITY_EXISTING_WORKFLOWS` if left + // unspecified. + // See the TaskReachability docstring for information about each enum variant. + temporal.api.enums.v1.TaskReachability reachability = 4; +} + +// [cleanup-wv-pre-release] +// Deprecated. Use `DescribeTaskQueue`. +message GetWorkerTaskReachabilityResponse { + // Task reachability, broken down by build id and then task queue. + // When requesting a large number of task queues or all task queues associated with the given build ids in a + // namespace, all task queues will be listed in the response but some of them may not contain reachability + // information due to a server enforced limit. When reaching the limit, task queues that reachability information + // could not be retrieved for will be marked with a single TASK_REACHABILITY_UNSPECIFIED entry. The caller may issue + // another call to get the reachability for those task queues. + // + // Open source users can adjust this limit by setting the server's dynamic config value for + // `limit.reachabilityTaskQueueScan` with the caveat that this call can strain the visibility store. + repeated temporal.api.taskqueue.v1.BuildIdReachability build_id_reachability = 1; +} + +// (-- api-linter: core::0134=disabled +// aip.dev/not-precedent: Update RPCs don't follow Google API format. --) +message UpdateWorkflowExecutionRequest { + // The namespace name of the target Workflow. + string namespace = 1; + + // The target Workflow Id and (optionally) a specific Run Id thereof. + // (-- api-linter: core::0203::optional=disabled + // aip.dev/not-precedent: false positive triggered by the word "optional" --) + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + // If set, this call will error if the most recent (if no Run Id is set on + // `workflow_execution`), or specified (if it is) Workflow Execution is not + // part of the same execution chain as this Id. + string first_execution_run_id = 3; + + // Specifies client's intent to wait for Update results. + // NOTE: This field works together with API call timeout which is limited by + // server timeout (maximum wait time). If server timeout is expired before + // user specified timeout, API call returns even if specified stage is not reached. + // Actual reached stage will be included in the response. + temporal.api.update.v1.WaitPolicy wait_policy = 4; + + // The request information that will be delivered all the way down to the + // Workflow Execution. + temporal.api.update.v1.Request request = 5; +} + +message UpdateWorkflowExecutionResponse { + // Enough information for subsequent poll calls if needed. Never null. + temporal.api.update.v1.UpdateRef update_ref = 1; + + // The outcome of the Update if and only if the Workflow Update + // has completed. If this response is being returned before the Update has + // completed then this field will not be set. + temporal.api.update.v1.Outcome outcome = 2; + + // The most advanced lifecycle stage that the Update is known to have + // reached, where lifecycle stages are ordered + // UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_UNSPECIFIED < + // UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED < + // UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED < + // UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED. + // UNSPECIFIED will be returned if and only if the server's maximum wait + // time was reached before the Update reached the stage specified in the + // request WaitPolicy, and before the context deadline expired; clients may + // may then retry the call as needed. + temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage stage = 3; + + // Link to the update event. May be null if the update has not yet been accepted. + temporal.api.common.v1.Link link = 4; +} + +message StartBatchOperationRequest { + // Namespace that contains the batch operation + string namespace = 1; + + // Visibility query defines the the group of workflow to apply the batch operation + // This field and `executions` are mutually exclusive + string visibility_query = 2; + + // Job ID defines the unique ID for the batch job + string job_id = 3; + + // Reason to perform the batch operation + string reason = 4; + + // Executions to apply the batch operation + // This field and `visibility_query` are mutually exclusive + // DEPRECATED: Use `target_executions` instead. + repeated temporal.api.common.v1.WorkflowExecution executions = 5 [deprecated = true]; + + // Target executions to apply the batch operation. This field and `visibility_query` + // are mutually exclusive. + repeated temporal.api.common.v1.Execution target_executions = 22; + + // Limit for the number of operations processed per second within this batch. + // Its purpose is to reduce the stress on the system caused by batch operations, which helps to prevent system + // overload and minimize potential delays in executing ongoing tasks for user workers. + // Note that when no explicit limit is provided, the server will operate according to its limit defined by the + // dynamic configuration key `worker.batcherRPS`. This also applies if the value in this field exceeds the + // server's configured limit. + float max_operations_per_second = 6; + + // Operation input + oneof operation { + temporal.api.batch.v1.BatchOperationTermination termination_operation = 10; + + temporal.api.batch.v1.BatchOperationSignal signal_operation = 11; + + temporal.api.batch.v1.BatchOperationCancellation cancellation_operation = 12; + + temporal.api.batch.v1.BatchOperationDeletion deletion_operation = 13; + + temporal.api.batch.v1.BatchOperationReset reset_operation = 14; + + temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptions update_workflow_options_operation = 15; + + temporal.api.batch.v1.BatchOperationUnpauseActivities unpause_activities_operation = 16; + + temporal.api.batch.v1.BatchOperationResetActivities reset_activities_operation = 17; + + temporal.api.batch.v1.BatchOperationUpdateActivityOptions update_activity_options_operation = 18; + + temporal.api.batch.v1.BatchOperationCancelActivities cancel_activities_operation = 19; + + temporal.api.batch.v1.BatchOperationTerminateActivities terminate_activities_operation = 20; + + temporal.api.batch.v1.BatchOperationDeleteActivities delete_activities_operation = 21; + } +} + +message StartBatchOperationResponse {} + +message StopBatchOperationRequest { + // Namespace that contains the batch operation + string namespace = 1; + + // Batch job id + string job_id = 2; + + // Reason to stop a batch operation + string reason = 3; + + // Identity of the operator + string identity = 4; +} + +message StopBatchOperationResponse {} + +message DescribeBatchOperationRequest { + // Namespace that contains the batch operation + string namespace = 1; + + // Batch job id + string job_id = 2; +} + +message DescribeBatchOperationResponse { + // Batch operation type + temporal.api.enums.v1.BatchOperationType operation_type = 1; + + // Batch job ID + string job_id = 2; + + // Batch operation state + temporal.api.enums.v1.BatchOperationState state = 3; + + // Batch operation start time + google.protobuf.Timestamp start_time = 4; + + // Batch operation close time + google.protobuf.Timestamp close_time = 5; + + // Total operation count + int64 total_operation_count = 6; + + // Complete operation count + int64 complete_operation_count = 7; + + // Failure operation count + int64 failure_operation_count = 8; + + // Identity indicates the operator identity + string identity = 9; + + // Reason indicates the reason to stop a operation + string reason = 10; + + // Query is the visibility query that defines the group of workflow to apply the batch operation + string query = 11; + + // Executions is the list of workflow OR standalone activity executions to apply the batch operation + repeated temporal.api.common.v1.Execution executions = 12; +} + +message ListBatchOperationsRequest { + // Namespace that contains the batch operation + string namespace = 1; + + // List page size + int32 page_size = 2; + + // Next page token + bytes next_page_token = 3; +} + +message ListBatchOperationsResponse { + // BatchOperationInfo contains the basic info about batch operation + repeated temporal.api.batch.v1.BatchOperationInfo operation_info = 1; + + bytes next_page_token = 2; +} + +message PollWorkflowExecutionUpdateRequest { + // The namespace of the Workflow Execution to which the Update was + // originally issued. + string namespace = 1; + + // The Update reference returned in the initial UpdateWorkflowExecutionResponse. + temporal.api.update.v1.UpdateRef update_ref = 2; + + // The identity of the worker/client who is polling this Update outcome. + string identity = 3; + + // Specifies client's intent to wait for Update results. + // Omit to request a non-blocking poll. + temporal.api.update.v1.WaitPolicy wait_policy = 4; +} + +message PollWorkflowExecutionUpdateResponse { + // The outcome of the update if and only if the update has completed. If + // this response is being returned before the update has completed (e.g. due + // to the specification of a wait policy that only waits on + // UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED) then this field will + // not be set. + temporal.api.update.v1.Outcome outcome = 1; + + // The most advanced lifecycle stage that the Update is known to have + // reached, where lifecycle stages are ordered + // UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_UNSPECIFIED < + // UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED < + // UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED < + // UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED. + // UNSPECIFIED will be returned if and only if the server's maximum wait + // time was reached before the Update reached the stage specified in the + // request WaitPolicy, and before the context deadline expired; clients may + // may then retry the call as needed. + temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage stage = 2; + + // Sufficient information to address this Update. + temporal.api.update.v1.UpdateRef update_ref = 3; +} + +message PollNexusTaskQueueRequest { + string namespace = 1; + + temporal.api.taskqueue.v1.TaskQueue task_queue = 3; + + // Unless this is the first poll, the client must pass one of the poller group IDs received in + // `poller_group_infos` of the last the PollNexusTaskQueueResponse according to the + // instructions. If not set, the poll is routed randomly which can cause it to be blocked + // without receiving a task while the queue actually has tasks in another server location. + string poller_group_id = 9; + + // The identity of the client who initiated this request. + string identity = 2; + + // A unique key for this worker instance, used for tracking worker lifecycle. + // This is guaranteed to be unique, whereas identity is not guaranteed to be unique. + string worker_instance_key = 8; + + // Information about this worker's build identifier and if it is choosing to use the versioning + // feature. See the `WorkerVersionCapabilities` docstring for more. + // Deprecated. Replaced by deployment_options. + temporal.api.common.v1.WorkerVersionCapabilities worker_version_capabilities = 4 [deprecated = true]; + + // Worker deployment options that user has set in the worker. + temporal.api.deployment.v1.WorkerDeploymentOptions deployment_options = 6; + + // Worker info to be sent to the server. + repeated temporal.api.worker.v1.WorkerHeartbeat worker_heartbeat = 7; +} + +message PollNexusTaskQueueResponse { + // An opaque unique identifier for this task for correlating a completion request the embedded request. + bytes task_token = 1; + + // Embedded request as translated from the incoming frontend request. + temporal.api.nexus.v1.Request request = 2; + + // Server-advised information the SDK may use to adjust its poller count. + temporal.api.taskqueue.v1.PollerScalingDecision poller_scaling_decision = 3; + + // This poller group ID identifies the owner of the nexus task awaiting for synchronous + // response. + // Corresponding `RespondNexusTaskCompleted` and `RespondNexusTaskFailed` calls should pass this + // value for proper response routing. + string poller_group_id = 4; + + // The weighted list of poller groups IDs that client should use for future polls to this task + // queue. Client is expected to: + // 1. Maintain minimum number of pollers no less than the number of groups. + // 2. Try to assign the next poll to a group without any pending polls, + // 3. If every group has some pending polls, assign the next poll to a group randomly + // according to the weights. + repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 5 [deprecated = true]; + + // The weighted, versioned list of poller groups IDs that client should use for future polls to + // this task queue. Client should ignore this if it has already applied a snapshot with a + // version greater than or equal to `poller_groups_info.version`. Client is expected to: + // 1. Maintain minimum number of pollers no less than the number of groups. + // 2. Try to assign the next poll to a group without any pending polls, + // 3. If every group has some pending polls, assign the next poll to a group randomly + // according to the weights. + temporal.api.taskqueue.v1.PollerGroupsInfo poller_groups_info = 6; +} + +message RespondNexusTaskCompletedRequest { + string namespace = 1; + + // The identity of the client who initiated this request. + string identity = 2; + + // A unique identifier for this task as received via a poll response. + bytes task_token = 3; + + // Embedded response to be translated into a frontend response. + temporal.api.nexus.v1.Response response = 4; + + // Client must forward the poller_group_id received in PollNexusTaskQueueResponse for proper + // routing of the response. + string poller_group_id = 5; +} + +message RespondNexusTaskCompletedResponse {} + +message RespondNexusTaskFailedRequest { + string namespace = 1; + + // The identity of the client who initiated this request. + string identity = 2; + + // A unique identifier for this task. + bytes task_token = 3; + + // Deprecated. Use the failure field instead. + temporal.api.nexus.v1.HandlerError error = 4 [deprecated = true]; + + // The error the handler failed with. Must contain a NexusHandlerFailureInfo object. + temporal.api.failure.v1.Failure failure = 5; + + // Client must forward the poller_group_id received in PollNexusTaskQueueResponse for proper + // routing of the response. + string poller_group_id = 6; +} + +message RespondNexusTaskFailedResponse {} + +message ExecuteMultiOperationRequest { + string namespace = 1; + + // List of operations to execute within a single workflow. + // + // Preconditions: + // - The list of operations must not be empty. + // - The workflow ids must match across operations. + // - The only valid list of operations at this time is [StartWorkflow, UpdateWorkflow], in this order. + // + // Note that additional operation-specific restrictions have to be considered. + repeated Operation operations = 2; + + // Resource ID for routing. Should match operations[0].start_workflow.workflow_id + string resource_id = 3; + + message Operation { + oneof operation { + // Additional restrictions: + // - setting `cron_schedule` is invalid + // - setting `request_eager_execution` is invalid + // - setting `workflow_start_delay` is invalid + StartWorkflowExecutionRequest start_workflow = 1; + + // Additional restrictions: + // - setting `first_execution_run_id` is invalid + // - setting `workflow_execution.run_id` is invalid + UpdateWorkflowExecutionRequest update_workflow = 2; + } + } +} + +// IMPORTANT: For [StartWorkflow, UpdateWorkflow] combination ("Update-with-Start") when both +// 1. the workflow update for the requested update ID has already completed, and +// 2. the workflow for the requested workflow ID has already been closed, +// then you'll receive +// - an update response containing the update's outcome, and +// - a start response with a `status` field that reflects the workflow's current state. +message ExecuteMultiOperationResponse { + repeated Response responses = 1; + + message Response { + oneof response { + StartWorkflowExecutionResponse start_workflow = 1; + + UpdateWorkflowExecutionResponse update_workflow = 2; + } + } +} + +// NOTE: keep in sync with temporal.api.batch.v1.BatchOperationUpdateActivityOptions +// Deprecated. Use `UpdateActivityExecutionOptionsRequest`. +message UpdateActivityOptionsRequest { + // Namespace of the workflow which scheduled this activity + string namespace = 1; + + // Execution info of the workflow which scheduled this activity + temporal.api.common.v1.WorkflowExecution execution = 2; + + // The identity of the client who initiated this request + string identity = 3; + + // Activity options. Partial updates are accepted and controlled by update_mask + temporal.api.activity.v1.ActivityOptions activity_options = 4; + + // Controls which fields from `activity_options` will be applied + google.protobuf.FieldMask update_mask = 5; + + // either activity id, activity type or update_all must be provided + oneof activity { + // Only activity with this ID will be updated. + string id = 6; + + // Update all running activities of this type. + string type = 7; + + // Update all running activities. + bool match_all = 9; + } + + // If set, the activity options will be restored to the default. + // Default options are then options activity was created with. + // They are part of the first schedule event. + // This flag cannot be combined with any other option; if you supply + // restore_original together with other options, the request will be rejected. + bool restore_original = 8; +} + +message UpdateActivityExecutionOptionsRequest { + // Namespace of the workflow which scheduled this activity + string namespace = 1; + + // If provided, targets a workflow activity for the given workflow ID. + // If empty, targets a standalone activity. + string workflow_id = 2; + + // The ID of the activity to target. + string activity_id = 3; + + // Run ID of the workflow or standalone activity. If empty, targets the latest run. + string run_id = 4; + + // The identity of the client who initiated this request + string identity = 5; + + // Activity options. Partial updates are accepted and controlled by update_mask + temporal.api.activity.v1.ActivityOptions activity_options = 6; + + // Controls which fields from `activity_options` will be applied + google.protobuf.FieldMask update_mask = 7; + + // If set, the activity options will be restored to the default. + // Default options are then options activity was created with. + // They are part of the first schedule event. + // This flag cannot be combined with any other option; if you supply + // restore_original together with other options, the request will be rejected. + bool restore_original = 8; + + // Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities. + string resource_id = 9; + + // Used to de-dupe update requests. + string request_id = 10; +} + +// Deprecated. Use `UpdateActivityExecutionOptionsResponse`. +message UpdateActivityOptionsResponse { + // Activity options after an update + temporal.api.activity.v1.ActivityOptions activity_options = 1; +} + +message UpdateActivityExecutionOptionsResponse { + // Activity options after an update + temporal.api.activity.v1.ActivityOptions activity_options = 1; +} + +// Deprecated. Use `PauseActivityExecutionRequest`. +message PauseActivityRequest { + // Namespace of the workflow which scheduled this activity. + string namespace = 1; + + // Execution info of the workflow which scheduled this activity + temporal.api.common.v1.WorkflowExecution execution = 2; + + // The identity of the client who initiated this request. + string identity = 3; + + // either activity id or activity type must be provided + oneof activity { + // Only the activity with this ID will be paused. + string id = 4; + + // Pause all running activities of this type. + // Note: Experimental - the behavior of pause by activity type might change in a future release. + string type = 5; + } + + // Reason to pause the activity. + string reason = 6; + + // Used to de-dupe pause requests. + string request_id = 7; +} + +message PauseActivityExecutionRequest { + // Namespace of the workflow which scheduled this activity. + string namespace = 1; + + // If provided, pause a workflow activity (or activities) for the given workflow ID. + // If empty, targets a standalone activity. + string workflow_id = 2; + + // The ID of the activity to target. + string activity_id = 3; + + // Run ID of the workflow or standalone activity. If empty, targets the latest run. + string run_id = 4; + + // The identity of the client who initiated this request. + string identity = 5; + + // Reason to pause the activity. + string reason = 6; + + // Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities. + string resource_id = 7; + + // Used to de-dupe pause requests. + string request_id = 8; +} + +// Deprecated. Use `PauseActivityExecutionResponse`. +message PauseActivityResponse {} + +message PauseActivityExecutionResponse {} + +// Deprecated. Use `UnpauseActivityExecutionRequest`. +message UnpauseActivityRequest { + // Namespace of the workflow which scheduled this activity. + string namespace = 1; + + // Execution info of the workflow which scheduled this activity + temporal.api.common.v1.WorkflowExecution execution = 2; + + // The identity of the client who initiated this request. + string identity = 3; + + // either activity id or activity type must be provided + oneof activity { + // Only the activity with this ID will be unpaused. + string id = 4; + + // Unpause all running activities with of this type. + string type = 5; + + // Unpause all running activities. + bool unpause_all = 6; + } + + // Providing this flag will also reset the number of attempts. + bool reset_attempts = 7; + + // Providing this flag will also reset the heartbeat details. + bool reset_heartbeat = 8; + + // If set, the activity will start at a random time within the specified jitter duration. + google.protobuf.Duration jitter = 9; +} + +message UnpauseActivityExecutionRequest { + // Namespace of the workflow which scheduled this activity. + string namespace = 1; + + // If provided, targets a workflow activity for the given workflow ID. + // If empty, targets a standalone activity. + string workflow_id = 2; + + // The ID of the activity to target. + string activity_id = 3; + + // Run ID of the workflow or standalone activity. If empty, targets the latest run. + string run_id = 4; + + // The identity of the client who initiated this request. + string identity = 5; + + reserved 6, 7; + + reserved "reset_attempts", "reset_heartbeat"; + + // Reason to unpause the activity. + string reason = 8; + + // If set, the activity will start at a random time within the specified jitter duration. + google.protobuf.Duration jitter = 9; + + // Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities. + string resource_id = 10; + + // Used to de-dupe unpause requests. + string request_id = 11; +} + +// Deprecated. Use `UnpauseActivityExecutionResponse`. +message UnpauseActivityResponse {} + +message UnpauseActivityExecutionResponse {} + +// NOTE: keep in sync with temporal.api.batch.v1.BatchOperationResetActivities +// Deprecated. Use `ResetActivityExecutionRequest`. +message ResetActivityRequest { + // Namespace of the workflow which scheduled this activity. + string namespace = 1; + + // Execution info of the workflow which scheduled this activity + temporal.api.common.v1.WorkflowExecution execution = 2; + + // The identity of the client who initiated this request. + string identity = 3; + + // either activity id, activity type or update_all must be provided + oneof activity { + // Only activity with this ID will be reset. + string id = 4; + + // Reset all running activities with of this type. + string type = 5; + + // Reset all running activities. + bool match_all = 10; + } + + // Indicates that activity should reset heartbeat details. + // This flag will be applied only to the new instance of the activity. + bool reset_heartbeat = 6; + + // If activity is paused, it will remain paused after reset + bool keep_paused = 7; + + // If set, and activity is in backoff, the activity will start at a random time within the specified jitter duration. + // (unless it is paused and keep_paused is set) + google.protobuf.Duration jitter = 8; + + // If set, the activity options will be restored to the defaults. + // Default options are then options activity was created with. + // They are part of the first schedule event. + bool restore_original_options = 9; +} + +message ResetActivityExecutionRequest { + // Namespace of the workflow which scheduled this activity. + string namespace = 1; + + // If provided, targets a workflow activity for the given workflow ID. + // If empty, targets a standalone activity. + string workflow_id = 2; + + // The ID of the activity to target. + string activity_id = 3; + + // Run ID of the workflow or standalone activity. If empty, targets the latest run. + string run_id = 4; + + // The identity of the client who initiated this request. + string identity = 5; + + // If activity is paused, it will remain paused after reset + bool keep_paused = 6; + + // If set, and activity is in backoff, the activity will start at a random time within the specified jitter duration. + // (unless it is paused and keep_paused is set) + google.protobuf.Duration jitter = 7; + + // If set, the activity options will be restored to the defaults. + // Default options are then options activity was created with. + // They are part of the first schedule event. + bool restore_original_options = 8; + + // Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities. + string resource_id = 9; + + // Used to de-dupe reset requests. + string request_id = 10; + + // Reset persisted heartbeat details. + // Reset always resets the attempt counter. Passing this flag causes reset to additionally + // discard any persisted heartbeat details. + bool reset_heartbeat = 11; +} + +// Deprecated. Use `ResetActivityExecutionRequest`. +message ResetActivityResponse {} + +message ResetActivityExecutionResponse {} + +// Keep the parameters in sync with: +// - temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptions. +// - temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptions. +message UpdateWorkflowExecutionOptionsRequest { + // The namespace name of the target Workflow. + string namespace = 1; + + // The target Workflow Id and (optionally) a specific Run Id thereof. + // (-- api-linter: core::0203::optional=disabled + // aip.dev/not-precedent: false positive triggered by the word "optional" --) + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + // Workflow Execution options. Partial updates are accepted and controlled by update_mask. + temporal.api.workflow.v1.WorkflowExecutionOptions workflow_execution_options = 3; + + // Controls which fields from `workflow_execution_options` will be applied. + // To unset a field, set it to null and use the update mask to indicate that it should be mutated. + google.protobuf.FieldMask update_mask = 4; + + // Optional. The identity of the client who initiated this request. + string identity = 5; +} + +message UpdateWorkflowExecutionOptionsResponse { + // Workflow Execution options after update. + temporal.api.workflow.v1.WorkflowExecutionOptions workflow_execution_options = 1; + + // The Workflow Execution time when the options were updated. When time skipping is + // enabled, this is the workflow's virtual time rather than wall-clock time. + // + // This timestamp cannot be used for time-skipping fast-forward verification, + // use `fast_forward_id` in `PollWorkflowExecutionTimeSkippingRequest` instead. + google.protobuf.Timestamp update_time = 2; +} + +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message DescribeDeploymentRequest { + string namespace = 1; + + temporal.api.deployment.v1.Deployment deployment = 2; +} + +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message DescribeDeploymentResponse { + temporal.api.deployment.v1.DeploymentInfo deployment_info = 1; +} + +message DescribeWorkerDeploymentVersionRequest { + string namespace = 1; + + // Deprecated. Use `deployment_version`. + string version = 2 [deprecated = true]; + + // Required. + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 3; + + // Report stats for task queues which have been polled by this version. + bool report_task_queue_stats = 4; +} + +message DescribeWorkerDeploymentVersionResponse { + temporal.api.deployment.v1.WorkerDeploymentVersionInfo worker_deployment_version_info = 1; + + // All the Task Queues that have ever polled from this Deployment version. + repeated VersionTaskQueue version_task_queues = 2; + + // (-- api-linter: core::0123::resource-annotation=disabled --) + message VersionTaskQueue { + string name = 1; + + temporal.api.enums.v1.TaskQueueType type = 2; + + // Only set if `report_task_queue_stats` is set on the request. + temporal.api.taskqueue.v1.TaskQueueStats stats = 3; + + // Task queue stats breakdown by priority key. Only contains actively used priority keys. + // Only set if `report_task_queue_stats` is set to true in the request. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "by" is used to clarify the key. --) + map stats_by_priority_key = 4; + } +} + +message DescribeWorkerDeploymentRequest { + string namespace = 1; + + string deployment_name = 2; +} + +message DescribeWorkerDeploymentResponse { + // This value is returned so that it can be optionally passed to APIs + // that write to the Worker Deployment state to ensure that the state + // did not change between this read and a future write. + bytes conflict_token = 1; + + temporal.api.deployment.v1.WorkerDeploymentInfo worker_deployment_info = 2; +} + +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message ListDeploymentsRequest { + string namespace = 1; + + int32 page_size = 2; + + bytes next_page_token = 3; + + // Optional. Use to filter based on exact series name match. + string series_name = 4; +} + +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message ListDeploymentsResponse { + bytes next_page_token = 1; + + repeated temporal.api.deployment.v1.DeploymentListInfo deployments = 2; +} + +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message SetCurrentDeploymentRequest { + string namespace = 1; + + temporal.api.deployment.v1.Deployment deployment = 2; + + // Optional. The identity of the client who initiated this request. + string identity = 3; + + // Optional. Use to add or remove user-defined metadata entries. Metadata entries are exposed + // when describing a deployment. It is a good place for information such as operator name, + // links to internal deployment pipelines, etc. + temporal.api.deployment.v1.UpdateDeploymentMetadata update_metadata = 4; +} + +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message SetCurrentDeploymentResponse { + temporal.api.deployment.v1.DeploymentInfo current_deployment_info = 1; + + // Info of the deployment that was current before executing this operation. + temporal.api.deployment.v1.DeploymentInfo previous_deployment_info = 2; +} + +// Set/unset the Current Version of a Worker Deployment. +message SetWorkerDeploymentCurrentVersionRequest { + string namespace = 1; + + string deployment_name = 2; + + // Deprecated. Use `build_id`. + string version = 3 [deprecated = true]; + + // The build id of the Version that you want to set as Current. + // Pass an empty value to set the Current Version to nil. + // A nil Current Version represents all the unversioned workers (those with `UNVERSIONED` (or unspecified) `WorkerVersioningMode`.) + string build_id = 7; + + // Optional. This can be the value of conflict_token from a Describe, or another Worker + // Deployment API. Passing a non-nil conflict token will cause this request to fail if the + // Deployment's configuration has been modified between the API call that generated the + // token and this one. + bytes conflict_token = 4; + + // Optional. The identity of the client who initiated this request. + string identity = 5; + + // Optional. By default this request would be rejected if not all the expected Task Queues are + // being polled by the new Version, to protect against accidental removal of Task Queues, or + // worker health issues. Pass `true` here to bypass this protection. + // The set of expected Task Queues is the set of all the Task Queues that were ever poller by + // the existing Current Version of the Deployment, with the following exclusions: + // - Task Queues that are not used anymore (inferred by having empty backlog and a task + // add_rate of 0.) + // - Task Queues that are moved to another Worker Deployment (inferred by the Task Queue + // having a different Current Version than the Current Version of this deployment.) + // WARNING: Do not set this flag unless you are sure that the missing task queue pollers are not + // needed. If the request is unexpectedly rejected due to missing pollers, then that means the + // pollers have not reached to the server yet. Only set this if you expect those pollers to + // never arrive. + bool ignore_missing_task_queues = 6; + + // Optional. By default this request will be rejected if no pollers have been seen for the proposed + // Current Version, in order to protect users from routing tasks to pollers that do not exist, leading + // to possible timeouts. Pass `true` here to bypass this protection. + bool allow_no_pollers = 9; +} + +message SetWorkerDeploymentCurrentVersionResponse { + // This value is returned so that it can be optionally passed to APIs + // that write to the Worker Deployment state to ensure that the state + // did not change between this API call and a future write. + bytes conflict_token = 1; + + // Deprecated. Use `previous_deployment_version`. + string previous_version = 2 [deprecated = true]; + + // The version that was current before executing this operation. + // Deprecated in favor of idempotency of the API. Use `DescribeWorkerDeployment` to get the + // Current version info before calling this API. By passing the `conflict_token` got from the + // `DescribeWorkerDeployment` call to this API you can ensure there is no interfering changes + // between the two calls. + temporal.api.deployment.v1.WorkerDeploymentVersion previous_deployment_version = 3 [deprecated = true]; +} + +// Set/unset the Ramping Version of a Worker Deployment and its ramp percentage. +message SetWorkerDeploymentRampingVersionRequest { + string namespace = 1; + + string deployment_name = 2; + + // Deprecated. Use `build_id`. + string version = 3 [deprecated = true]; + + // The build id of the Version that you want to ramp traffic to. + // Pass an empty value to set the Ramping Version to nil. + // A nil Ramping Version represents all the unversioned workers (those with `UNVERSIONED` (or unspecified) `WorkerVersioningMode`.) + string build_id = 8; + + // Ramp percentage to set. Valid range: [0,100]. + float percentage = 4; + + // Optional. This can be the value of conflict_token from a Describe, or another Worker + // Deployment API. Passing a non-nil conflict token will cause this request to fail if the + // Deployment's configuration has been modified between the API call that generated the + // token and this one. + bytes conflict_token = 5; + + // Optional. The identity of the client who initiated this request. + string identity = 6; + + // Optional. By default this request would be rejected if not all the expected Task Queues are + // being polled by the new Version, to protect against accidental removal of Task Queues, or + // worker health issues. Pass `true` here to bypass this protection. + // The set of expected Task Queues equals to all the Task Queues ever polled from the existing + // Current Version of the Deployment, with the following exclusions: + // - Task Queues that are not used anymore (inferred by having empty backlog and a task + // add_rate of 0.) + // - Task Queues that are moved to another Worker Deployment (inferred by the Task Queue + // having a different Current Version than the Current Version of this deployment.) + // WARNING: Do not set this flag unless you are sure that the missing task queue poller are not + // needed. If the request is unexpectedly rejected due to missing pollers, then that means the + // pollers have not reached to the server yet. Only set this if you expect those pollers to + // never arrive. + // Note: this check only happens when the ramping version is about to change, not every time + // that the percentage changes. Also note that the check is against the deployment's Current + // Version, not the previous Ramping Version. + bool ignore_missing_task_queues = 7; + + // Optional. By default this request will be rejected if no pollers have been seen for the proposed + // Current Version, in order to protect users from routing tasks to pollers that do not exist, leading + // to possible timeouts. Pass `true` here to bypass this protection. + bool allow_no_pollers = 10; +} + +message SetWorkerDeploymentRampingVersionResponse { + // This value is returned so that it can be optionally passed to APIs + // that write to the Worker Deployment state to ensure that the state + // did not change between this API call and a future write. + bytes conflict_token = 1; + + // Deprecated. Use `previous_deployment_version`. + string previous_version = 2 [deprecated = true]; + + // The version that was ramping before executing this operation. + // Deprecated in favor of idempotency of the API. Use `DescribeWorkerDeployment` to get the + // Ramping version info before calling this API. By passing the `conflict_token` got from the + // `DescribeWorkerDeployment` call to this API you can ensure there is no interfering changes + // between the two calls. + temporal.api.deployment.v1.WorkerDeploymentVersion previous_deployment_version = 4 [deprecated = true]; + + // The ramping version percentage before executing this operation. + // Deprecated in favor of idempotency of the API. Use `DescribeWorkerDeployment` to get the + // Ramping version info before calling this API. By passing the `conflict_token` got from the + // `DescribeWorkerDeployment` call to this API you can ensure there is no interfering changes + // between the two calls. + float previous_percentage = 3 [deprecated = true]; +} + +// Creates a new WorkerDeployment. +message CreateWorkerDeploymentRequest { + string namespace = 1; + + // The name of the Worker Deployment to create. If a Worker Deployment with + // this name already exists, an error will be returned. + string deployment_name = 2; + + // Optional. The identity of the client who initiated this request. + string identity = 4; + + // A unique identifier for this create request for idempotence. Typically UUIDv4. + string request_id = 5; +} + +message CreateWorkerDeploymentResponse { + // This value is returned so that it can be optionally passed to APIs that + // write to the WorkerDeployment state to ensure that the state did not + // change between this API call and a future write. + bytes conflict_token = 1; +} + +message ListWorkerDeploymentsRequest { + string namespace = 1; + + int32 page_size = 2; + + bytes next_page_token = 3; +} + +message ListWorkerDeploymentsResponse { + bytes next_page_token = 1; + + // The list of worker deployments. + repeated WorkerDeploymentSummary worker_deployments = 2; + + // (-- api-linter: core::0123::resource-annotation=disabled --) + // A subset of WorkerDeploymentInfo + message WorkerDeploymentSummary { + string name = 1; + + google.protobuf.Timestamp create_time = 2; + + temporal.api.deployment.v1.RoutingConfig routing_config = 3; + + // Summary of the version that was added most recently in the Worker Deployment. + temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary latest_version_summary = 4; + + // Summary of the current version of the Worker Deployment. + temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary current_version_summary = 5; + + // Summary of the ramping version of the Worker Deployment. + temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary ramping_version_summary = 6; + } +} + +// Creates a new WorkerDeploymentVersion. +message CreateWorkerDeploymentVersionRequest { + string namespace = 1; + + // Required. + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 2; + + // Optional. Contains the new worker compute configuration for the Worker + // Deployment. Used for worker scale management. + temporal.api.compute.v1.ComputeConfig compute_config = 4; + + // Optional. The identity of the client who initiated this request. + string identity = 3; + + // A unique identifier for this create request for idempotence. Typically UUIDv4. + // If a second request with the same ID is recieved, it is considered a successful no-op. + // Retrying with a different request ID for the same deployment name + build ID is an error. + string request_id = 5; +} + +message CreateWorkerDeploymentVersionResponse {} + +// Used for manual deletion of Versions. User can delete a Version only when all the +// following conditions are met: +// - It is not the Current or Ramping Version of its Deployment. +// - It has no active pollers (none of the task queues in the Version have pollers) +// - It is not draining (see WorkerDeploymentVersionInfo.drainage_info). This condition +// can be skipped by passing `skip-drainage=true`. +message DeleteWorkerDeploymentVersionRequest { + string namespace = 1; + + // Deprecated. Use `deployment_version`. + string version = 2 [deprecated = true]; + + // Required. + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 5; + + // Pass to force deletion even if the Version is draining. In this case the open pinned + // workflows will be stuck until manually moved to another version by UpdateWorkflowExecutionOptions. + bool skip_drainage = 3; + + // Optional. The identity of the client who initiated this request. + string identity = 4; +} + +message DeleteWorkerDeploymentVersionResponse {} + +// Deletes records of (an old) Deployment. A deployment can only be deleted if +// it has no Version in it. +message DeleteWorkerDeploymentRequest { + string namespace = 1; + + string deployment_name = 2; + + // Optional. The identity of the client who initiated this request. + string identity = 3; +} + +message DeleteWorkerDeploymentResponse {} + +// Used to update the compute config of a Worker Deployment Version. +message UpdateWorkerDeploymentVersionComputeConfigRequest { + string namespace = 1; + + // Required. + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 2; + + // Optional. Contains the compute config scaling groups to add or update for the Worker + // Deployment. + map compute_config_scaling_groups = 6; + + // Optional. Contains the compute config scaling groups to remove from the Worker Deployment. + repeated string remove_compute_config_scaling_groups = 7; + + // Optional. The identity of the client who initiated this request. + string identity = 3; + + // A unique identifier for this create request for idempotence. Typically UUIDv4. + // If a second request with the same ID is recieved, it is considered a successful no-op. + // Retrying with a different request ID for the same deployment name + build ID is an error. + string request_id = 4; +} + +message UpdateWorkerDeploymentVersionComputeConfigResponse {} + +// Used to validate the compute config without attaching it to a Worker Deployment Version. +message ValidateWorkerDeploymentVersionComputeConfigRequest { + string namespace = 1; + + // Required. + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 2; + + // Optional. Contains the compute config scaling groups to add or update for the Worker + // Deployment. + map compute_config_scaling_groups = 6; + + // Optional. Contains the compute config scaling groups to remove from the Worker Deployment. + repeated string remove_compute_config_scaling_groups = 7; + + // Optional. The identity of the client who initiated this request. + string identity = 3; +} + +message ValidateWorkerDeploymentVersionComputeConfigResponse {} + +// Used to update the user-defined metadata of a Worker Deployment Version. +message UpdateWorkerDeploymentVersionMetadataRequest { + string namespace = 1; + + // Deprecated. Use `deployment_version`. + string version = 2 [deprecated = true]; + + // Required. + temporal.api.deployment.v1.WorkerDeploymentVersion deployment_version = 5; + + map upsert_entries = 3; + + // List of keys to remove from the metadata. + repeated string remove_entries = 4; + + // Optional. The identity of the client who initiated this request. + string identity = 6; +} + +message UpdateWorkerDeploymentVersionMetadataResponse { + // Full metadata after performing the update. + temporal.api.deployment.v1.VersionMetadata metadata = 1; +} + +// Update the ManagerIdentity of a Worker Deployment. +message SetWorkerDeploymentManagerRequest { + string namespace = 1; + + string deployment_name = 2; + + oneof new_manager_identity { + // Arbitrary value for `manager_identity`. + // Empty will unset the field. + string manager_identity = 3; + + // True will set `manager_identity` to `identity`. + bool self = 4; + } + + // Optional. This can be the value of conflict_token from a Describe, or another Worker + // Deployment API. Passing a non-nil conflict token will cause this request to fail if the + // Deployment's configuration has been modified between the API call that generated the + // token and this one. + bytes conflict_token = 5; + + // Required. The identity of the client who initiated this request. + string identity = 6; +} + +message SetWorkerDeploymentManagerResponse { + // This value is returned so that it can be optionally passed to APIs + // that write to the Worker Deployment state to ensure that the state + // did not change between this API call and a future write. + bytes conflict_token = 1; + + // What the `manager_identity` field was before this change. + // Deprecated in favor of idempotency of the API. Use `DescribeWorkerDeployment` to get the + // manager identity before calling this API. By passing the `conflict_token` got from the + // `DescribeWorkerDeployment` call to this API you can ensure there is no interfering changes + // between the two calls. + string previous_manager_identity = 2 [deprecated = true]; +} + +// Returns the Current Deployment of a deployment series. +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message GetCurrentDeploymentRequest { + string namespace = 1; + + string series_name = 2; +} + +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message GetCurrentDeploymentResponse { + temporal.api.deployment.v1.DeploymentInfo current_deployment_info = 1; +} + +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message GetDeploymentReachabilityRequest { + string namespace = 1; + + temporal.api.deployment.v1.Deployment deployment = 2; +} + +// [cleanup-wv-pre-release] Pre-release deployment APIs, clean up later +message GetDeploymentReachabilityResponse { + temporal.api.deployment.v1.DeploymentInfo deployment_info = 1; + + temporal.api.enums.v1.DeploymentReachability reachability = 2; + + // Reachability level might come from server cache. This timestamp specifies when the value + // was actually calculated. + google.protobuf.Timestamp last_update_time = 3; +} + +message CreateWorkflowRuleRequest { + string namespace = 1; + + // The rule specification . + temporal.api.rules.v1.WorkflowRuleSpec spec = 2; + + // If true, the rule will be applied to the currently running workflows via batch job. + // If not set , the rule will only be applied when triggering condition is satisfied. + // visibility_query in the rule will be used to select the workflows to apply the rule to. + bool force_scan = 3; + + // Used to de-dupe requests. Typically should be UUID. + string request_id = 4; + + // Identity of the actor who created the rule. Will be stored with the rule. + string identity = 5; + + // Rule description.Will be stored with the rule. + string description = 6; +} + +message CreateWorkflowRuleResponse { + // Created rule. + temporal.api.rules.v1.WorkflowRule rule = 1; + + // Batch Job ID if force-scan flag was provided. Otherwise empty. + string job_id = 2; +} + +message DescribeWorkflowRuleRequest { + string namespace = 1; + + // User-specified ID of the rule to read. Unique within the namespace. + string rule_id = 2; +} + +message DescribeWorkflowRuleResponse { + // The rule that was read. + temporal.api.rules.v1.WorkflowRule rule = 1; +} + +message DeleteWorkflowRuleRequest { + string namespace = 1; + + // ID of the rule to delete. Unique within the namespace. + string rule_id = 2; +} + +message DeleteWorkflowRuleResponse {} + +message ListWorkflowRulesRequest { + string namespace = 1; + + bytes next_page_token = 2; +} + +message ListWorkflowRulesResponse { + repeated temporal.api.rules.v1.WorkflowRule rules = 1; + + bytes next_page_token = 2; +} + +message TriggerWorkflowRuleRequest { + string namespace = 1; + + // Execution info of the workflow which scheduled this activity + temporal.api.common.v1.WorkflowExecution execution = 2; + + // Either provide id of existing rule, or rule specification + oneof rule { + string id = 4; + + // Note: Rule ID and expiration date are not used in the trigger request. + temporal.api.rules.v1.WorkflowRuleSpec spec = 5; + } + + // The identity of the client who initiated this request + string identity = 3; +} + +message TriggerWorkflowRuleResponse { + // True is the rule was applied, based on the rule conditions (predicate/visibility_query). + bool applied = 1; +} + +message RecordWorkerHeartbeatRequest { + // Namespace this worker belongs to. + string namespace = 1; + + // The identity of the client who initiated this request. + string identity = 2; + + repeated temporal.api.worker.v1.WorkerHeartbeat worker_heartbeat = 3; + + // Resource ID for routing. Contains the worker grouping key. + string resource_id = 4; +} + +message RecordWorkerHeartbeatResponse {} + +message ListWorkersRequest { + string namespace = 1; + + int32 page_size = 2; + + bytes next_page_token = 3; + + // `query` in ListWorkers is used to filter workers based on worker attributes. + // Supported attributes: + // * WorkerInstanceKey + // * WorkerIdentity + // * HostName + // * TaskQueue + // * DeploymentName + // * BuildId + // * SdkName + // * SdkVersion + // * StartTime + // * Status + string query = 4; + + // When true, the response will include system workers that are created implicitly + // by the server and not by the user. By default, system workers are excluded. + bool include_system_workers = 5; +} + +message ListWorkersResponse { + // Deprecated: Use workers instead. This field returns full WorkerInfo which + // includes expensive runtime metrics. We will stop populating this field in the future. + repeated temporal.api.worker.v1.WorkerInfo workers_info = 1 [deprecated = true]; + + // Limited worker information. + repeated temporal.api.worker.v1.WorkerListInfo workers = 3; + + // Next page token + bytes next_page_token = 2; +} + +message UpdateTaskQueueConfigRequest { + message RateLimitUpdate { + // Rate Limit to be updated + temporal.api.taskqueue.v1.RateLimit rate_limit = 1; + + // Reason for why the rate limit was set. + string reason = 2; + } + + string namespace = 1; + + string identity = 2; + + // Selects the task queue to update. + string task_queue = 3; + + temporal.api.enums.v1.TaskQueueType task_queue_type = 4; + + // Update to queue-wide rate limit. + // If not set, this configuration is unchanged. + // NOTE: A limit set by the worker is overriden; and restored again when reset. + // If the `rate_limit` field in the `RateLimitUpdate` is missing, remove the existing rate limit. + RateLimitUpdate update_queue_rate_limit = 5; + + // Update to the default fairness key rate limit. + // If not set, this configuration is unchanged. + // If the `rate_limit` field in the `RateLimitUpdate` is missing, remove the existing rate limit. + RateLimitUpdate update_fairness_key_rate_limit_default = 6; + + // If set, overrides the fairness weight for each specified fairness key. + // Fairness keys not listed in this map will keep their existing overrides (if any). + map set_fairness_weight_overrides = 7; + + // If set, removes any existing fairness weight overrides for each specified fairness key. + // Fairness weights for corresponding keys fall back to the values set during task creation (if any), + // or to the default weight of 1.0. + repeated string unset_fairness_weight_overrides = 8; +} + +message UpdateTaskQueueConfigResponse { + temporal.api.taskqueue.v1.TaskQueueConfig config = 1; +} + +message FetchWorkerConfigRequest { + // Namespace this worker belongs to. + string namespace = 1; + + // The identity of the client who initiated this request. + string identity = 2; + + // Reason for sending worker command, can be used for audit purpose. + string reason = 3; + + // Defines which workers should receive this command. + // only single worker is supported at this time. + temporal.api.common.v1.WorkerSelector selector = 6; + + // Resource ID for routing. Contains the worker grouping key. + string resource_id = 7; +} + +message FetchWorkerConfigResponse { + // The worker configuration. + temporal.api.sdk.v1.WorkerConfig worker_config = 1; +} + +message UpdateWorkerConfigRequest { + // Namespace this worker belongs to. + string namespace = 1; + + // The identity of the client who initiated this request. + string identity = 2; + + // Reason for sending worker command, can be used for audit purpose. + string reason = 3; + + // Partial updates are accepted and controlled by update_mask. + // The worker configuration to set. + temporal.api.sdk.v1.WorkerConfig worker_config = 4; + + // Controls which fields from `worker_config` will be applied + google.protobuf.FieldMask update_mask = 5; + + // Defines which workers should receive this command. + temporal.api.common.v1.WorkerSelector selector = 6; + + // Resource ID for routing. Contains the worker grouping key. + string resource_id = 7; +} + +message UpdateWorkerConfigResponse { + oneof response { + // The worker configuration. Will be returned if the command was sent to a single worker. + temporal.api.sdk.v1.WorkerConfig worker_config = 1; + } +} + +message DescribeWorkerRequest { + // Namespace this worker belongs to. + string namespace = 1; + + // Worker instance key to describe. + string worker_instance_key = 2; +} + +message DescribeWorkerResponse { + temporal.api.worker.v1.WorkerInfo worker_info = 1; +} + +message CountWorkersRequest { + string namespace = 1; + + // Query to filter workers before counting. + // Supported filter fields are the same as in ListWorkersRequest. + string query = 2; + + // When true, the count will include system workers that are created implicitly + // by the server and not by the user. By default, system workers are excluded. + bool include_system_workers = 3; +} + +message CountWorkersResponse { + // Number of workers matching the query. + int64 count = 1; +} + +// Request to pause a workflow execution. +message PauseWorkflowExecutionRequest { + // Namespace of the workflow to pause. + string namespace = 1; + + // ID of the workflow execution to be paused. Required. + string workflow_id = 2; + + // Run ID of the workflow execution to be paused. Optional. If not provided, the current run of the workflow will be paused. + string run_id = 3; + + // The identity of the client who initiated this request. + string identity = 4; + + // Reason to pause the workflow execution. + string reason = 5; + + // A unique identifier for this pause request for idempotence. Typically UUIDv4. + string request_id = 6; +} + +// Response to a successful PauseWorkflowExecution request. +message PauseWorkflowExecutionResponse {} + +message UnpauseWorkflowExecutionRequest { + // Namespace of the workflow to unpause. + string namespace = 1; + + // ID of the workflow execution to be paused. Required. + string workflow_id = 2; + + // Run ID of the workflow execution to be paused. Optional. If not provided, the current run of the workflow will be paused. + string run_id = 3; + + // The identity of the client who initiated this request. + string identity = 4; + + // Reason to unpause the workflow execution. + string reason = 5; + + // A unique identifier for this unpause request for idempotence. Typically UUIDv4. + string request_id = 6; +} + +// Response to a successful UnpauseWorkflowExecution request. +message UnpauseWorkflowExecutionResponse {} + +message StartActivityExecutionRequest { + string namespace = 1; + + // The identity of the client who initiated this request + string identity = 2; + + // A unique identifier for this start request. Typically UUIDv4. + string request_id = 3; + + // Identifier for this activity. Required. This identifier should be meaningful in the user's + // own system. It must be unique among activities in the same namespace, subject to the rules + // imposed by id_reuse_policy and id_conflict_policy. + string activity_id = 4; + + // The type of the activity, a string that corresponds to a registered activity on a worker. + temporal.api.common.v1.ActivityType activity_type = 5; + + // Task queue to schedule this activity on. + temporal.api.taskqueue.v1.TaskQueue task_queue = 6; + + // Indicates how long the caller is willing to wait for an activity completion. Limits how long + // retries will be attempted. Either this or `start_to_close_timeout` must be specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 7; + + // Limits time an activity task can stay in a task queue before a worker picks it up. This + // timeout is always non retryable, as all a retry would achieve is to put it back into the same + // queue. Defaults to `schedule_to_close_timeout` if not specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 8; + + // Maximum time an activity is allowed to execute after being picked up by a worker. This + // timeout is always retryable. Either this or `schedule_to_close_timeout` must be + // specified. + // + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 9; + + // Maximum permitted time between successful worker heartbeats. + google.protobuf.Duration heartbeat_timeout = 10; + + // The retry policy for the activity. Will never exceed `schedule_to_close_timeout`. + temporal.api.common.v1.RetryPolicy retry_policy = 11; + + // Serialized arguments to the activity. These are passed as arguments to the activity function. + temporal.api.common.v1.Payloads input = 12; + + // Defines whether to allow re-using the activity id from a previously *closed* activity. + // The default policy is ACTIVITY_ID_REUSE_POLICY_ALLOW_DUPLICATE. + temporal.api.enums.v1.ActivityIdReusePolicy id_reuse_policy = 13; + + // Defines how to resolve an activity id conflict with a *running* activity. + // The default policy is ACTIVITY_ID_CONFLICT_POLICY_FAIL. + temporal.api.enums.v1.ActivityIdConflictPolicy id_conflict_policy = 14; + + // Search attributes for indexing. + temporal.api.common.v1.SearchAttributes search_attributes = 15; + + // Header for context propagation and tracing purposes. + temporal.api.common.v1.Header header = 16; + + // Metadata for use by user interfaces to display the fixed as-of-start summary and details of the activity. + temporal.api.sdk.v1.UserMetadata user_metadata = 17; + + // Priority metadata. + temporal.api.common.v1.Priority priority = 18; + + // Callbacks to be called by the server when this activity reaches a terminal state. + // Callback addresses must be whitelisted in the server's dynamic configuration. + repeated temporal.api.common.v1.Callback completion_callbacks = 19; + + // Links to be associated with the activity. Callbacks may also have associated links; + // links already included with a callback should not be duplicated here. + repeated temporal.api.common.v1.Link links = 20; + + // Options for handling conflicts when using ACTIVITY_ID_CONFLICT_POLICY_USE_EXISTING. + temporal.api.common.v1.OnConflictOptions on_conflict_options = 21; + + // Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts. + google.protobuf.Duration start_delay = 22; +} + +message StartActivityExecutionResponse { + // The run ID of the activity that was started - or used (via ACTIVITY_ID_CONFLICT_POLICY_USE_EXISTING). + string run_id = 1; + + // If true, a new activity was started. + bool started = 2; + + // Link to the started activity. + temporal.api.common.v1.Link link = 3; +} + +message DescribeActivityExecutionRequest { + string namespace = 1; + + string activity_id = 2; + + // Activity run ID. If empty the request targets the latest run. + string run_id = 3; + + // Include the input field in the response. + bool include_input = 4; + + // Include the outcome (result/failure) in the response if the activity has completed. + bool include_outcome = 5; + + // Token from a previous DescribeActivityExecutionResponse. If present, long-poll until activity + // state changes from the state encoded in this token. If absent, return current state immediately. + // If present, run_id must also be present. + // Note that activity state may change multiple times between requests, therefore it is not + // guaranteed that a client making a sequence of long-poll requests will see a complete + // sequence of state changes. + bytes long_poll_token = 6; + + // Include the heartbeat_details field inside info in the response if available. + bool include_heartbeat_details = 7; + + // Include the last_failure field inside info in the response if available. + bool include_last_failure = 8; +} + +message DescribeActivityExecutionResponse { + // The run ID of the activity, useful when run_id was not specified in the request. + string run_id = 1; + + // Information about the activity execution. Fields heartbeat_details and last_failure are omitted unless + // the request has include_heartbeat_details or include_last_failure set to true, respectively. + temporal.api.activity.v1.ActivityExecutionInfo info = 2; + + // Serialized activity input, passed as arguments to the activity function. + // Only set if include_input was true in the request. + temporal.api.common.v1.Payloads input = 3; + + // Only set if the activity is completed and include_outcome was true in the request. + temporal.api.activity.v1.ActivityExecutionOutcome outcome = 4; + + // Token for follow-on long-poll requests. Absent only if the activity is complete. + bytes long_poll_token = 5; + + // Callbacks attached to this activity execution and their current state. + repeated temporal.api.activity.v1.CallbackInfo callbacks = 6; +} + +message PollActivityExecutionRequest { + string namespace = 1; + + string activity_id = 2; + + // Activity run ID. If empty the request targets the latest run. + string run_id = 3; +} + +message PollActivityExecutionResponse { + // The run ID of the activity, useful when run_id was not specified in the request. + string run_id = 1; + + temporal.api.activity.v1.ActivityExecutionOutcome outcome = 2; +} + +message ListActivityExecutionsRequest { + string namespace = 1; + + // Max number of executions to return per page. + int32 page_size = 2; + + // Token returned in ListActivityExecutionsResponse. + bytes next_page_token = 3; + + // Visibility query, see https://docs.temporal.io/list-filter for the syntax. + string query = 4; +} + +message ListActivityExecutionsResponse { + repeated temporal.api.activity.v1.ActivityExecutionListInfo executions = 1; + + // Token to use to fetch the next page. If empty, there is no next page. + bytes next_page_token = 2; +} + +message StartNexusOperationExecutionRequest { + string namespace = 1; + + // The identity of the client who initiated this request. + string identity = 2; + + // A unique identifier for this caller-side start request. Typically UUIDv4. + // StartOperation requests sent to the handler will use a server-generated request ID. + string request_id = 3; + + // Identifier for this operation. This is a caller-side ID, distinct from any internal + // operation identifiers generated by the handler. Must be unique among operations in the + // same namespace, subject to the rules imposed by id_reuse_policy and id_conflict_policy. + string operation_id = 4; + + // Endpoint name, resolved to a URL via the cluster's endpoint registry. + string endpoint = 5; + + // Service name. + string service = 6; + + // Operation name. + string operation = 7; + + // Schedule-to-close timeout for this operation. + // Indicates how long the caller is willing to wait for operation completion. + // Calls are retried internally by the server. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_close_timeout = 8; + + // Schedule-to-start timeout for this operation. + // Indicates how long the caller is willing to wait for the operation to be started (or completed if synchronous) + // by the handler. + // If not set or zero, no schedule-to-start timeout is enforced. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration schedule_to_start_timeout = 9; + + // Start-to-close timeout for this operation. + // Indicates how long the caller is willing to wait for an asynchronous operation to complete after it has been + // started. Synchronous operations ignore this timeout. + // If not set or zero, no start-to-close timeout is enforced. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "to" is used to indicate interval. --) + google.protobuf.Duration start_to_close_timeout = 10; + + // Serialized input to the operation. Passed as the request payload. + temporal.api.common.v1.Payload input = 11; + + // Defines whether to allow re-using the operation id from a previously *closed* operation. + // The default policy is NEXUS_OPERATION_ID_REUSE_POLICY_ALLOW_DUPLICATE. + temporal.api.enums.v1.NexusOperationIdReusePolicy id_reuse_policy = 12; + + // Defines how to resolve an operation id conflict with a *running* operation. + // The default policy is NEXUS_OPERATION_ID_CONFLICT_POLICY_FAIL. + temporal.api.enums.v1.NexusOperationIdConflictPolicy id_conflict_policy = 13; + + // Search attributes for indexing. + temporal.api.common.v1.SearchAttributes search_attributes = 14; + + // Header to attach to the Nexus request. + // Users are responsible for encrypting sensitive data in this header as it is stored in workflow history and + // transmitted to external services as-is. + // This is useful for propagating tracing information. + // Note these headers are not the same as Temporal headers on internal activities and child workflows, these are + // transmitted to Nexus operations that may be external and are not traditional payloads. + map nexus_header = 15; + + // Metadata for use by user interfaces to display the fixed as-of-start summary and details of the operation. + temporal.api.sdk.v1.UserMetadata user_metadata = 16; +} + +message StartNexusOperationExecutionResponse { + // The run ID of the operation that was started - or used (via NEXUS_OPERATION_ID_CONFLICT_POLICY_USE_EXISTING). + string run_id = 1; + + // If true, a new operation was started. + bool started = 2; +} + +message DescribeNexusOperationExecutionRequest { + string namespace = 1; + + string operation_id = 2; + + // Operation run ID. If empty the request targets the latest run. + string run_id = 3; + + // Include the input field in the response. + bool include_input = 4; + + // Include the outcome (result/failure) in the response if the operation has completed. + bool include_outcome = 5; + + // Token from a previous DescribeNexusOperationExecutionResponse. If present, this RPC will long-poll until operation + // state changes from the state encoded in this token. If absent, return current state immediately. + // If present, run_id must also be present. + // Note that operation state may change multiple times between requests, therefore it is not + // guaranteed that a client making a sequence of long-poll requests will see a complete + // sequence of state changes. + bytes long_poll_token = 6; +} + +message DescribeNexusOperationExecutionResponse { + // The run ID of the operation, useful when run_id was not specified in the request. + string run_id = 1; + + // Information about the operation. + temporal.api.nexus.v1.NexusOperationExecutionInfo info = 2; + + // Serialized operation input, passed as the request payload. + // Only set if include_input was true in the request. + temporal.api.common.v1.Payload input = 3; + + // Only set if the operation is completed and include_outcome was true in the request. + oneof outcome { + // The result if the operation completed successfully. + temporal.api.common.v1.Payload result = 4; + + // The failure if the operation completed unsuccessfully. + temporal.api.failure.v1.Failure failure = 5; + } + + // Token for follow-on long-poll requests. Absent only if the operation is complete. + bytes long_poll_token = 6; +} + +message PollNexusOperationExecutionRequest { + string namespace = 1; + + string operation_id = 2; + + // Operation run ID. If empty the request targets the latest run. + string run_id = 3; + + // Stage to wait for. The operation may be in a more advanced stage when the poll is unblocked. + temporal.api.enums.v1.NexusOperationWaitStage wait_stage = 4; +} + +message PollNexusOperationExecutionResponse { + // The run ID of the operation, useful when run_id was not specified in the request. + string run_id = 1; + + // The current stage of the operation. May be more advanced than the stage requested in the poll. + temporal.api.enums.v1.NexusOperationWaitStage wait_stage = 2; + + // Operation token. Only populated for asynchronous operations after a successful StartOperation call. + string operation_token = 3; + + // The operation outcome, available if the operation is in a closed state. + oneof outcome { + // The result if the operation completed successfully. + temporal.api.common.v1.Payload result = 4; + + // The failure if the operation completed unsuccessfully. + temporal.api.failure.v1.Failure failure = 5; + } +} + +message ListNexusOperationExecutionsRequest { + string namespace = 1; + + // Max number of operations to return per page. + int32 page_size = 2; + + // Token returned in ListNexusOperationExecutionsResponse. + bytes next_page_token = 3; + + // Visibility query, see https://docs.temporal.io/list-filter for the syntax. + // Search attributes that are avaialble for Nexus operations include: + // - OperationId + // - RunId + // - Endpoint + // - Service + // - Operation + // - RequestId + // - StartTime + // - ExecutionTime + // - CloseTime + // - ExecutionStatus + // - ExecutionDuration + // - StateTransitionCount + string query = 4; +} + +message ListNexusOperationExecutionsResponse { + repeated temporal.api.nexus.v1.NexusOperationExecutionListInfo operations = 1; + + // Token to use to fetch the next page. If empty, there is no next page. + bytes next_page_token = 2; +} + +message CountActivityExecutionsRequest { + string namespace = 1; + + // Visibility query, see https://docs.temporal.io/list-filter for the syntax. + string query = 2; +} + +message CountActivityExecutionsResponse { + // If `query` is not grouping by any field, the count is an approximate number + // of activities that match the query. + // If `query` is grouping by a field, the count is simply the sum of the counts + // of the groups returned in the response. This number can be smaller than the + // total number of activities matching the query. + int64 count = 1; + + // Contains the groups if the request is grouping by a field. + // The list might not be complete, and the counts of each group is approximate. + repeated AggregationGroup groups = 2; + + message AggregationGroup { + repeated temporal.api.common.v1.Payload group_values = 1; + + int64 count = 2; + } +} + +message CountNexusOperationExecutionsRequest { + string namespace = 1; + + // Visibility query, see https://docs.temporal.io/list-filter for the syntax. + // See also ListNexusOperationExecutionsRequest for search attributes available for Nexus operations. + string query = 2; +} + +message CountNexusOperationExecutionsResponse { + // If `query` is not grouping by any field, the count is an approximate number + // of operations that match the query. + // If `query` is grouping by a field, the count is simply the sum of the counts + // of the groups returned in the response. This number can be smaller than the + // total number of operations matching the query. + int64 count = 1; + + // Contains the groups if the request is grouping by a field. + // The list might not be complete, and the counts of each group is approximate. + repeated AggregationGroup groups = 2; + + message AggregationGroup { + repeated temporal.api.common.v1.Payload group_values = 1; + + int64 count = 2; + } +} + +message RequestCancelActivityExecutionRequest { + string namespace = 1; + + string activity_id = 2; + + // Activity run ID. If empty, targets the latest run. + string run_id = 3; + + // The identity of the worker/client. + string identity = 4; + + // Used to de-dupe cancellation requests. + string request_id = 5; + + // Reason for requesting the cancellation, recorded and available via the PollActivityExecution API. + // Not propagated to a worker if an activity attempt is currently running. + string reason = 6; +} + +message RequestCancelActivityExecutionResponse {} + +message TerminateActivityExecutionRequest { + string namespace = 1; + + string activity_id = 2; + + // Activity run ID. If empty, targets the latest run. + string run_id = 3; + + // The identity of the worker/client. + string identity = 4; + + // Used to de-dupe termination requests. + string request_id = 5; + + // Reason for requesting the termination, recorded in in the activity's result failure outcome. + string reason = 6; +} + +message TerminateActivityExecutionResponse {} + +message DeleteActivityExecutionRequest { + string namespace = 1; + + string activity_id = 2; + + // Activity run ID, targets the latest run if run_id is empty. + string run_id = 3; +} + +message DeleteActivityExecutionResponse {} + +message RequestCancelNexusOperationExecutionRequest { + string namespace = 1; + + string operation_id = 2; + + // Operation run ID, targets the latest run if empty. + string run_id = 3; + + // The identity of the client who initiated this request. + string identity = 4; + + // Used to de-dupe cancellation requests. + string request_id = 5; + + // Reason for requesting the cancellation, recorded and available via the DescribeNexusOperationExecution API. + string reason = 6; +} + +message RequestCancelNexusOperationExecutionResponse {} + +message TerminateNexusOperationExecutionRequest { + string namespace = 1; + + string operation_id = 2; + + // Operation run ID, targets the latest run if empty. + string run_id = 3; + + // The identity of the client who initiated this request. + string identity = 4; + + // Used to de-dupe termination requests. + string request_id = 5; + + // Reason for requesting the termination, recorded in the operation's result failure outcome. + string reason = 6; +} + +message TerminateNexusOperationExecutionResponse {} + +message DeleteNexusOperationExecutionRequest { + string namespace = 1; + + string operation_id = 2; + + // Operation run ID, targets the latest run if empty. + string run_id = 3; +} + +message DeleteNexusOperationExecutionResponse {} + +// A long-poll request that blocks according to a time-skipping waiting policy on the workflow +// execution. Currently the only supported policy is waiting for completion of the fast-forward +// identified by `fast_forward_id`; the poll also returns once anything else settles that outcome +// (e.g. the execution ends or time skipping is disabled). +message PollWorkflowExecutionTimeSkippingRequest { + string namespace = 1; + + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + + // Required. Identifies the fast-forward whose completion the caller wants to wait for. + // Must match the `fast_forward_id` set in the execution's TimeSkippingConfig. + string fast_forward_id = 3; +} + +message PollWorkflowExecutionTimeSkippingResponse { + // The outcome of the poll for the fast-forward identified by the request's `fast_forward_id`. + temporal.api.enums.v1.FastForwardPollingResult fast_forward_polling_result = 1; + + // Set only when the result is FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_FAILED; explains why + // the fast-forward can no longer complete. + string failed_reason = 2; + + // The execution's current fast-forward, if any. + temporal.api.common.v1.TimeSkippingFastForwardInfo fast_forward_info = 3; +} diff --git a/temporal/api/workflowservice/v1/service.proto b/temporal/api/workflowservice/v1/service.proto new file mode 100644 index 000000000..fb7deb192 --- /dev/null +++ b/temporal/api/workflowservice/v1/service.proto @@ -0,0 +1,2158 @@ +// Generated from api_next. DO NOT EDIT. + +syntax = "proto3"; + +package temporal.api.workflowservice.v1; + +import "google/api/annotations.proto"; +import "nexusannotations/v1/options.proto"; +import "temporal/api/protometa/v1/annotations.proto"; +import "temporal/api/workflowservice/v1/request_response.proto"; + +option csharp_namespace = "Temporalio.Api.WorkflowService.V1"; +option go_package = "go.temporal.io/api/workflowservice/v1;workflowservice"; +option java_multiple_files = true; +option java_outer_classname = "ServiceProto"; +option java_package = "io.temporal.api.workflowservice.v1"; +option ruby_package = "Temporalio::Api::WorkflowService::V1"; + +// WorkflowService API defines how Temporal SDKs and other clients interact with the Temporal server +// to create and interact with workflows and activities. +// +// Users are expected to call `StartWorkflowExecution` to create a new workflow execution. +// +// To drive workflows, a worker using a Temporal SDK must exist which regularly polls for workflow +// and activity tasks from the service. For each workflow task, the sdk must process the +// (incremental or complete) event history and respond back with any newly generated commands. +// +// For each activity task, the worker is expected to execute the user's code which implements that +// activity, responding with completion or failure. +service WorkflowService { + // RegisterNamespace creates a new namespace which can be used as a container for all resources. + // + // A Namespace is a top level entity within Temporal, and is used as a container for resources + // like workflow executions, task queues, etc. A Namespace acts as a sandbox and provides + // isolation for all resources within the namespace. All resources belongs to exactly one + // namespace. + rpc RegisterNamespace(RegisterNamespaceRequest) returns (RegisterNamespaceResponse) { + option (google.api.http) = { + post: "/cluster/namespaces", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces", + body: "*" + } + ] + }; + } + + // DescribeNamespace returns the information and configuration for a registered namespace. + rpc DescribeNamespace(DescribeNamespaceRequest) returns (DescribeNamespaceResponse) { + option (google.api.http) = { + get: "/cluster/namespaces/{namespace}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}"}] + }; + } + + // ListNamespaces returns the information and configuration for all namespaces. + rpc ListNamespaces(ListNamespacesRequest) returns (ListNamespacesResponse) { + option (google.api.http) = { + get: "/cluster/namespaces", + additional_bindings: [ + {get: "/api/v1/namespaces"}] + }; + } + + // UpdateNamespace is used to update the information and configuration of a registered + // namespace. + rpc UpdateNamespace(UpdateNamespaceRequest) returns (UpdateNamespaceResponse) { + option (google.api.http) = { + post: "/cluster/namespaces/{namespace}/update", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/update", + body: "*" + } + ] + }; + } + + // DeprecateNamespace is used to update the state of a registered namespace to DEPRECATED. + // + // Once the namespace is deprecated it cannot be used to start new workflow executions. Existing + // workflow executions will continue to run on deprecated namespaces. + // Deprecated. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Deprecated --) + rpc DeprecateNamespace(DeprecateNamespaceRequest) returns (DeprecateNamespaceResponse); + + // StartWorkflowExecution starts a new workflow execution. + // + // It will create the execution with a `WORKFLOW_EXECUTION_STARTED` event in its history and + // also schedule the first workflow task. Returns `WorkflowExecutionAlreadyStarted`, if an + // instance already exists with same workflow id. + rpc StartWorkflowExecution(StartWorkflowExecutionRequest) returns (StartWorkflowExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_id}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_id}" + }; + } + + // ExecuteMultiOperation executes multiple operations within a single workflow. + // + // Operations are started atomically, meaning if *any* operation fails to be started, none are, + // and the request fails. Upon start, the API returns only when *all* operations have a response. + // + // Upon failure, it returns `MultiOperationExecutionFailure` where the status code + // equals the status code of the *first* operation that failed to be started. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: To be exposed over HTTP in the future. --) + rpc ExecuteMultiOperation(ExecuteMultiOperationRequest) returns (ExecuteMultiOperationResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // GetWorkflowExecutionHistory returns the history of specified workflow execution. Fails with + // `NotFound` if the specified workflow execution is unknown to the service. + rpc GetWorkflowExecutionHistory(GetWorkflowExecutionHistoryRequest) returns (GetWorkflowExecutionHistoryResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workflows/{execution.workflow_id}/history", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // GetWorkflowExecutionHistoryReverse returns the history of specified workflow execution in reverse + // order (starting from last event). Fails with`NotFound` if the specified workflow execution is + // unknown to the service. + rpc GetWorkflowExecutionHistoryReverse(GetWorkflowExecutionHistoryReverseRequest) returns (GetWorkflowExecutionHistoryReverseResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // PollWorkflowTaskQueue is called by workers to make progress on workflows. + // + // A WorkflowTask is dispatched to callers for active workflow executions with pending workflow + // tasks. The worker is expected to call `RespondWorkflowTaskCompleted` when it is done + // processing the task. The service will create a `WorkflowTaskStarted` event in the history for + // this task before handing it to the worker. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc PollWorkflowTaskQueue(PollWorkflowTaskQueueRequest) returns (PollWorkflowTaskQueueResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "poller:{poller_group_id}" + }; + } + + // RespondWorkflowTaskCompleted is called by workers to successfully complete workflow tasks + // they received from `PollWorkflowTaskQueue`. + // + // Completing a WorkflowTask will write a `WORKFLOW_TASK_COMPLETED` event to the workflow's + // history, along with events corresponding to whatever commands the SDK generated while + // executing the task (ex timer started, activity task scheduled, etc). + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc RespondWorkflowTaskCompleted(RespondWorkflowTaskCompletedRequest) returns (RespondWorkflowTaskCompletedResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // RespondWorkflowTaskFailed is called by workers to indicate the processing of a workflow task + // failed. + // + // This results in a `WORKFLOW_TASK_FAILED` event written to the history, and a new workflow + // task will be scheduled. This API can be used to report unhandled failures resulting from + // applying the workflow task. + // + // Temporal will only append first WorkflowTaskFailed event to the history of workflow execution + // for consecutive failures. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc RespondWorkflowTaskFailed(RespondWorkflowTaskFailedRequest) returns (RespondWorkflowTaskFailedResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // PollActivityTaskQueue is called by workers to process activity tasks from a specific task + // queue. + // + // The worker is expected to call one of the `RespondActivityTaskXXX` methods when it is done + // processing the task. + // + // An activity task is dispatched whenever a `SCHEDULE_ACTIVITY_TASK` command is produced during + // workflow execution. An in memory `ACTIVITY_TASK_STARTED` event is written to mutable state + // before the task is dispatched to the worker. The started event, and the final event + // (`ACTIVITY_TASK_COMPLETED` / `ACTIVITY_TASK_FAILED` / `ACTIVITY_TASK_TIMED_OUT`) will both be + // written permanently to Workflow execution history when Activity is finished. This is done to + // avoid writing many events in the case of a failure/retry loop. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc PollActivityTaskQueue(PollActivityTaskQueueRequest) returns (PollActivityTaskQueueResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "poller:{poller_group_id}" + }; + } + + // RecordActivityTaskHeartbeat is optionally called by workers while they execute activities. + // + // If a worker fails to heartbeat within the `heartbeat_timeout` interval for the activity task, + // then the current attempt times out. Depending on RetryPolicy, this may trigger a retry or + // time out the activity. + // + // For workflow activities, an `ACTIVITY_TASK_TIMED_OUT` event will be written to the workflow + // history. Calling `RecordActivityTaskHeartbeat` will fail with `NotFound` in such situations, + // in that event, the SDK should request cancellation of the activity. + // + // The request may contain response `details` which will be persisted by the server and may be + // used by the activity to checkpoint progress. The `cancel_requested` field in the response + // indicates whether cancellation has been requested for the activity. + rpc RecordActivityTaskHeartbeat(RecordActivityTaskHeartbeatRequest) returns (RecordActivityTaskHeartbeatResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activity-heartbeat", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activity-heartbeat", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // See `RecordActivityTaskHeartbeat`. This version allows clients to record heartbeats by + // namespace/workflow id/activity id instead of task token. + // + // (-- api-linter: core::0136::prepositions=disabled + // aip.dev/not-precedent: "By" is used to indicate request type. --) + rpc RecordActivityTaskHeartbeatById(RecordActivityTaskHeartbeatByIdRequest) returns (RecordActivityTaskHeartbeatByIdResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/heartbeat", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat", + body: "*" + }, + { + post: "/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat", + body: "*" + }, + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // RespondActivityTaskCompleted is called by workers when they successfully complete an activity + // task. + // + // For workflow activities, this results in a new `ACTIVITY_TASK_COMPLETED` event being written to the workflow history + // and a new workflow task created for the workflow. Fails with `NotFound` if the task token is + // no longer valid due to activity timeout, already being completed, or never having existed. + rpc RespondActivityTaskCompleted(RespondActivityTaskCompletedRequest) returns (RespondActivityTaskCompletedResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activity-complete", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activity-complete", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // See `RespondActivityTaskCompleted`. This version allows clients to record completions by + // namespace/workflow id/activity id instead of task token. + // + // (-- api-linter: core::0136::prepositions=disabled + // aip.dev/not-precedent: "By" is used to indicate request type. --) + rpc RespondActivityTaskCompletedById(RespondActivityTaskCompletedByIdRequest) returns (RespondActivityTaskCompletedByIdResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/complete", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/complete", + body: "*" + }, + { + post: "/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete", + body: "*" + }, + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // RespondActivityTaskFailed is called by workers when processing an activity task fails. + // + // This results in a new `ACTIVITY_TASK_FAILED` event being written to the workflow history and + // a new workflow task created for the workflow. Fails with `NotFound` if the task token is no + // longer valid due to activity timeout, already being completed, or never having existed. + rpc RespondActivityTaskFailed(RespondActivityTaskFailedRequest) returns (RespondActivityTaskFailedResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activity-fail", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activity-fail", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // See `RecordActivityTaskFailed`. This version allows clients to record failures by + // namespace/workflow id/activity id instead of task token. + // + // (-- api-linter: core::0136::prepositions=disabled + // aip.dev/not-precedent: "By" is used to indicate request type. --) + rpc RespondActivityTaskFailedById(RespondActivityTaskFailedByIdRequest) returns (RespondActivityTaskFailedByIdResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/fail", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/fail", + body: "*" + }, + { + post: "/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/fail", + body: "*" + }, + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/fail", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // RespondActivityTaskFailed is called by workers when processing an activity task fails. + // + // For workflow activities, this results in a new `ACTIVITY_TASK_CANCELED` event being written to the workflow history + // and a new workflow task created for the workflow. Fails with `NotFound` if the task token is + // no longer valid due to activity timeout, already being completed, or never having existed. + rpc RespondActivityTaskCanceled(RespondActivityTaskCanceledRequest) returns (RespondActivityTaskCanceledResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activity-resolve-as-canceled", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activity-resolve-as-canceled", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // See `RespondActivityTaskCanceled`. This version allows clients to record failures by + // namespace/workflow id/activity id instead of task token. + // + // (-- api-linter: core::0136::prepositions=disabled + // aip.dev/not-precedent: "By" is used to indicate request type. --) + rpc RespondActivityTaskCanceledById(RespondActivityTaskCanceledByIdRequest) returns (RespondActivityTaskCanceledByIdResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/resolve-as-canceled", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/resolve-as-canceled", + body: "*" + }, + { + post: "/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/resolve-as-canceled", + body: "*" + }, + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/resolve-as-canceled", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // RequestCancelWorkflowExecution is called by workers when they want to request cancellation of + // a workflow execution. + // + // This results in a new `WORKFLOW_EXECUTION_CANCEL_REQUESTED` event being written to the + // workflow history and a new workflow task created for the workflow. It returns success if the requested + // workflow is already closed. It fails with 'NotFound' if the requested workflow doesn't exist. + rpc RequestCancelWorkflowExecution(RequestCancelWorkflowExecutionRequest) returns (RequestCancelWorkflowExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/cancel", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/cancel", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_execution.workflow_id}" + }; + } + + // SignalWorkflowExecution is used to send a signal to a running workflow execution. + // + // This results in a `WORKFLOW_EXECUTION_SIGNALED` event recorded in the history and a workflow + // task being created for the execution. + rpc SignalWorkflowExecution(SignalWorkflowExecutionRequest) returns (SignalWorkflowExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/signal/{signal_name}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/signal/{signal_name}", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_execution.workflow_id}" + }; + } + + // SignalWithStartWorkflowExecution is used to ensure a signal is sent to a workflow, even if + // it isn't yet started. + // + // If the workflow is running, a `WORKFLOW_EXECUTION_SIGNALED` event is recorded in the history + // and a workflow task is generated. + // + // If the workflow is not running or not found, then the workflow is created with + // `WORKFLOW_EXECUTION_STARTED` and `WORKFLOW_EXECUTION_SIGNALED` events in its history, and a + // workflow task is generated. + // + // (-- api-linter: core::0136::prepositions=disabled + // aip.dev/not-precedent: "With" is used to indicate combined operation. --) + rpc SignalWithStartWorkflowExecution(SignalWithStartWorkflowExecutionRequest) returns (SignalWithStartWorkflowExecutionResponse) { + option (nexusannotations.v1.operation) = { + tags: ["exposed"] + }; + + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_id}/signal-with-start/{signal_name}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/signal-with-start/{signal_name}", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_id}" + }; + } + + // ResetWorkflowExecution will reset an existing workflow execution to a specified + // `WORKFLOW_TASK_COMPLETED` event (exclusive). It will immediately terminate the current + // execution instance. "Exclusive" means the identified completed event itself is not replayed + // in the reset history; the preceding `WORKFLOW_TASK_STARTED` event remains and will be marked as failed + // immediately, and a new workflow task will be scheduled to retry it. + rpc ResetWorkflowExecution(ResetWorkflowExecutionRequest) returns (ResetWorkflowExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_execution.workflow_id}" + }; + } + + // TerminateWorkflowExecution terminates an existing workflow execution by recording a + // `WORKFLOW_EXECUTION_TERMINATED` event in the history and immediately terminating the + // execution instance. + rpc TerminateWorkflowExecution(TerminateWorkflowExecutionRequest) returns (TerminateWorkflowExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_execution.workflow_id}" + }; + } + + // DeleteWorkflowExecution asynchronously deletes a specific Workflow Execution (when + // WorkflowExecution.run_id is provided) or the latest Workflow Execution (when + // WorkflowExecution.run_id is not provided). If the Workflow Execution is Running, it will be + // terminated before deletion. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Workflow deletion not exposed to HTTP, users should use cancel or terminate. --) + rpc DeleteWorkflowExecution(DeleteWorkflowExecutionRequest) returns (DeleteWorkflowExecutionResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_execution.workflow_id}" + }; + } + + // ListOpenWorkflowExecutions is a visibility API to list the open executions in a specific namespace. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: HTTP users should use ListWorkflowExecutions instead. --) + rpc ListOpenWorkflowExecutions(ListOpenWorkflowExecutionsRequest) returns (ListOpenWorkflowExecutionsResponse); + + // ListClosedWorkflowExecutions is a visibility API to list the closed executions in a specific namespace. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: HTTP users should use ListWorkflowExecutions instead. --) + rpc ListClosedWorkflowExecutions(ListClosedWorkflowExecutionsRequest) returns (ListClosedWorkflowExecutionsResponse); + + // ListWorkflowExecutions is a visibility API to list workflow executions in a specific namespace. + rpc ListWorkflowExecutions(ListWorkflowExecutionsRequest) returns (ListWorkflowExecutionsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workflows", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workflows"}] + }; + } + + // ListArchivedWorkflowExecutions is a visibility API to list archived workflow executions in a specific namespace. + rpc ListArchivedWorkflowExecutions(ListArchivedWorkflowExecutionsRequest) returns (ListArchivedWorkflowExecutionsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/archived-workflows", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/archived-workflows"}] + }; + } + + // ScanWorkflowExecutions _was_ a visibility API to list large amount of workflow executions in a specific namespace without order. + // It has since been deprecated in favor of `ListWorkflowExecutions` and rewritten to use `ListWorkflowExecutions` internally. + // + // Deprecated: Replaced with `ListWorkflowExecutions`. + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: HTTP users should use ListWorkflowExecutions instead. --) + rpc ScanWorkflowExecutions(ScanWorkflowExecutionsRequest) returns (ScanWorkflowExecutionsResponse); + + // CountWorkflowExecutions is a visibility API to count of workflow executions in a specific namespace. + rpc CountWorkflowExecutions(CountWorkflowExecutionsRequest) returns (CountWorkflowExecutionsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workflow-count", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workflow-count"}] + }; + } + + // GetSearchAttributes is a visibility API to get all legal keys that could be used in list APIs + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose this search attribute API to HTTP (but may expose on OperatorService). --) + rpc GetSearchAttributes(GetSearchAttributesRequest) returns (GetSearchAttributesResponse); + + // RespondQueryTaskCompleted is called by workers to complete queries which were delivered on + // the `query` (not `queries`) field of a `PollWorkflowTaskQueueResponse`. + // + // Completing the query will unblock the corresponding client call to `QueryWorkflow` and return + // the query result a response. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc RespondQueryTaskCompleted(RespondQueryTaskCompletedRequest) returns (RespondQueryTaskCompletedResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "poller:{poller_group_id}" + }; + } + + // ResetStickyTaskQueue resets the sticky task queue related information in the mutable state of + // a given workflow. This is prudent for workers to perform if a workflow has been paged out of + // their cache. + // + // Things cleared are: + // 1. StickyTaskQueue + // 2. StickyScheduleToStartTimeout + // + // When possible, ShutdownWorker should be preferred over + // ResetStickyTaskQueue (particularly when a worker is shutting down or + // cycling). + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc ResetStickyTaskQueue(ResetStickyTaskQueueRequest) returns (ResetStickyTaskQueueResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // ShutdownWorker is used to indicate that the given sticky task + // queue is no longer being polled by its worker. Following the completion of + // ShutdownWorker, newly-added workflow tasks will instead be placed + // in the normal task queue, eligible for any worker to pick up. + // + // ShutdownWorker should be called by workers while shutting down, + // after they've shut down their pollers. If another sticky poll + // request is issued, the sticky task queue will be revived. + // + // As of Temporal Server v1.25.0, ShutdownWorker hasn't yet been implemented. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc ShutdownWorker(ShutdownWorkerRequest) returns (ShutdownWorkerResponse); + + // QueryWorkflow requests a query be executed for a specified workflow execution. + rpc QueryWorkflow(QueryWorkflowRequest) returns (QueryWorkflowResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // DescribeWorkflowExecution returns information about the specified workflow execution. + rpc DescribeWorkflowExecution(DescribeWorkflowExecutionRequest) returns (DescribeWorkflowExecutionResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workflows/{execution.workflow_id}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // DescribeTaskQueue returns the following information about the target task queue, broken down by Build ID: + // - List of pollers + // - Workflow Reachability status + // - Backlog info for Workflow and/or Activity tasks + rpc DescribeTaskQueue(DescribeTaskQueueRequest) returns (DescribeTaskQueueResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/task-queues/{task_queue.name}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/task-queues/{task_queue.name}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "taskqueue:{task_queue.name}" + }; + } + + // GetClusterInfo returns information about temporal cluster + rpc GetClusterInfo(GetClusterInfoRequest) returns (GetClusterInfoResponse) { + option (google.api.http) = { + get: "/cluster", + additional_bindings: [ + {get: "/api/v1/cluster-info"}] + }; + } + + // GetSystemInfo returns information about the system. + rpc GetSystemInfo(GetSystemInfoRequest) returns (GetSystemInfoResponse) { + option (google.api.http) = { + get: "/system-info", + additional_bindings: [ + {get: "/api/v1/system-info"}] + }; + } + + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose this low-level API to HTTP. --) + rpc ListTaskQueuePartitions(ListTaskQueuePartitionsRequest) returns (ListTaskQueuePartitionsResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "taskqueue:{task_queue.name}" + }; + } + + // Creates a new schedule. + rpc CreateSchedule(CreateScheduleRequest) returns (CreateScheduleResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/schedules/{schedule_id}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/schedules/{schedule_id}", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "schedule:{schedule_id}" + }; + } + + // Returns the schedule description and current state of an existing schedule. + rpc DescribeSchedule(DescribeScheduleRequest) returns (DescribeScheduleResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/schedules/{schedule_id}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/schedules/{schedule_id}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "schedule:{schedule_id}" + }; + } + + // Changes the configuration or state of an existing schedule. + rpc UpdateSchedule(UpdateScheduleRequest) returns (UpdateScheduleResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/schedules/{schedule_id}/update", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/schedules/{schedule_id}/update", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "schedule:{schedule_id}" + }; + } + + // Makes a specific change to a schedule or triggers an immediate action. + rpc PatchSchedule(PatchScheduleRequest) returns (PatchScheduleResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/schedules/{schedule_id}/patch", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/schedules/{schedule_id}/patch", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "schedule:{schedule_id}" + }; + } + + // Lists matching times within a range. + rpc ListScheduleMatchingTimes(ListScheduleMatchingTimesRequest) returns (ListScheduleMatchingTimesResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/schedules/{schedule_id}/matching-times", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "schedule:{schedule_id}" + }; + } + + // Deletes a schedule, removing it from the system. + rpc DeleteSchedule(DeleteScheduleRequest) returns (DeleteScheduleResponse) { + option (google.api.http) = { + delete: "/namespaces/{namespace}/schedules/{schedule_id}", + additional_bindings: [ + {delete: "/api/v1/namespaces/{namespace}/schedules/{schedule_id}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "schedule:{schedule_id}" + }; + } + + // List all schedules in a namespace. + rpc ListSchedules(ListSchedulesRequest) returns (ListSchedulesResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/schedules", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/schedules"}] + }; + } + + // CountSchedules is a visibility API to count schedules in a specific namespace. + rpc CountSchedules(CountSchedulesRequest) returns (CountSchedulesResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/schedule-count", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/schedule-count"}] + }; + } + + // Deprecated. Use `UpdateWorkerVersioningRules`. + // Will be removed in server version v1.32.0. + // + // Allows users to specify sets of worker build id versions on a per task queue basis. Versions + // are ordered, and may be either compatible with some extant version, or a new incompatible + // version, forming sets of ids which are incompatible with each other, but whose contained + // members are compatible with one another. + // + // A single build id may be mapped to multiple task queues using this API for cases where a single process hosts + // multiple workers. + // + // To query which workers can be retired, use the `GetWorkerTaskReachability` API. + // + // NOTE: The number of task queues mapped to a single build id is limited by the `limit.taskQueuesPerBuildId` + // (default is 20), if this limit is exceeded this API will error with a FailedPrecondition. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do yet expose versioning API to HTTP. --) + rpc UpdateWorkerBuildIdCompatibility(UpdateWorkerBuildIdCompatibilityRequest) returns (UpdateWorkerBuildIdCompatibilityResponse); + + // Deprecated. Use `GetWorkerVersioningRules`. + // Will be removed in server version v1.32.0. + // Fetches the worker build id versioning sets for a task queue. + rpc GetWorkerBuildIdCompatibility(GetWorkerBuildIdCompatibilityRequest) returns (GetWorkerBuildIdCompatibilityResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility"}] + }; + } + + // Use this API to manage Worker Versioning Rules for a given Task Queue. There are two types of + // rules: Build ID Assignment rules and Compatible Build ID Redirect rules. + // + // Assignment rules determine how to assign new executions to a Build IDs. Their primary + // use case is to specify the latest Build ID but they have powerful features for gradual rollout + // of a new Build ID. + // + // Once a workflow execution is assigned to a Build ID and it completes its first Workflow Task, + // the workflow stays on the assigned Build ID regardless of changes in assignment rules. This + // eliminates the need for compatibility between versions when you only care about using the new + // version for new workflows and let existing workflows finish in their own version. + // + // Activities, Child Workflows and Continue-as-New executions have the option to inherit the + // Build ID of their parent/previous workflow or use the latest assignment rules to independently + // select a Build ID. + // + // Redirect rules should only be used when you want to move workflows and activities assigned to + // one Build ID (source) to another compatible Build ID (target). You are responsible to make sure + // the target Build ID of a redirect rule is able to process event histories made by the source + // Build ID by using [Patching](https://docs.temporal.io/workflows#patching) or other means. + // + // Will be removed in server version v1.32.0. + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do yet expose versioning API to HTTP. --) + rpc UpdateWorkerVersioningRules(UpdateWorkerVersioningRulesRequest) returns (UpdateWorkerVersioningRulesResponse); + + // Fetches the Build ID assignment and redirect rules for a Task Queue. + // Will be removed in server version v1.32.0. + rpc GetWorkerVersioningRules(GetWorkerVersioningRulesRequest) returns (GetWorkerVersioningRulesResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules"}] + }; + } + + // Deprecated. Use `DescribeTaskQueue`. + // Will be removed in server version v1.32.0. + // + // Fetches task reachability to determine whether a worker may be retired. + // The request may specify task queues to query for or let the server fetch all task queues mapped to the given + // build IDs. + // + // When requesting a large number of task queues or all task queues associated with the given build ids in a + // namespace, all task queues will be listed in the response but some of them may not contain reachability + // information due to a server enforced limit. When reaching the limit, task queues that reachability information + // could not be retrieved for will be marked with a single TASK_REACHABILITY_UNSPECIFIED entry. The caller may issue + // another call to get the reachability for those task queues. + // + // Open source users can adjust this limit by setting the server's dynamic config value for + // `limit.reachabilityTaskQueueScan` with the caveat that this call can strain the visibility store. + rpc GetWorkerTaskReachability(GetWorkerTaskReachabilityRequest) returns (GetWorkerTaskReachabilityResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/worker-task-reachability", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/worker-task-reachability"}] + }; + } + + // Describes a worker deployment. + // Experimental. This API might significantly change or be removed in a future release. + // Deprecated. Replaced with `DescribeWorkerDeploymentVersion`. + rpc DescribeDeployment(DescribeDeploymentRequest) returns (DescribeDeploymentResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}"}] + }; + } + + // Describes a worker deployment version. + // Experimental. This API might significantly change or be removed in a future release. + rpc DescribeWorkerDeploymentVersion(DescribeWorkerDeploymentVersionRequest) returns (DescribeWorkerDeploymentVersionResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "deployment:{deployment_version.deployment_name}" + }; + } + + // Lists worker deployments in the namespace. Optionally can filter based on deployment series + // name. + // Experimental. This API might significantly change or be removed in a future release. + // Deprecated. Replaced with `ListWorkerDeployments`. + rpc ListDeployments(ListDeploymentsRequest) returns (ListDeploymentsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/deployments", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/deployments"}] + }; + } + + // Returns the reachability level of a worker deployment to help users decide when it is time + // to decommission a deployment. Reachability level is calculated based on the deployment's + // `status` and existing workflows that depend on the given deployment for their execution. + // Calculating reachability is relatively expensive. Therefore, server might return a recently + // cached value. In such a case, the `last_update_time` will inform you about the actual + // reachability calculation time. + // Experimental. This API might significantly change or be removed in a future release. + // Deprecated. Replaced with `DrainageInfo` returned by `DescribeWorkerDeploymentVersion`. + rpc GetDeploymentReachability(GetDeploymentReachabilityRequest) returns (GetDeploymentReachabilityResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability"}] + }; + } + + // Returns the current deployment (and its info) for a given deployment series. + // Experimental. This API might significantly change or be removed in a future release. + // Deprecated. Replaced by `current_version` returned by `DescribeWorkerDeployment`. + rpc GetCurrentDeployment(GetCurrentDeploymentRequest) returns (GetCurrentDeploymentResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/current-deployment/{series_name}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/current-deployment/{series_name}"}] + }; + } + + // Sets a deployment as the current deployment for its deployment series. Can optionally update + // the metadata of the deployment as well. + // Experimental. This API might significantly change or be removed in a future release. + // Deprecated. Replaced by `SetWorkerDeploymentCurrentVersion`. + rpc SetCurrentDeployment(SetCurrentDeploymentRequest) returns (SetCurrentDeploymentResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/current-deployment/{deployment.series_name}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}", + body: "*" + } + ] + }; + } + + // Set/unset the Current Version of a Worker Deployment. Automatically unsets the Ramping + // Version if it is the Version being set as Current. + // Experimental. This API might significantly change or be removed in a future release. + rpc SetWorkerDeploymentCurrentVersion(SetWorkerDeploymentCurrentVersionRequest) returns (SetWorkerDeploymentCurrentVersionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "deployment:{deployment_name}" + }; + } + + // Describes a Worker Deployment. + // Experimental. This API might significantly change or be removed in a future release. + rpc DescribeWorkerDeployment(DescribeWorkerDeploymentRequest) returns (DescribeWorkerDeploymentResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/worker-deployments/{deployment_name}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "deployment:{deployment_name}" + }; + } + + // Deletes records of (an old) Deployment. A deployment can only be deleted if + // it has no Version in it. + // Experimental. This API might significantly change or be removed in a future release. + rpc DeleteWorkerDeployment(DeleteWorkerDeploymentRequest) returns (DeleteWorkerDeploymentResponse) { + option (google.api.http) = { + delete: "/namespaces/{namespace}/worker-deployments/{deployment_name}", + additional_bindings: [ + {delete: "/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "deployment:{deployment_name}" + }; + } + + // Used for manual deletion of Versions. User can delete a Version only when all the + // following conditions are met: + // - It is not the Current or Ramping Version of its Deployment. + // - It has no active pollers (none of the task queues in the Version have pollers) + // - It is not draining (see WorkerDeploymentVersionInfo.drainage_info). This condition + // can be skipped by passing `skip-drainage=true`. + // Experimental. This API might significantly change or be removed in a future release. + rpc DeleteWorkerDeploymentVersion(DeleteWorkerDeploymentVersionRequest) returns (DeleteWorkerDeploymentVersionResponse) { + option (google.api.http) = { + delete: "/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}", + additional_bindings: [ + {delete: "/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "deployment:{deployment_version.deployment_name}" + }; + } + + // Set/unset the Ramping Version of a Worker Deployment and its ramp percentage. Can be used for + // gradual ramp to unversioned workers too. + // Experimental. This API might significantly change or be removed in a future release. + rpc SetWorkerDeploymentRampingVersion(SetWorkerDeploymentRampingVersionRequest) returns (SetWorkerDeploymentRampingVersionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/worker-deployments/{deployment_name}/set-ramping-version", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-ramping-version", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "deployment:{deployment_name}" + }; + } + + // Lists all Worker Deployments that are tracked in the Namespace. + // Experimental. This API might significantly change or be removed in a future release. + rpc ListWorkerDeployments(ListWorkerDeploymentsRequest) returns (ListWorkerDeploymentsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/worker-deployments", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/worker-deployments"}] + }; + } + + // Creates a new Worker Deployment. + // + // Experimental. This API might significantly change or be removed in a + // future release. + rpc CreateWorkerDeployment(CreateWorkerDeploymentRequest) returns (CreateWorkerDeploymentResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/worker-deployments/{deployment_name}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}", + body: "*" + } + ] + }; + } + + // Creates a new Worker Deployment Version. + // + // Experimental. This API might significantly change or be removed in a + // future release. + rpc CreateWorkerDeploymentVersion(CreateWorkerDeploymentVersionRequest) returns (CreateWorkerDeploymentVersionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}", + body: "*" + } + ] + }; + } + + // Updates the compute config attached to a Worker Deployment Version. + // Experimental. This API might significantly change or be removed in a future release. + rpc UpdateWorkerDeploymentVersionComputeConfig(UpdateWorkerDeploymentVersionComputeConfigRequest) returns (UpdateWorkerDeploymentVersionComputeConfigResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-compute-config", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-compute-config", + body: "*" + } + ] + }; + } + + // Validates the compute config without attaching it to a Worker Deployment Version. + // Experimental. This API might significantly change or be removed in a future release. + rpc ValidateWorkerDeploymentVersionComputeConfig(ValidateWorkerDeploymentVersionComputeConfigRequest) returns (ValidateWorkerDeploymentVersionComputeConfigResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/validate-compute-config", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/validate-compute-config", + body: "*" + } + ] + }; + } + + // Updates the user-given metadata attached to a Worker Deployment Version. + // Experimental. This API might significantly change or be removed in a future release. + rpc UpdateWorkerDeploymentVersionMetadata(UpdateWorkerDeploymentVersionMetadataRequest) returns (UpdateWorkerDeploymentVersionMetadataResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-metadata", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-metadata", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "deployment:{deployment_version.deployment_name}" + }; + } + + // Set/unset the ManagerIdentity of a Worker Deployment. + // Experimental. This API might significantly change or be removed in a future release. + rpc SetWorkerDeploymentManager(SetWorkerDeploymentManagerRequest) returns (SetWorkerDeploymentManagerResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/worker-deployments/{deployment_name}/set-manager", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-manager", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "deployment:{deployment_name}" + }; + } + + // Invokes the specified Update function on user Workflow code. + rpc UpdateWorkflowExecution(UpdateWorkflowExecutionRequest) returns (UpdateWorkflowExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update/{request.input.name}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update/{request.input.name}", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_execution.workflow_id}" + }; + } + + // Polls a Workflow Execution for the outcome of a Workflow Update + // previously issued through the UpdateWorkflowExecution RPC. The effective + // timeout on this call will be shorter of the the caller-supplied gRPC + // timeout and the server's configured long-poll timeout. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We don't expose update polling API to HTTP in favor of a potential future non-blocking form. --) + rpc PollWorkflowExecutionUpdate(PollWorkflowExecutionUpdateRequest) returns (PollWorkflowExecutionUpdateResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{update_ref.workflow_execution.workflow_id}" + }; + } + + // StartBatchOperation starts a new batch operation + rpc StartBatchOperation(StartBatchOperationRequest) returns (StartBatchOperationResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/batch-operations/{job_id}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/batch-operations/{job_id}", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "batch:{job_id}" + }; + } + + // StopBatchOperation stops a batch operation + rpc StopBatchOperation(StopBatchOperationRequest) returns (StopBatchOperationResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/batch-operations/{job_id}/stop", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/batch-operations/{job_id}/stop", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "batch:{job_id}" + }; + } + + // DescribeBatchOperation returns the information about a batch operation + rpc DescribeBatchOperation(DescribeBatchOperationRequest) returns (DescribeBatchOperationResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/batch-operations/{job_id}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/batch-operations/{job_id}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "batch:{job_id}" + }; + } + + // ListBatchOperations returns a list of batch operations + rpc ListBatchOperations(ListBatchOperationsRequest) returns (ListBatchOperationsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/batch-operations", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/batch-operations"}] + }; + } + + // PollNexusTaskQueue is a long poll call used by workers to receive Nexus tasks. + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc PollNexusTaskQueue(PollNexusTaskQueueRequest) returns (PollNexusTaskQueueResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "poller:{poller_group_id}" + }; + } + + // RespondNexusTaskCompleted is called by workers to respond to Nexus tasks received via PollNexusTaskQueue. + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc RespondNexusTaskCompleted(RespondNexusTaskCompletedRequest) returns (RespondNexusTaskCompletedResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "poller:{poller_group_id}" + }; + } + + // RespondNexusTaskFailed is called by workers to fail Nexus tasks received via PollNexusTaskQueue. + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We do not expose worker API to HTTP. --) + rpc RespondNexusTaskFailed(RespondNexusTaskFailedRequest) returns (RespondNexusTaskFailedResponse) { + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "poller:{poller_group_id}" + }; + } + + // UpdateActivityOptions is called by the client to update the options of an activity by its ID or type. + // If there are multiple pending activities of the provided type - all of them will be updated. + // This API will be deprecated soon and replaced with a newer UpdateActivityExecutionOptions that is better named and + // structured to work well for standalone activities. + rpc UpdateActivityOptions(UpdateActivityOptionsRequest) returns (UpdateActivityOptionsResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities-deprecated/update-options", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities-deprecated/update-options", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // UpdateWorkflowExecutionOptions partially updates the WorkflowExecutionOptions of an existing workflow execution. + rpc UpdateWorkflowExecutionOptions(UpdateWorkflowExecutionOptionsRequest) returns (UpdateWorkflowExecutionOptionsResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update-options", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update-options", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_execution.workflow_id}" + }; + } + + // PauseActivity pauses the execution of an activity specified by its ID or type. + // If there are multiple pending activities of the provided type - all of them will be paused + // + // Pausing an activity means: + // - If the activity is currently waiting for a retry or is running and subsequently fails, + // it will not be rescheduled until it is unpaused. + // - If the activity is already paused, calling this method will have no effect. + // - If the activity is running and finishes successfully, the activity will be completed. + // - If the activity is running and finishes with failure: + // * if there is no retry left - the activity will be completed. + // * if there are more retries left - the activity will be paused. + // For long-running activities: + // - activities in paused state will send a cancellation with "activity_paused" set to 'true' in response to 'RecordActivityTaskHeartbeat'. + // - The activity should respond to the cancellation accordingly. + // + // Returns a `NotFound` error if there is no pending activity with the provided ID or type + // This API will be deprecated soon and replaced with a newer PauseActivityExecution that is better named and + // structured to work well for standalone activities. + rpc PauseActivity(PauseActivityRequest) returns (PauseActivityResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities-deprecated/pause", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities-deprecated/pause", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // UnpauseActivity unpauses the execution of an activity specified by its ID or type. + // If there are multiple pending activities of the provided type - all of them will be unpaused. + // + // If activity is not paused, this call will have no effect. + // If the activity was paused while waiting for retry, it will be scheduled immediately (* see 'jitter' flag). + // Once the activity is unpaused, all timeout timers will be regenerated. + // + // Flags: + // 'jitter': the activity will be scheduled at a random time within the jitter duration. + // 'reset_attempts': the number of attempts will be reset. + // 'reset_heartbeat': the activity heartbeat timer and heartbeats will be reset. + // + // Returns a `NotFound` error if there is no pending activity with the provided ID or type + // This API will be deprecated soon and replaced with a newer UnpauseActivityExecution that is better named and + // structured to work well for standalone activities. + rpc UnpauseActivity(UnpauseActivityRequest) returns (UnpauseActivityResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities-deprecated/unpause", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities-deprecated/unpause", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // ResetActivity resets the execution of an activity specified by its ID or type. + // If there are multiple pending activities of the provided type - all of them will be reset. + // + // Resetting an activity means: + // * number of attempts will be reset to 0. + // * activity timeouts will be reset. + // * if the activity is waiting for retry, and it is not paused or 'keep_paused' is not provided: + // it will be scheduled immediately (* see 'jitter' flag), + // + // Flags: + // + // 'jitter': the activity will be scheduled at a random time within the jitter duration. + // If the activity currently paused it will be unpaused, unless 'keep_paused' flag is provided. + // 'reset_heartbeats': the activity heartbeat timer and heartbeats will be reset. + // 'keep_paused': if the activity is paused, it will remain paused. + // + // Returns a `NotFound` error if there is no pending activity with the provided ID or type. + // This API will be deprecated soon and replaced with a newer ResetActivityExecution that is better named and + // structured to work well for standalone activities. + rpc ResetActivity(ResetActivityRequest) returns (ResetActivityResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities-deprecated/reset", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities-deprecated/reset", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // Create a new workflow rule. The rules are used to control the workflow execution. + // The rule will be applied to all running and new workflows in the namespace. + // If the rule with such ID already exist this call will fail + // Note: the rules are part of namespace configuration and will be stored in the namespace config. + // Namespace config is eventually consistent. + rpc CreateWorkflowRule(CreateWorkflowRuleRequest) returns (CreateWorkflowRuleResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflow-rules", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflow-rules", + body: "*" + } + ] + }; + } + + // DescribeWorkflowRule return the rule specification for existing rule id. + // If there is no rule with such id - NOT FOUND error will be returned. + rpc DescribeWorkflowRule(DescribeWorkflowRuleRequest) returns (DescribeWorkflowRuleResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workflow-rules/{rule_id}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workflow-rules/{rule_id}"}] + }; + } + + // Delete rule by rule id + rpc DeleteWorkflowRule(DeleteWorkflowRuleRequest) returns (DeleteWorkflowRuleResponse) { + option (google.api.http) = { + delete: "/namespaces/{namespace}/workflow-rules/{rule_id}", + additional_bindings: [ + {delete: "/api/v1/namespaces/{namespace}/workflow-rules/{rule_id}"}] + }; + } + + // Return all namespace workflow rules + rpc ListWorkflowRules(ListWorkflowRulesRequest) returns (ListWorkflowRulesResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workflow-rules", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workflow-rules"}] + }; + } + + // TriggerWorkflowRule allows to: + // * trigger existing rule for a specific workflow execution; + // * trigger rule for a specific workflow execution without creating a rule; + // This is useful for one-off operations. + rpc TriggerWorkflowRule(TriggerWorkflowRuleRequest) returns (TriggerWorkflowRuleResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{execution.workflow_id}/trigger-rule", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/trigger-rule", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{execution.workflow_id}" + }; + } + + // WorkerHeartbeat receive heartbeat request from the worker. + rpc RecordWorkerHeartbeat(RecordWorkerHeartbeatRequest) returns (RecordWorkerHeartbeatResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workers/heartbeat", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workers/heartbeat", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // ListWorkers is a visibility API to list worker status information in a specific namespace. + rpc ListWorkers(ListWorkersRequest) returns (ListWorkersResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workers", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workers"}] + }; + } + + // CountWorkers counts the number of workers in a specific namespace. + rpc CountWorkers(CountWorkersRequest) returns (CountWorkersResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/worker-count", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/worker-count"}] + }; + } + + // Updates task queue configuration. + // For the overall queue rate limit: the rate limit set by this api overrides the worker-set rate limit, + // which uncouples the rate limit from the worker lifecycle. + // If the overall queue rate limit is unset, the worker-set rate limit takes effect. + rpc UpdateTaskQueueConfig(UpdateTaskQueueConfigRequest) returns (UpdateTaskQueueConfigResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/task-queues/{task_queue}/update-config", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "taskqueue:{task_queue}" + }; + } + + // FetchWorkerConfig returns the worker configuration for a specific worker. + rpc FetchWorkerConfig(FetchWorkerConfigRequest) returns (FetchWorkerConfigResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workers/fetch-config", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workers/fetch-config", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // UpdateWorkerConfig updates the worker configuration of one or more workers. + // Can be used to partially update the worker configuration. + // Can be used to update the configuration of multiple workers. + rpc UpdateWorkerConfig(UpdateWorkerConfigRequest) returns (UpdateWorkerConfigResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workers/update-config", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workers/update-config", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // DescribeWorker returns information about the specified worker. + rpc DescribeWorker(DescribeWorkerRequest) returns (DescribeWorkerResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workers/describe/{worker_instance_key}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "worker:{worker_instance_key}" + }; + } + + // Note: This is an experimental API and the behavior may change in a future release. + // PauseWorkflowExecution pauses the workflow execution specified in the request. Pausing a workflow execution results in + // - The workflow execution status changes to `PAUSED` and a new WORKFLOW_EXECUTION_PAUSED event is added to the history + // - No new workflow tasks or activity tasks are dispatched. + // - Any workflow task currently executing on the worker will be allowed to complete. + // - Any activity task currently executing will be paused. + // - All server-side events will continue to be processed by the server. + // - Queries & Updates on a paused workflow will be rejected. + rpc PauseWorkflowExecution(PauseWorkflowExecutionRequest) returns (PauseWorkflowExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_id}/pause", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/pause", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_id}" + }; + } + + // Note: This is an experimental API and the behavior may change in a future release. + // UnpauseWorkflowExecution unpauses a previously paused workflow execution specified in the request. + // Unpausing a workflow execution results in + // - The workflow execution status changes to `RUNNING` and a new WORKFLOW_EXECUTION_UNPAUSED event is added to the history + // - Workflow tasks and activity tasks are resumed. + rpc UnpauseWorkflowExecution(UnpauseWorkflowExecutionRequest) returns (UnpauseWorkflowExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/workflows/{workflow_id}/unpause", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_id}" + }; + } + + // StartActivityExecution starts a new activity execution. + // + // Returns an `ActivityExecutionAlreadyStarted` error if an instance already exists with same activity ID in this namespace + // unless permitted by the specified ID conflict policy. + rpc StartActivityExecution(StartActivityExecutionRequest) returns (StartActivityExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "activity:{activity_id}" + }; + } + + // StartNexusOperationExecution starts a new Nexus operation. + // + // Returns a `NexusOperationExecutionAlreadyStarted` error if an instance already exists with same operation ID in this + // namespace unless permitted by the specified ID conflict policy. + rpc StartNexusOperationExecution(StartNexusOperationExecutionRequest) returns (StartNexusOperationExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/nexus-operations/{operation_id}", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}", + body: "*" + } + ] + }; + } + + // DescribeActivityExecution returns information about an activity execution. + // It can be used to: + // - Get current activity info without waiting + // - Long-poll for next state change and return new activity info + // Response can optionally include activity input or outcome (if the activity has completed). + rpc DescribeActivityExecution(DescribeActivityExecutionRequest) returns (DescribeActivityExecutionResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/activities/{activity_id}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/activities/{activity_id}"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "activity:{activity_id}" + }; + } + + // DescribeNexusOperationExecution returns information about a Nexus operation. + // Supported use cases include: + // - Get current operation info without waiting + // - Long-poll for next state change and return new operation info + // Response can optionally include operation input or outcome (if the operation has completed). + rpc DescribeNexusOperationExecution(DescribeNexusOperationExecutionRequest) returns (DescribeNexusOperationExecutionResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/nexus-operations/{operation_id}", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}"}] + }; + } + + // PollActivityExecution long-polls for an activity execution to complete and returns the + // outcome (result or failure). + rpc PollActivityExecution(PollActivityExecutionRequest) returns (PollActivityExecutionResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/activities/{activity_id}/outcome", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "activity:{activity_id}" + }; + } + + // PollNexusOperationExecution long-polls for a Nexus operation for a given wait stage to complete and returns + // the outcome (result or failure). + rpc PollNexusOperationExecution(PollNexusOperationExecutionRequest) returns (PollNexusOperationExecutionResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/nexus-operations/{operation_id}/poll", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/poll"}] + }; + } + + // ListActivityExecutions is a visibility API to list activity executions in a specific namespace. + rpc ListActivityExecutions(ListActivityExecutionsRequest) returns (ListActivityExecutionsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/activities", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/activities"}] + }; + } + + // ListNexusOperationExecutions is a visibility API to list Nexus operations in a specific namespace. + rpc ListNexusOperationExecutions(ListNexusOperationExecutionsRequest) returns (ListNexusOperationExecutionsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/nexus-operations", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/nexus-operations"}] + }; + } + + // CountActivityExecutions is a visibility API to count activity executions in a specific namespace. + rpc CountActivityExecutions(CountActivityExecutionsRequest) returns (CountActivityExecutionsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/activity-count", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/activity-count"}] + }; + } + + // CountNexusOperationExecutions is a visibility API to count Nexus operations in a specific namespace. + rpc CountNexusOperationExecutions(CountNexusOperationExecutionsRequest) returns (CountNexusOperationExecutionsResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/nexus-operation-count", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/nexus-operation-count"}] + }; + } + + // RequestCancelActivityExecution requests cancellation of an activity execution. + // + // Cancellation is cooperative: this call records the request, but the activity must detect and + // acknowledge it for the activity to reach CANCELED status. The cancellation signal is + // delivered via `cancel_requested` in the heartbeat response; SDKs surface this via + // language-idiomatic mechanisms (context cancellation, exceptions, abort signals). + rpc RequestCancelActivityExecution(RequestCancelActivityExecutionRequest) returns (RequestCancelActivityExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/cancel", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "activity:{activity_id}" + }; + } + + // RequestCancelNexusOperationExecution requests cancellation of a Nexus operation. + // + // Requesting to cancel an operation does not automatically transition the operation to canceled status. + // The operation will only transition to canceled status if it supports cancellation and the handler + // processes the cancellation request. + rpc RequestCancelNexusOperationExecution(RequestCancelNexusOperationExecutionRequest) returns (RequestCancelNexusOperationExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/nexus-operations/{operation_id}/cancel", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel", + body: "*" + } + ] + }; + } + + // TerminateActivityExecution terminates an existing activity execution immediately. + // + // Termination does not reach the worker and the activity code cannot react to it. A terminated activity may have a + // running attempt. + rpc TerminateActivityExecution(TerminateActivityExecutionRequest) returns (TerminateActivityExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/terminate", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "activity:{activity_id}" + }; + } + + // DeleteActivityExecution asynchronously deletes a specific activity execution (when + // ActivityExecution.run_id is provided) or the latest activity execution (when + // ActivityExecution.run_id is not provided). If the activity Execution is running, it will be + // terminated before deletion. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Activity deletion not exposed to HTTP, users should use cancel or terminate. --) + rpc DeleteActivityExecution(DeleteActivityExecutionRequest) returns (DeleteActivityExecutionResponse); + + // PauseActivityExecution pauses the execution of an activity specified by its ID. + // This API can be used to target a workflow activity or a standalone activity + // + // Pausing an activity means: + // - If the activity is currently waiting for a retry or is running and subsequently fails, + // it will not be rescheduled until it is unpaused. + // - If the activity is already paused, calling this method will have no effect. + // - If the activity is running and finishes successfully, the activity will be completed. + // - If the activity is running and finishes with failure: + // * if there is no retry left - the activity will be completed. + // * if there are more retries left - the activity will be paused. + // For long-running activities: + // - activities in paused state will send a cancellation with "activity_paused" set to 'true' in response to 'RecordActivityTaskHeartbeat'. + // + // Returns a `NotFound` error if there is no pending activity with the provided ID + rpc PauseActivityExecution(PauseActivityExecutionRequest) returns (PauseActivityExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/pause", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/pause", + body: "*" + }, + { + post: "/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause", + body: "*" + }, + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // ResetActivityExecution resets the execution of an activity specified by its ID. + // This API can be used to target a workflow activity or a standalone activity. + // + // Resetting an activity means: + // * number of attempts will be reset to 0. + // * activity timeouts will be reset. + // * if the activity is waiting for retry, and it is not paused or 'keep_paused' is not provided: + // it will be scheduled immediately (* see 'jitter' flag) + // + // Returns a `NotFound` error if there is no pending activity with the provided ID or type. + rpc ResetActivityExecution(ResetActivityExecutionRequest) returns (ResetActivityExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/reset", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/reset", + body: "*" + }, + { + post: "/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset", + body: "*" + }, + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // UnpauseActivityExecution unpauses the execution of an activity specified by its ID. + // This API can be used to target a workflow activity or a standalone activity. + // + // If activity is not paused, this call will have no effect. + // If the activity was paused while waiting for retry, it will be scheduled immediately (* see 'jitter' flag). + // Once the activity is unpaused, all timeout timers will be regenerated. + // + // Returns a `NotFound` error if there is no pending activity with the provided ID + rpc UnpauseActivityExecution(UnpauseActivityExecutionRequest) returns (UnpauseActivityExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/unpause", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/unpause", + body: "*" + }, + { + post: "/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause", + body: "*" + }, + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // UpdateActivityExecutionOptions is called by the client to update the options of an activity by its ID. + // This API can be used to target a workflow activity or a standalone activity. + rpc UpdateActivityExecutionOptions(UpdateActivityExecutionOptionsRequest) returns (UpdateActivityExecutionOptionsResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/activities/{activity_id}/update-options", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/activities/{activity_id}/update-options", + body: "*" + }, + { + post: "/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options", + body: "*" + }, + { + post: "/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options", + body: "*" + } + ] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "{resource_id}" + }; + } + + // TerminateNexusOperationExecution terminates an existing Nexus operation immediately. + // + // Termination happens immediately and the operation handler cannot react to it. A terminated operation will have + // its outcome set to a failure with a termination reason. + rpc TerminateNexusOperationExecution(TerminateNexusOperationExecutionRequest) returns (TerminateNexusOperationExecutionResponse) { + option (google.api.http) = { + post: "/namespaces/{namespace}/nexus-operations/{operation_id}/terminate", + body: "*", + additional_bindings: [ + { + post: "/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate", + body: "*" + } + ] + }; + } + + // DeleteNexusOperationExecution asynchronously deletes a specific Nexus operation run (when + // run_id is provided) or the latest run (when run_id is not provided). If the operation + // is running, it will be terminated before deletion. + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: Nexus operation deletion not exposed to HTTP, users should use cancel or terminate. --) + rpc DeleteNexusOperationExecution(DeleteNexusOperationExecutionRequest) returns (DeleteNexusOperationExecutionResponse); + + rpc PollWorkflowExecutionTimeSkipping(PollWorkflowExecutionTimeSkippingRequest) returns (PollWorkflowExecutionTimeSkippingResponse) { + option (google.api.http) = { + get: "/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/time-skipping/poll", + additional_bindings: [ + {get: "/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/time-skipping/poll"}] + }; + + option (temporal.api.protometa.v1.request_header) = { + header: "temporal-resource-id", + value: "workflow:{workflow_execution.workflow_id}" + }; + } +} diff --git a/temporal/api_next/activity/v1/message.proto b/temporal/api_next/activity/v1/message.proto index e3852aa9f..acbd0b3f9 100644 --- a/temporal/api_next/activity/v1/message.proto +++ b/temporal/api_next/activity/v1/message.proto @@ -12,14 +12,14 @@ option csharp_namespace = "Temporalio.Api.Activity.V1"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/deployment/v1/message.proto"; -import "temporal/api/enums/v1/activity.proto"; -import "temporal/api/callback/v1/message.proto"; -import "temporal/api/enums/v1/workflow.proto"; -import "temporal/api/failure/v1/message.proto"; -import "temporal/api/taskqueue/v1/message.proto"; -import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/deployment/v1/message.proto"; +import "temporal/api_next/enums/v1/activity.proto"; +import "temporal/api_next/callback/v1/message.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; +import "temporal/api_next/failure/v1/message.proto"; +import "temporal/api_next/taskqueue/v1/message.proto"; +import "temporal/api_next/sdk/v1/user_metadata.proto"; // The outcome of a completed activity execution: either a successful result or a failure. message ActivityExecutionOutcome { diff --git a/temporal/api_next/batch/v1/message.proto b/temporal/api_next/batch/v1/message.proto index 63d3fafdb..74ec8e383 100644 --- a/temporal/api_next/batch/v1/message.proto +++ b/temporal/api_next/batch/v1/message.proto @@ -12,12 +12,12 @@ option csharp_namespace = "Temporalio.Api.Batch.V1"; import "google/protobuf/duration.proto"; import "google/protobuf/field_mask.proto"; import "google/protobuf/timestamp.proto"; -import "temporal/api/activity/v1/message.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/enums/v1/batch_operation.proto"; -import "temporal/api/enums/v1/reset.proto"; -import "temporal/api/rules/v1/message.proto"; -import "temporal/api/workflow/v1/message.proto"; +import "temporal/api_next/activity/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/enums/v1/batch_operation.proto"; +import "temporal/api_next/enums/v1/reset.proto"; +import "temporal/api_next/rules/v1/message.proto"; +import "temporal/api_next/workflow/v1/message.proto"; message BatchOperationInfo { // Batch job ID diff --git a/temporal/api_next/callback/v1/message.proto b/temporal/api_next/callback/v1/message.proto index f881a4eef..b62c1c9ca 100644 --- a/temporal/api_next/callback/v1/message.proto +++ b/temporal/api_next/callback/v1/message.proto @@ -11,9 +11,9 @@ option csharp_namespace = "Temporalio.Api.Callback.V1"; import "google/protobuf/timestamp.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/enums/v1/common.proto"; -import "temporal/api/failure/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/enums/v1/common.proto"; +import "temporal/api_next/failure/v1/message.proto"; // Common callback information. Specific CallbackInfo messages should embed this and may include additional fields. message CallbackInfo { diff --git a/temporal/api_next/command/v1/message.proto b/temporal/api_next/command/v1/message.proto index ee839115b..e9a70f686 100644 --- a/temporal/api_next/command/v1/message.proto +++ b/temporal/api_next/command/v1/message.proto @@ -11,14 +11,14 @@ option csharp_namespace = "Temporalio.Api.Command.V1"; import "google/protobuf/duration.proto"; -import "temporal/api/enums/v1/workflow.proto"; -import "temporal/api/enums/v1/command_type.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/failure/v1/message.proto"; -import "temporal/api/taskqueue/v1/message.proto"; -import "temporal/api/workflow/v1/message.proto"; -import "temporal/api/sdk/v1/user_metadata.proto"; -import "temporal/api/sdk/v1/event_group_marker.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; +import "temporal/api_next/enums/v1/command_type.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/failure/v1/message.proto"; +import "temporal/api_next/taskqueue/v1/message.proto"; +import "temporal/api_next/workflow/v1/message.proto"; +import "temporal/api_next/sdk/v1/user_metadata.proto"; +import "temporal/api_next/sdk/v1/event_group_marker.proto"; message ScheduleActivityTaskCommandAttributes { string activity_id = 1; diff --git a/temporal/api_next/common/v1/message.proto b/temporal/api_next/common/v1/message.proto index 3e2fc0e1c..c129f1e83 100644 --- a/temporal/api_next/common/v1/message.proto +++ b/temporal/api_next/common/v1/message.proto @@ -13,9 +13,9 @@ import "google/protobuf/duration.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; -import "temporal/api/enums/v1/common.proto"; -import "temporal/api/enums/v1/event_type.proto"; -import "temporal/api/enums/v1/reset.proto"; +import "temporal/api_next/enums/v1/common.proto"; +import "temporal/api_next/enums/v1/event_type.proto"; +import "temporal/api_next/enums/v1/reset.proto"; message DataBlob { temporal.api.enums.v1.EncodingType encoding_type = 1; diff --git a/temporal/api_next/compute/v1/config.proto b/temporal/api_next/compute/v1/config.proto index 998ead08b..6b406eb9e 100644 --- a/temporal/api_next/compute/v1/config.proto +++ b/temporal/api_next/compute/v1/config.proto @@ -9,9 +9,9 @@ option java_outer_classname = "ConfigProto"; option ruby_package = "Temporalio::Api::Compute::V1"; option csharp_namespace = "Temporalio.Api.Compute.V1"; -import "temporal/api/compute/v1/provider.proto"; -import "temporal/api/compute/v1/scaler.proto"; -import "temporal/api/enums/v1/task_queue.proto"; +import "temporal/api_next/compute/v1/provider.proto"; +import "temporal/api_next/compute/v1/scaler.proto"; +import "temporal/api_next/enums/v1/task_queue.proto"; import "google/protobuf/field_mask.proto"; message ComputeConfigScalingGroup { diff --git a/temporal/api_next/compute/v1/provider.proto b/temporal/api_next/compute/v1/provider.proto index ed0baf9d5..e801acc70 100644 --- a/temporal/api_next/compute/v1/provider.proto +++ b/temporal/api_next/compute/v1/provider.proto @@ -9,7 +9,7 @@ option java_outer_classname = "ProviderProto"; option ruby_package = "Temporalio::Api::Compute::V1"; option csharp_namespace = "Temporalio.Api.Compute.V1"; -import "temporal/api/common/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; // ComputeProvider stores information used by a worker control plane controller // to respond to worker lifecycle events. For example, when a Task is received diff --git a/temporal/api_next/compute/v1/scaler.proto b/temporal/api_next/compute/v1/scaler.proto index ecce95f1b..a97b2d187 100644 --- a/temporal/api_next/compute/v1/scaler.proto +++ b/temporal/api_next/compute/v1/scaler.proto @@ -9,7 +9,7 @@ option java_outer_classname = "ScalerProto"; option ruby_package = "Temporalio::Api::Compute::V1"; option csharp_namespace = "Temporalio.Api.Compute.V1"; -import "temporal/api/common/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; // ComputeScaler instructs the Temporal Service when to scale up or down the number of // Workers that comprise a WorkerDeployment. diff --git a/temporal/api_next/deployment/v1/message.proto b/temporal/api_next/deployment/v1/message.proto index eaa465966..9ee1b369c 100644 --- a/temporal/api_next/deployment/v1/message.proto +++ b/temporal/api_next/deployment/v1/message.proto @@ -11,11 +11,11 @@ option csharp_namespace = "Temporalio.Api.Deployment.V1"; import "google/protobuf/timestamp.proto"; -import "temporal/api/enums/v1/workflow.proto"; -import "temporal/api/enums/v1/deployment.proto"; -import "temporal/api/enums/v1/task_queue.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/compute/v1/config.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; +import "temporal/api_next/enums/v1/deployment.proto"; +import "temporal/api_next/enums/v1/task_queue.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/compute/v1/config.proto"; // Worker Deployment options set in SDK that need to be sent to server in every poll. message WorkerDeploymentOptions { diff --git a/temporal/api_next/errordetails/v1/message.proto b/temporal/api_next/errordetails/v1/message.proto index 7d8ed6b1b..57d5c7121 100644 --- a/temporal/api_next/errordetails/v1/message.proto +++ b/temporal/api_next/errordetails/v1/message.proto @@ -13,11 +13,11 @@ option ruby_package = "Temporalio::Api::ErrorDetails::V1"; option csharp_namespace = "Temporalio.Api.ErrorDetails.V1"; import "google/protobuf/any.proto"; -import "temporal/api/common/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; -import "temporal/api/enums/v1/failed_cause.proto"; -import "temporal/api/enums/v1/namespace.proto"; -import "temporal/api/failure/v1/message.proto"; +import "temporal/api_next/enums/v1/failed_cause.proto"; +import "temporal/api_next/enums/v1/namespace.proto"; +import "temporal/api_next/failure/v1/message.proto"; message NotFoundFailure { string current_cluster = 1; diff --git a/temporal/api_next/export/v1/message.proto b/temporal/api_next/export/v1/message.proto index 8673bfd23..168f73f88 100644 --- a/temporal/api_next/export/v1/message.proto +++ b/temporal/api_next/export/v1/message.proto @@ -9,7 +9,7 @@ option java_outer_classname = "MessageProto"; option ruby_package = "Temporalio::Api::Export::V1"; option csharp_namespace = "Temporalio.Api.Export.V1"; -import "temporal/api/history/v1/message.proto"; +import "temporal/api_next/history/v1/message.proto"; message WorkflowExecution { temporal.api.history.v1.History history = 1; diff --git a/temporal/api_next/failure/v1/message.proto b/temporal/api_next/failure/v1/message.proto index a8634dc93..bd182f30c 100644 --- a/temporal/api_next/failure/v1/message.proto +++ b/temporal/api_next/failure/v1/message.proto @@ -9,10 +9,10 @@ option java_outer_classname = "MessageProto"; option ruby_package = "Temporalio::Api::Failure::V1"; option csharp_namespace = "Temporalio.Api.Failure.V1"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/enums/v1/workflow.proto"; -import "temporal/api/enums/v1/nexus.proto"; -import "temporal/api/enums/v1/common.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; +import "temporal/api_next/enums/v1/nexus.proto"; +import "temporal/api_next/enums/v1/common.proto"; import "google/protobuf/duration.proto"; diff --git a/temporal/api_next/filter/v1/message.proto b/temporal/api_next/filter/v1/message.proto index a3d4a4dd0..47763283a 100644 --- a/temporal/api_next/filter/v1/message.proto +++ b/temporal/api_next/filter/v1/message.proto @@ -11,7 +11,7 @@ option csharp_namespace = "Temporalio.Api.Filter.V1"; import "google/protobuf/timestamp.proto"; -import "temporal/api/enums/v1/workflow.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; message WorkflowExecutionFilter { string workflow_id = 1; diff --git a/temporal/api_next/history/v1/message.proto b/temporal/api_next/history/v1/message.proto index 0211c6f55..16706b6ad 100644 --- a/temporal/api_next/history/v1/message.proto +++ b/temporal/api_next/history/v1/message.proto @@ -12,19 +12,19 @@ option csharp_namespace = "Temporalio.Api.History.V1"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "temporal/api/enums/v1/event_type.proto"; -import "temporal/api/enums/v1/failed_cause.proto"; -import "temporal/api/enums/v1/update.proto"; -import "temporal/api/enums/v1/workflow.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/deployment/v1/message.proto"; -import "temporal/api/failure/v1/message.proto"; -import "temporal/api/taskqueue/v1/message.proto"; -import "temporal/api/update/v1/message.proto"; -import "temporal/api/workflow/v1/message.proto"; -import "temporal/api/sdk/v1/task_complete_metadata.proto"; -import "temporal/api/sdk/v1/user_metadata.proto"; -import "temporal/api/sdk/v1/event_group_marker.proto"; +import "temporal/api_next/enums/v1/event_type.proto"; +import "temporal/api_next/enums/v1/failed_cause.proto"; +import "temporal/api_next/enums/v1/update.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/deployment/v1/message.proto"; +import "temporal/api_next/failure/v1/message.proto"; +import "temporal/api_next/taskqueue/v1/message.proto"; +import "temporal/api_next/update/v1/message.proto"; +import "temporal/api_next/workflow/v1/message.proto"; +import "temporal/api_next/sdk/v1/task_complete_metadata.proto"; +import "temporal/api_next/sdk/v1/user_metadata.proto"; +import "temporal/api_next/sdk/v1/event_group_marker.proto"; // Always the first event in workflow history message WorkflowExecutionStartedEventAttributes { diff --git a/temporal/api_next/namespace/v1/message.proto b/temporal/api_next/namespace/v1/message.proto index a80566458..2417d92fb 100644 --- a/temporal/api_next/namespace/v1/message.proto +++ b/temporal/api_next/namespace/v1/message.proto @@ -12,7 +12,7 @@ option csharp_namespace = "Temporalio.Api.Namespace.V1"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "temporal/api/enums/v1/namespace.proto"; +import "temporal/api_next/enums/v1/namespace.proto"; message NamespaceInfo { diff --git a/temporal/api_next/nexus/v1/message.proto b/temporal/api_next/nexus/v1/message.proto index a4e400c29..4d67edb66 100644 --- a/temporal/api_next/nexus/v1/message.proto +++ b/temporal/api_next/nexus/v1/message.proto @@ -11,11 +11,12 @@ option csharp_namespace = "Temporalio.Api.Nexus.V1"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/enums/v1/common.proto"; -import "temporal/api/enums/v1/nexus.proto"; -import "temporal/api/failure/v1/message.proto"; -import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/enums/v1/common.proto"; +import "temporal/api_next/enums/v1/nexus.proto"; +import "temporal/api_next/failure/v1/message.proto"; +import "temporal/api_next/sdk/v1/user_metadata.proto"; +import "temporal/api_next/protometa/v1/experimental.proto"; // A general purpose failure message. // See: https://github.com/nexus-rpc/api/blob/main/SPEC.md#failure @@ -332,6 +333,8 @@ message NexusOperationExecutionInfo { // Updated once on scheduled and once on terminal status. int64 state_size_bytes = 29; + + string tag = 30 [(temporal.api.protometa.v1.experimental) = "nexus-operation-tags"]; } // Limited Nexus operation information returned in the list response. diff --git a/temporal/api_next/nexusservices/workerservice/v1/request_response.proto b/temporal/api_next/nexusservices/workerservice/v1/request_response.proto index e5b46e7ce..42cd78538 100644 --- a/temporal/api_next/nexusservices/workerservice/v1/request_response.proto +++ b/temporal/api_next/nexusservices/workerservice/v1/request_response.proto @@ -9,7 +9,7 @@ option java_outer_classname = "RequestResponseProto"; option ruby_package = "Temporalio::Api::Nexusservices::Workerservice::V1"; option csharp_namespace = "Temporalio.Api.Nexusservices.Workerservice.V1"; -import "temporal/api/worker/v1/message.proto"; +import "temporal/api_next/worker/v1/message.proto"; // (-- // Internal Nexus service for server-to-worker communication. diff --git a/temporal/api_next/operatorservice/v1/request_response.proto b/temporal/api_next/operatorservice/v1/request_response.proto index f4a74b331..1f8690f94 100644 --- a/temporal/api_next/operatorservice/v1/request_response.proto +++ b/temporal/api_next/operatorservice/v1/request_response.proto @@ -9,8 +9,8 @@ option java_outer_classname = "RequestResponseProto"; option ruby_package = "Temporalio::Api::OperatorService::V1"; option csharp_namespace = "Temporalio.Api.OperatorService.V1"; -import "temporal/api/enums/v1/common.proto"; -import "temporal/api/nexus/v1/message.proto"; +import "temporal/api_next/enums/v1/common.proto"; +import "temporal/api_next/nexus/v1/message.proto"; import "google/protobuf/duration.proto"; // (-- Search Attribute --) diff --git a/temporal/api_next/operatorservice/v1/service.proto b/temporal/api_next/operatorservice/v1/service.proto index bcf5ab04b..443a5d2d9 100644 --- a/temporal/api_next/operatorservice/v1/service.proto +++ b/temporal/api_next/operatorservice/v1/service.proto @@ -10,7 +10,7 @@ option ruby_package = "Temporalio::Api::OperatorService::V1"; option csharp_namespace = "Temporalio.Api.OperatorService.V1"; -import "temporal/api/operatorservice/v1/request_response.proto"; +import "temporal/api_next/operatorservice/v1/request_response.proto"; import "google/api/annotations.proto"; // OperatorService API defines how Temporal SDKs and other clients interact with the Temporal server diff --git a/temporal/api_next/protometa/v1/annotations.proto b/temporal/api_next/protometa/v1/annotations.proto index 483ffd676..85594a555 100644 --- a/temporal/api_next/protometa/v1/annotations.proto +++ b/temporal/api_next/protometa/v1/annotations.proto @@ -34,4 +34,4 @@ message RequestHeaderAnnotation { // Multiple headers can be set by repeating this option. extend google.protobuf.MethodOptions { repeated RequestHeaderAnnotation request_header = 7234001; -} \ No newline at end of file +} diff --git a/temporal/api_next/protometa/v1/experimental.proto b/temporal/api_next/protometa/v1/experimental.proto new file mode 100644 index 000000000..3a4c2a3ab --- /dev/null +++ b/temporal/api_next/protometa/v1/experimental.proto @@ -0,0 +1,38 @@ +syntax = "proto3"; + +package temporal.api.protometa.v1; + +option go_package = "go.temporal.io/api/protometa/v1;protometa"; +option java_package = "io.temporal.api.protometa.v1"; +option java_multiple_files = true; +option java_outer_classname = "ExperimentalProto"; +option ruby_package = "Temporalio::Api::Protometa::V1"; +option csharp_namespace = "Temporalio.Api.Protometa.V1"; + +import "google/protobuf/descriptor.proto"; + +// Tags for experimental/draft declarations. + +extend google.protobuf.FieldOptions { + string experimental = 95134; +} + +extend google.protobuf.MessageOptions { + string experimental_message = 95135; +} + +extend google.protobuf.EnumOptions { + string experimental_enum = 95136; +} + +extend google.protobuf.EnumValueOptions { + string experimental_enum_value = 95137; +} + +extend google.protobuf.ServiceOptions { + string experimental_service = 95138; +} + +extend google.protobuf.MethodOptions { + string experimental_method = 95139; +} diff --git a/temporal/api_next/query/v1/message.proto b/temporal/api_next/query/v1/message.proto index d144471f4..d504fd23a 100644 --- a/temporal/api_next/query/v1/message.proto +++ b/temporal/api_next/query/v1/message.proto @@ -9,10 +9,10 @@ option java_outer_classname = "MessageProto"; option ruby_package = "Temporalio::Api::Query::V1"; option csharp_namespace = "Temporalio.Api.Query.V1"; -import "temporal/api/enums/v1/query.proto"; -import "temporal/api/enums/v1/workflow.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/failure/v1/message.proto"; +import "temporal/api_next/enums/v1/query.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/failure/v1/message.proto"; // See https://docs.temporal.io/docs/concepts/queries/ message WorkflowQuery { diff --git a/temporal/api_next/replication/v1/message.proto b/temporal/api_next/replication/v1/message.proto index 0c2f614eb..7df71a900 100644 --- a/temporal/api_next/replication/v1/message.proto +++ b/temporal/api_next/replication/v1/message.proto @@ -11,7 +11,7 @@ option csharp_namespace = "Temporalio.Api.Replication.V1"; import "google/protobuf/timestamp.proto"; -import "temporal/api/enums/v1/namespace.proto"; +import "temporal/api_next/enums/v1/namespace.proto"; message ClusterReplicationConfig { string cluster_name = 1; diff --git a/temporal/api_next/schedule/v1/message.proto b/temporal/api_next/schedule/v1/message.proto index 3a0a9344c..38f4c89aa 100644 --- a/temporal/api_next/schedule/v1/message.proto +++ b/temporal/api_next/schedule/v1/message.proto @@ -17,10 +17,10 @@ option csharp_namespace = "Temporalio.Api.Schedule.V1"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/enums/v1/schedule.proto"; -import "temporal/api/enums/v1/workflow.proto"; -import "temporal/api/workflow/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/enums/v1/schedule.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; +import "temporal/api_next/workflow/v1/message.proto"; // CalendarSpec describes an event specification relative to the calendar, // similar to a traditional cron specification, but with labeled fields. Each diff --git a/temporal/api_next/sdk/v1/event_group_marker.proto b/temporal/api_next/sdk/v1/event_group_marker.proto index c16922d4a..79b838ba0 100644 --- a/temporal/api_next/sdk/v1/event_group_marker.proto +++ b/temporal/api_next/sdk/v1/event_group_marker.proto @@ -10,7 +10,7 @@ option ruby_package = "Temporalio::Api::Sdk::V1"; option csharp_namespace = "Temporalio.Api.Sdk.V1"; -import "temporal/api/common/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; message EventGroupMarker { // What this Marker represents. The variant determines whether the Marker was diff --git a/temporal/api_next/sdk/v1/user_metadata.proto b/temporal/api_next/sdk/v1/user_metadata.proto index 9081fac1c..278fc41b8 100644 --- a/temporal/api_next/sdk/v1/user_metadata.proto +++ b/temporal/api_next/sdk/v1/user_metadata.proto @@ -10,7 +10,7 @@ option ruby_package = "Temporalio::Api::Sdk::V1"; option csharp_namespace = "Temporalio.Api.Sdk.V1"; -import "temporal/api/common/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; // Information a user can set, often for use by user interfaces. message UserMetadata { diff --git a/temporal/api_next/taskqueue/v1/message.proto b/temporal/api_next/taskqueue/v1/message.proto index 6ab668fdb..1247539c7 100644 --- a/temporal/api_next/taskqueue/v1/message.proto +++ b/temporal/api_next/taskqueue/v1/message.proto @@ -13,9 +13,9 @@ import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/wrappers.proto"; -import "temporal/api/enums/v1/task_queue.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/deployment/v1/message.proto"; +import "temporal/api_next/enums/v1/task_queue.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/deployment/v1/message.proto"; // See https://docs.temporal.io/docs/concepts/task-queues/ message TaskQueue { diff --git a/temporal/api_next/update/v1/message.proto b/temporal/api_next/update/v1/message.proto index 76c46d47d..f87a7d9a3 100644 --- a/temporal/api_next/update/v1/message.proto +++ b/temporal/api_next/update/v1/message.proto @@ -9,9 +9,9 @@ option java_outer_classname = "MessageProto"; option ruby_package = "Temporalio::Api::Update::V1"; option csharp_namespace = "Temporalio.Api.Update.V1"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/enums/v1/update.proto"; -import "temporal/api/failure/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/enums/v1/update.proto"; +import "temporal/api_next/failure/v1/message.proto"; // Specifies client's intent to wait for Update results. message WaitPolicy { diff --git a/temporal/api_next/version/v1/message.proto b/temporal/api_next/version/v1/message.proto index 6661a3a8c..b427d5128 100644 --- a/temporal/api_next/version/v1/message.proto +++ b/temporal/api_next/version/v1/message.proto @@ -10,7 +10,7 @@ option ruby_package = "Temporalio::Api::Version::V1"; option csharp_namespace = "Temporalio.Api.Version.V1"; import "google/protobuf/timestamp.proto"; -import "temporal/api/enums/v1/common.proto"; +import "temporal/api_next/enums/v1/common.proto"; // ReleaseInfo contains information about specific version of temporal. message ReleaseInfo { diff --git a/temporal/api_next/worker/v1/message.proto b/temporal/api_next/worker/v1/message.proto index 05c9e5b45..34d3f77d4 100644 --- a/temporal/api_next/worker/v1/message.proto +++ b/temporal/api_next/worker/v1/message.proto @@ -11,8 +11,8 @@ option csharp_namespace = "Temporalio.Api.Worker.V1"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "temporal/api/deployment/v1/message.proto"; -import "temporal/api/enums/v1/common.proto"; +import "temporal/api_next/deployment/v1/message.proto"; +import "temporal/api_next/enums/v1/common.proto"; message WorkerPollerInfo { // Number of polling RPCs that are currently in flight. diff --git a/temporal/api_next/workflow/v1/message.proto b/temporal/api_next/workflow/v1/message.proto index 1ed33fa4c..23f03a7c3 100644 --- a/temporal/api_next/workflow/v1/message.proto +++ b/temporal/api_next/workflow/v1/message.proto @@ -14,15 +14,15 @@ import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/field_mask.proto"; -import "temporal/api/activity/v1/message.proto"; -import "temporal/api/enums/v1/common.proto"; -import "temporal/api/enums/v1/event_type.proto"; -import "temporal/api/enums/v1/workflow.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/deployment/v1/message.proto"; -import "temporal/api/failure/v1/message.proto"; -import "temporal/api/taskqueue/v1/message.proto"; -import "temporal/api/sdk/v1/user_metadata.proto"; +import "temporal/api_next/activity/v1/message.proto"; +import "temporal/api_next/enums/v1/common.proto"; +import "temporal/api_next/enums/v1/event_type.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/deployment/v1/message.proto"; +import "temporal/api_next/failure/v1/message.proto"; +import "temporal/api_next/taskqueue/v1/message.proto"; +import "temporal/api_next/sdk/v1/user_metadata.proto"; // Hold basic information about a workflow execution. diff --git a/temporal/api_next/workflowservice/v1/request_response.proto b/temporal/api_next/workflowservice/v1/request_response.proto index c3dd95769..47b790688 100644 --- a/temporal/api_next/workflowservice/v1/request_response.proto +++ b/temporal/api_next/workflowservice/v1/request_response.proto @@ -9,43 +9,43 @@ option java_outer_classname = "RequestResponseProto"; option ruby_package = "Temporalio::Api::WorkflowService::V1"; option csharp_namespace = "Temporalio.Api.WorkflowService.V1"; -import "temporal/api/enums/v1/batch_operation.proto"; -import "temporal/api/enums/v1/common.proto"; -import "temporal/api/enums/v1/workflow.proto"; -import "temporal/api/enums/v1/namespace.proto"; -import "temporal/api/enums/v1/failed_cause.proto"; -import "temporal/api/enums/v1/query.proto"; -import "temporal/api/enums/v1/reset.proto"; -import "temporal/api/enums/v1/task_queue.proto"; -import "temporal/api/enums/v1/deployment.proto"; -import "temporal/api/enums/v1/update.proto"; -import "temporal/api/enums/v1/time_skipping.proto"; -import "temporal/api/enums/v1/activity.proto"; -import "temporal/api/enums/v1/nexus.proto"; -import "temporal/api/activity/v1/message.proto"; -import "temporal/api/common/v1/message.proto"; -import "temporal/api/history/v1/message.proto"; -import "temporal/api/workflow/v1/message.proto"; -import "temporal/api/command/v1/message.proto"; -import "temporal/api/compute/v1/config.proto"; -import "temporal/api/deployment/v1/message.proto"; -import "temporal/api/failure/v1/message.proto"; -import "temporal/api/filter/v1/message.proto"; -import "temporal/api/protocol/v1/message.proto"; -import "temporal/api/namespace/v1/message.proto"; -import "temporal/api/query/v1/message.proto"; -import "temporal/api/replication/v1/message.proto"; -import "temporal/api/rules/v1/message.proto"; -import "temporal/api/sdk/v1/worker_config.proto"; -import "temporal/api/schedule/v1/message.proto"; -import "temporal/api/taskqueue/v1/message.proto"; -import "temporal/api/update/v1/message.proto"; -import "temporal/api/version/v1/message.proto"; -import "temporal/api/batch/v1/message.proto"; -import "temporal/api/sdk/v1/task_complete_metadata.proto"; -import "temporal/api/sdk/v1/user_metadata.proto"; -import "temporal/api/nexus/v1/message.proto"; -import "temporal/api/worker/v1/message.proto"; +import "temporal/api_next/enums/v1/batch_operation.proto"; +import "temporal/api_next/enums/v1/common.proto"; +import "temporal/api_next/enums/v1/workflow.proto"; +import "temporal/api_next/enums/v1/namespace.proto"; +import "temporal/api_next/enums/v1/failed_cause.proto"; +import "temporal/api_next/enums/v1/query.proto"; +import "temporal/api_next/enums/v1/reset.proto"; +import "temporal/api_next/enums/v1/task_queue.proto"; +import "temporal/api_next/enums/v1/deployment.proto"; +import "temporal/api_next/enums/v1/update.proto"; +import "temporal/api_next/enums/v1/time_skipping.proto"; +import "temporal/api_next/enums/v1/activity.proto"; +import "temporal/api_next/enums/v1/nexus.proto"; +import "temporal/api_next/activity/v1/message.proto"; +import "temporal/api_next/common/v1/message.proto"; +import "temporal/api_next/history/v1/message.proto"; +import "temporal/api_next/workflow/v1/message.proto"; +import "temporal/api_next/command/v1/message.proto"; +import "temporal/api_next/compute/v1/config.proto"; +import "temporal/api_next/deployment/v1/message.proto"; +import "temporal/api_next/failure/v1/message.proto"; +import "temporal/api_next/filter/v1/message.proto"; +import "temporal/api_next/protocol/v1/message.proto"; +import "temporal/api_next/namespace/v1/message.proto"; +import "temporal/api_next/query/v1/message.proto"; +import "temporal/api_next/replication/v1/message.proto"; +import "temporal/api_next/rules/v1/message.proto"; +import "temporal/api_next/sdk/v1/worker_config.proto"; +import "temporal/api_next/schedule/v1/message.proto"; +import "temporal/api_next/taskqueue/v1/message.proto"; +import "temporal/api_next/update/v1/message.proto"; +import "temporal/api_next/version/v1/message.proto"; +import "temporal/api_next/batch/v1/message.proto"; +import "temporal/api_next/sdk/v1/task_complete_metadata.proto"; +import "temporal/api_next/sdk/v1/user_metadata.proto"; +import "temporal/api_next/nexus/v1/message.proto"; +import "temporal/api_next/worker/v1/message.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/field_mask.proto"; diff --git a/temporal/api_next/workflowservice/v1/service.proto b/temporal/api_next/workflowservice/v1/service.proto index 768553bd9..6a0d793c8 100644 --- a/temporal/api_next/workflowservice/v1/service.proto +++ b/temporal/api_next/workflowservice/v1/service.proto @@ -12,8 +12,8 @@ option csharp_namespace = "Temporalio.Api.WorkflowService.V1"; import "google/api/annotations.proto"; import "nexusannotations/v1/options.proto"; -import "temporal/api/protometa/v1/annotations.proto"; -import "temporal/api/workflowservice/v1/request_response.proto"; +import "temporal/api_next/protometa/v1/annotations.proto"; +import "temporal/api_next/workflowservice/v1/request_response.proto"; // WorkflowService API defines how Temporal SDKs and other clients interact with the Temporal server // to create and interact with workflows and activities.