From e0de7a764b254d4eb13580df5ed0b9b4881fda00 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Tue, 27 Oct 2026 16:16:12 -0400 Subject: [PATCH] Add RPC definitions for namespace soft deletion and restoration --- openapi/openapiv2.json | 6 ++- openapi/openapiv3.yaml | 2 + temporal/api/enums/v1/namespace.proto | 11 +++++ .../operatorservice/v1/request_response.proto | 42 +++++++++++++++++++ temporal/api/operatorservice/v1/service.proto | 17 ++++++++ 5 files changed, 76 insertions(+), 2 deletions(-) diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index 917fce76c..3b8f66cff 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -16482,9 +16482,11 @@ "NAMESPACE_STATE_UNSPECIFIED", "NAMESPACE_STATE_REGISTERED", "NAMESPACE_STATE_DEPRECATED", - "NAMESPACE_STATE_DELETED" + "NAMESPACE_STATE_DELETED", + "NAMESPACE_STATE_SOFT_DELETED" ], - "default": "NAMESPACE_STATE_UNSPECIFIED" + "default": "NAMESPACE_STATE_UNSPECIFIED", + "description": " - NAMESPACE_STATE_SOFT_DELETED: Set by OperatorService.SoftDeleteNamespace. Executions make no progress, but no data is\nremoved until the namespace is restored or deleted." }, "v1NewWorkflowExecutionInfo": { "type": "object", diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index 4ada710f0..176bc6d3a 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -12860,6 +12860,7 @@ components: - NAMESPACE_STATE_REGISTERED - NAMESPACE_STATE_DEPRECATED - NAMESPACE_STATE_DELETED + - NAMESPACE_STATE_SOFT_DELETED type: string format: enum description: @@ -17544,6 +17545,7 @@ components: - NAMESPACE_STATE_REGISTERED - NAMESPACE_STATE_DEPRECATED - NAMESPACE_STATE_DELETED + - NAMESPACE_STATE_SOFT_DELETED type: string description: |- New namespace state, server will reject if transition is not allowed. diff --git a/temporal/api/enums/v1/namespace.proto b/temporal/api/enums/v1/namespace.proto index d55c086d8..9babc3310 100644 --- a/temporal/api/enums/v1/namespace.proto +++ b/temporal/api/enums/v1/namespace.proto @@ -14,6 +14,17 @@ enum NamespaceState { NAMESPACE_STATE_REGISTERED = 1; NAMESPACE_STATE_DEPRECATED = 2; NAMESPACE_STATE_DELETED = 3; + // Set by OperatorService.SoftDeleteNamespace. Executions make no progress, but no data is + // removed until the namespace is restored or deleted. + NAMESPACE_STATE_SOFT_DELETED = 4; +} + +// State of a restore started by OperatorService.RestoreNamespace. +enum NamespaceRestoreState { + NAMESPACE_RESTORE_STATE_UNSPECIFIED = 0; + NAMESPACE_RESTORE_STATE_RUNNING = 1; + NAMESPACE_RESTORE_STATE_COMPLETED = 2; + NAMESPACE_RESTORE_STATE_FAILED = 3; } enum ArchivalState { diff --git a/temporal/api/operatorservice/v1/request_response.proto b/temporal/api/operatorservice/v1/request_response.proto index f4a74b331..bb0efde79 100644 --- a/temporal/api/operatorservice/v1/request_response.proto +++ b/temporal/api/operatorservice/v1/request_response.proto @@ -10,8 +10,10 @@ option ruby_package = "Temporalio::Api::OperatorService::V1"; option csharp_namespace = "Temporalio.Api.OperatorService.V1"; import "temporal/api/enums/v1/common.proto"; +import "temporal/api/enums/v1/namespace.proto"; import "temporal/api/nexus/v1/message.proto"; import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; // (-- Search Attribute --) @@ -60,6 +62,46 @@ message DeleteNamespaceResponse { string deleted_namespace = 1; } +message SoftDeleteNamespaceRequest { + // Only one of namespace or namespace_id must be specified to identify namespace. + string namespace = 1; + string namespace_id = 2; +} + +message SoftDeleteNamespaceResponse { +} + +message RestoreNamespaceRequest { + // Only one of namespace or namespace_id must be specified to identify namespace. + string namespace = 1; + string namespace_id = 2; +} + +message RestoreNamespaceResponse { +} + +message DescribeNamespaceRestoreRequest { + // Only one of namespace or namespace_id must be specified to identify namespace. + string namespace = 1; + string namespace_id = 2; +} + +message DescribeNamespaceRestoreResponse { + temporal.api.enums.v1.NamespaceRestoreState state = 1; + // Cluster that runs the restore job. + string host_cluster = 2; + google.protobuf.Timestamp start_time = 3; + // Unset while the restore is running. + google.protobuf.Timestamp close_time = 4; + // Run ID of the restore job. + string run_id = 5; + // Estimated when the refresh starts. + int64 total_execution_count = 6; + // Executions processed on every cluster. + int64 processed_execution_count = 7; + google.protobuf.Timestamp estimated_completion_time = 8; +} + message AddOrUpdateRemoteClusterRequest { // Frontend Address is a cross cluster accessible address for gRPC traffic. This field is required. string frontend_address = 1; diff --git a/temporal/api/operatorservice/v1/service.proto b/temporal/api/operatorservice/v1/service.proto index bcf5ab04b..f5428a148 100644 --- a/temporal/api/operatorservice/v1/service.proto +++ b/temporal/api/operatorservice/v1/service.proto @@ -47,6 +47,23 @@ service OperatorService { rpc DeleteNamespace (DeleteNamespaceRequest) returns (DeleteNamespaceResponse) { } + // SoftDeleteNamespace moves a namespace to NAMESPACE_STATE_SOFT_DELETED on every cluster in its + // replication config. Executions stop making progress, but no data is removed. A running restore + // is marked failed. Idempotent. + rpc SoftDeleteNamespace (SoftDeleteNamespaceRequest) returns (SoftDeleteNamespaceResponse) { + } + + // RestoreNamespace moves a soft-deleted namespace back to NAMESPACE_STATE_REGISTERED on every + // cluster in its replication config, then starts a job that refreshes every execution so they + // resume. Returns UNAVAILABLE until every cluster has the new state; retry until it succeeds. + // Idempotent. + rpc RestoreNamespace (RestoreNamespaceRequest) returns (RestoreNamespaceResponse) { + } + + // DescribeNamespaceRestore reports the state and progress of the namespace's most recent restore. + rpc DescribeNamespaceRestore (DescribeNamespaceRestoreRequest) returns (DescribeNamespaceRestoreResponse) { + } + // AddOrUpdateRemoteCluster adds or updates remote cluster. rpc AddOrUpdateRemoteCluster(AddOrUpdateRemoteClusterRequest) returns (AddOrUpdateRemoteClusterResponse) { }