Skip to content

Commit

Permalink
Allow delete namespace by Id (#2643)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexshtin committed Mar 25, 2022
1 parent f0d20df commit 82ab54f
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 20 deletions.
18 changes: 14 additions & 4 deletions service/worker/deletenamespace/activities.go
Expand Up @@ -32,6 +32,7 @@ import (

enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/api/serviceerror"
"go.temporal.io/sdk/temporal"

"go.temporal.io/server/common/log"
"go.temporal.io/server/common/log/tag"
Expand All @@ -46,6 +47,11 @@ type (
metricsClient metrics.Client
logger log.Logger
}

getNamespaceInfoResult struct {
NamespaceID namespace.ID
Namespace namespace.Name
}
)

func NewActivities(
Expand All @@ -60,21 +66,25 @@ func NewActivities(
}
}

func (a *activities) GetNamespaceIDActivity(ctx context.Context, nsName namespace.Name) (namespace.ID, error) {
func (a *activities) GetNamespaceInfoActivity(ctx context.Context, nsID namespace.ID, nsName namespace.Name) (getNamespaceInfoResult, error) {
getNamespaceRequest := &persistence.GetNamespaceRequest{
Name: nsName.String(),
ID: nsID.String(),
}

getNamespaceResponse, err := a.metadataManager.GetNamespace(ctx, getNamespaceRequest)
if err != nil {
return namespace.EmptyID, err
return getNamespaceInfoResult{}, err
}

if getNamespaceResponse.Namespace == nil || getNamespaceResponse.Namespace.Info == nil || getNamespaceResponse.Namespace.Info.Id == "" {
return namespace.EmptyID, serviceerror.NewInternal("namespace info is corrupted")
return getNamespaceInfoResult{}, temporal.NewNonRetryableApplicationError("namespace info is corrupted", "", nil)
}

return namespace.ID(getNamespaceResponse.Namespace.Info.Id), nil
return getNamespaceInfoResult{
NamespaceID: namespace.ID(getNamespaceResponse.Namespace.Info.Id),
Namespace: namespace.Name(getNamespaceResponse.Namespace.Info.Name),
}, nil
}

func (a *activities) MarkNamespaceDeletedActivity(ctx context.Context, nsName namespace.Name) error {
Expand Down
4 changes: 2 additions & 2 deletions service/worker/deletenamespace/deleteexecutions/workflow.go
Expand Up @@ -78,11 +78,11 @@ var (

func validateParams(params *DeleteExecutionsParams) error {
if params.NamespaceID.IsEmpty() {
return temporal.NewNonRetryableApplicationError("namespace ID is empty", "", nil)
return temporal.NewNonRetryableApplicationError("namespace ID is required", "", nil)
}

if params.Namespace.IsEmpty() {
return temporal.NewNonRetryableApplicationError("namespace is empty", "", nil)
return temporal.NewNonRetryableApplicationError("namespace is required", "", nil)
}

params.Config.ApplyDefaults()
Expand Down
4 changes: 2 additions & 2 deletions service/worker/deletenamespace/reclaimresources/workflow.go
Expand Up @@ -73,11 +73,11 @@ var (

func validateParams(params *ReclaimResourcesParams) error {
if params.NamespaceID.IsEmpty() {
return temporal.NewNonRetryableApplicationError("namespace ID is empty", "", nil)
return temporal.NewNonRetryableApplicationError("namespace ID is required", "", nil)
}

if params.Namespace.IsEmpty() {
return temporal.NewNonRetryableApplicationError("namespace is empty", "", nil)
return temporal.NewNonRetryableApplicationError("namespace is required", "", nil)
}

params.Config.ApplyDefaults()
Expand Down
27 changes: 17 additions & 10 deletions service/worker/deletenamespace/workflow.go
Expand Up @@ -48,6 +48,7 @@ const (

type (
DeleteNamespaceWorkflowParams struct {
// One of NamespaceID or Namespace must be provided.
NamespaceID namespace.ID
Namespace namespace.Name

Expand Down Expand Up @@ -81,7 +82,11 @@ var (

func validateParams(params *DeleteNamespaceWorkflowParams) error {
if params.Namespace.IsEmpty() && params.NamespaceID.IsEmpty() {
return temporal.NewNonRetryableApplicationError("both namespace name and namespace ID are empty", "", nil)
return temporal.NewNonRetryableApplicationError("namespace or namespace ID is required", "", nil)
}

if !params.Namespace.IsEmpty() && !params.NamespaceID.IsEmpty() {
return temporal.NewNonRetryableApplicationError("only one of namespace or namespace ID must be set", "", nil)
}

params.DeleteExecutionsConfig.ApplyDefaults()
Expand All @@ -101,23 +106,25 @@ func DeleteNamespaceWorkflow(ctx workflow.Context, params DeleteNamespaceWorkflo

var a *activities

// Step 1. Get namespaceID.
if params.NamespaceID.IsEmpty() {
ctx1 := workflow.WithLocalActivityOptions(ctx, localActivityOptions)
err := workflow.ExecuteLocalActivity(ctx1, a.GetNamespaceIDActivity, params.Namespace).Get(ctx, &params.NamespaceID)
if err != nil {
return result, temporal.NewNonRetryableApplicationError(fmt.Sprintf("namespace %s is not found", params.Namespace), "", err)
}
// Step 1. Get namespace info.
ctx1 := workflow.WithLocalActivityOptions(ctx, localActivityOptions)
var namespaceInfo getNamespaceInfoResult
err := workflow.ExecuteLocalActivity(ctx1, a.GetNamespaceInfoActivity, params.NamespaceID, params.Namespace).Get(ctx, &namespaceInfo)
if err != nil {
return result, temporal.NewNonRetryableApplicationError(fmt.Sprintf("namespace %s is not found", params.Namespace), "", err)
}
result.DeletedID = params.NamespaceID
params.Namespace = namespaceInfo.Namespace
params.NamespaceID = namespaceInfo.NamespaceID

// Step 2. Mark namespace as deleted.
ctx2 := workflow.WithLocalActivityOptions(ctx, localActivityOptions)
err := workflow.ExecuteLocalActivity(ctx2, a.MarkNamespaceDeletedActivity, params.Namespace).Get(ctx, nil)
err = workflow.ExecuteLocalActivity(ctx2, a.MarkNamespaceDeletedActivity, params.Namespace).Get(ctx, nil)
if err != nil {
return result, fmt.Errorf("%w: MarkNamespaceDeletedActivity: %v", errors.ErrUnableToExecuteActivity, err)
}

result.DeletedID = params.NamespaceID

// Step 3. Rename namespace.
ctx3 := workflow.WithLocalActivityOptions(ctx, localActivityOptions)
err = workflow.ExecuteLocalActivity(ctx3, a.GenerateDeletedNamespaceNameActivity, params.Namespace).Get(ctx, &result.DeletedName)
Expand Down
72 changes: 70 additions & 2 deletions service/worker/deletenamespace/workflow_test.go
Expand Up @@ -29,20 +29,25 @@ import (

"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.temporal.io/sdk/temporal"
"go.temporal.io/sdk/testsuite"

"go.temporal.io/server/common/namespace"
"go.temporal.io/server/service/worker/deletenamespace/deleteexecutions"
"go.temporal.io/server/service/worker/deletenamespace/reclaimresources"
)

func Test_DeleteNamespaceWorkflow_Success(t *testing.T) {
func Test_DeleteNamespaceWorkflow_ByName(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()

var a *activities

env.OnActivity(a.GetNamespaceIDActivity, mock.Anything, namespace.Name("namespace")).Return(namespace.ID("namespace-id"), nil)
env.OnActivity(a.GetNamespaceInfoActivity, mock.Anything, namespace.EmptyID, namespace.Name("namespace")).Return(
getNamespaceInfoResult{
NamespaceID: "namespace-id",
Namespace: "namespace",
}, nil)
env.OnActivity(a.MarkNamespaceDeletedActivity, mock.Anything, namespace.Name("namespace")).Return(nil)
env.OnActivity(a.GenerateDeletedNamespaceNameActivity, mock.Anything, namespace.Name("namespace")).Return(namespace.Name("namespace-delete-220878"), nil)
env.OnActivity(a.RenameNamespaceActivity, mock.Anything, namespace.Name("namespace"), namespace.Name("namespace-delete-220878")).Return(nil)
Expand All @@ -64,6 +69,7 @@ func Test_DeleteNamespaceWorkflow_Success(t *testing.T) {
ErrorCount: 0,
}, nil)

// Delete by name.
env.ExecuteWorkflow(DeleteNamespaceWorkflow, DeleteNamespaceWorkflowParams{
Namespace: "namespace",
DeleteExecutionsConfig: deleteexecutions.DeleteExecutionsConfig{},
Expand All @@ -76,3 +82,65 @@ func Test_DeleteNamespaceWorkflow_Success(t *testing.T) {
require.Equal(t, namespace.Name("namespace-delete-220878"), result.DeletedName)
require.Equal(t, namespace.ID("namespace-id"), result.DeletedID)
}

func Test_DeleteNamespaceWorkflow_ByID(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()

var a *activities

env.OnActivity(a.GetNamespaceInfoActivity, mock.Anything, namespace.ID("namespace-id"), namespace.EmptyName).Return(
getNamespaceInfoResult{
NamespaceID: "namespace-id",
Namespace: "namespace",
}, nil)
env.OnActivity(a.MarkNamespaceDeletedActivity, mock.Anything, namespace.Name("namespace")).Return(nil)
env.OnActivity(a.GenerateDeletedNamespaceNameActivity, mock.Anything, namespace.Name("namespace")).Return(namespace.Name("namespace-delete-220878"), nil)
env.OnActivity(a.RenameNamespaceActivity, mock.Anything, namespace.Name("namespace"), namespace.Name("namespace-delete-220878")).Return(nil)

env.RegisterWorkflow(reclaimresources.ReclaimResourcesWorkflow)
env.OnWorkflow(reclaimresources.ReclaimResourcesWorkflow, mock.Anything, reclaimresources.ReclaimResourcesParams{DeleteExecutionsParams: deleteexecutions.DeleteExecutionsParams{
Namespace: "namespace-delete-220878",
NamespaceID: "namespace-id",
Config: deleteexecutions.DeleteExecutionsConfig{
DeleteActivityRPS: 100,
PageSize: 1000,
PagesPerExecutionCount: 256,
ConcurrentDeleteExecutionsActivities: 4,
},
PreviousSuccessCount: 0,
PreviousErrorCount: 0,
}}).Return(reclaimresources.ReclaimResourcesResult{
SuccessCount: 10,
ErrorCount: 0,
}, nil)

// Delete by name.
env.ExecuteWorkflow(DeleteNamespaceWorkflow, DeleteNamespaceWorkflowParams{
NamespaceID: "namespace-id",
})

require.True(t, env.IsWorkflowCompleted())
require.NoError(t, env.GetWorkflowError())
var result DeleteNamespaceWorkflowResult
require.NoError(t, env.GetWorkflowResult(&result))
require.Equal(t, namespace.Name("namespace-delete-220878"), result.DeletedName)
require.Equal(t, namespace.ID("namespace-id"), result.DeletedID)
}

func Test_DeleteNamespaceWorkflow_ByNameAndID(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()

// Delete by name and ID.
env.ExecuteWorkflow(DeleteNamespaceWorkflow, DeleteNamespaceWorkflowParams{
NamespaceID: "namespace-id",
Namespace: "namespace",
})

require.True(t, env.IsWorkflowCompleted())
wfErr := env.GetWorkflowError()
require.Error(t, wfErr)
var applicationErr *temporal.ApplicationError
require.ErrorAs(t, wfErr, &applicationErr)
}

0 comments on commit 82ab54f

Please sign in to comment.