go.temporal.io/server@v1.23.0/common/persistence/persistence-tests/metadata_persistence_v2.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package persistencetests
    26  
    27  import (
    28  	"context"
    29  	"fmt"
    30  	"strconv"
    31  	"strings"
    32  	"sync"
    33  	"sync/atomic"
    34  	"time"
    35  
    36  	"github.com/pborman/uuid"
    37  	"github.com/stretchr/testify/require"
    38  	enumspb "go.temporal.io/api/enums/v1"
    39  	namespacepb "go.temporal.io/api/namespace/v1"
    40  	"go.temporal.io/api/serviceerror"
    41  	"google.golang.org/protobuf/types/known/timestamppb"
    42  
    43  	persistencespb "go.temporal.io/server/api/persistence/v1"
    44  	"go.temporal.io/server/common/cluster"
    45  	"go.temporal.io/server/common/debug"
    46  	p "go.temporal.io/server/common/persistence"
    47  	"go.temporal.io/server/common/persistence/cassandra"
    48  	"go.temporal.io/server/common/primitives/timestamp"
    49  	"go.temporal.io/server/common/testing/protorequire"
    50  )
    51  
    52  type (
    53  	// MetadataPersistenceSuiteV2 is test of the V2 version of metadata persistence
    54  	MetadataPersistenceSuiteV2 struct {
    55  		*TestBase
    56  		// override suite.Suite.Assertions with require.Assertions; this means that s.NotNil(nil) will stop the test,
    57  		// not merely log an error
    58  		*require.Assertions
    59  		protorequire.ProtoAssertions
    60  
    61  		ctx    context.Context
    62  		cancel context.CancelFunc
    63  	}
    64  )
    65  
    66  // SetupSuite implementation
    67  func (m *MetadataPersistenceSuiteV2) SetupSuite() {
    68  }
    69  
    70  // SetupTest implementation
    71  func (m *MetadataPersistenceSuiteV2) SetupTest() {
    72  	// Have to define our overridden assertions in the test setup. If we did it earlier, s.T() will return nil
    73  	m.Assertions = require.New(m.T())
    74  	m.ProtoAssertions = protorequire.New(m.T())
    75  	m.ctx, m.cancel = context.WithTimeout(context.Background(), 30*time.Second*debug.TimeoutMultiplier)
    76  
    77  	// cleanup the namespace created
    78  	var token []byte
    79  	pageSize := 10
    80  ListLoop:
    81  	for {
    82  		resp, err := m.ListNamespaces(pageSize, token)
    83  		m.NoError(err)
    84  		token = resp.NextPageToken
    85  		for _, n := range resp.Namespaces {
    86  			m.NoError(m.DeleteNamespace(n.Namespace.Info.Id, ""))
    87  		}
    88  		if len(token) == 0 {
    89  			break ListLoop
    90  		}
    91  	}
    92  }
    93  
    94  // TearDownTest implementation
    95  func (m *MetadataPersistenceSuiteV2) TearDownTest() {
    96  	m.cancel()
    97  }
    98  
    99  // TearDownSuite implementation
   100  func (m *MetadataPersistenceSuiteV2) TearDownSuite() {
   101  	m.TearDownWorkflowStore()
   102  }
   103  
   104  // Partial namespace creation is only relevant for Cassandra, the following tests will only run when the underlying cluster is cassandra
   105  func (m *MetadataPersistenceSuiteV2) createPartialNamespace(id string, name string) {
   106  	// only add the namespace to namespaces_by_id table and not namespaces table
   107  	const constNamespacePartition = 0
   108  	const templateCreateNamespaceQuery = `INSERT INTO namespaces_by_id (` +
   109  		`id, name) ` +
   110  		`VALUES(?, ?) IF NOT EXISTS`
   111  	query := m.DefaultTestCluster.(*cassandra.TestCluster).GetSession().Query(templateCreateNamespaceQuery, id, name).WithContext(context.Background())
   112  	err := query.Exec()
   113  	m.NoError(err)
   114  
   115  }
   116  
   117  func (m *MetadataPersistenceSuiteV2) truncatePartialNamespace() {
   118  	query := m.DefaultTestCluster.(*cassandra.TestCluster).GetSession().Query("TRUNCATE namespaces_by_id").WithContext(context.Background())
   119  	err := query.Exec()
   120  	m.NoError(err)
   121  
   122  	query = m.DefaultTestCluster.(*cassandra.TestCluster).GetSession().Query("TRUNCATE namespaces").WithContext(context.Background())
   123  	err = query.Exec()
   124  	m.NoError(err)
   125  }
   126  
   127  func (m *MetadataPersistenceSuiteV2) TestCreateWithPartialNamespaceSameNameSameID() {
   128  	// This is only relevant for cassandra
   129  	switch m.DefaultTestCluster.(type) {
   130  	case *cassandra.TestCluster:
   131  	default:
   132  		return
   133  	}
   134  	id := uuid.New()
   135  	name := "create-partial-namespace-test-name"
   136  	m.createPartialNamespace(id, name)
   137  
   138  	state := enumspb.NAMESPACE_STATE_REGISTERED
   139  	description := "create-namespace-test-description"
   140  	owner := "create-namespace-test-owner"
   141  	data := map[string]string{"k1": "v1"}
   142  	retention := int32(10)
   143  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   144  	historyArchivalURI := "test://history/uri"
   145  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   146  	visibilityArchivalURI := "test://visibility/uri"
   147  	badBinaries := &namespacepb.BadBinaries{Binaries: map[string]*namespacepb.BadBinaryInfo{}}
   148  	isGlobalNamespace := false
   149  	configVersion := int64(0)
   150  	failoverVersion := int64(0)
   151  
   152  	resp0, err0 := m.CreateNamespace(
   153  		&persistencespb.NamespaceInfo{
   154  			Id:          id,
   155  			Name:        name,
   156  			State:       state,
   157  			Description: description,
   158  			Owner:       owner,
   159  			Data:        data,
   160  		},
   161  		&persistencespb.NamespaceConfig{
   162  			Retention:               timestamp.DurationFromDays(retention),
   163  			HistoryArchivalState:    historyArchivalState,
   164  			HistoryArchivalUri:      historyArchivalURI,
   165  			VisibilityArchivalState: visibilityArchivalState,
   166  			VisibilityArchivalUri:   visibilityArchivalURI,
   167  			BadBinaries:             badBinaries,
   168  		},
   169  		&persistencespb.NamespaceReplicationConfig{},
   170  		isGlobalNamespace,
   171  		configVersion,
   172  		failoverVersion,
   173  	)
   174  	m.NoError(err0)
   175  	m.NotNil(resp0)
   176  	m.EqualValues(id, resp0.ID)
   177  
   178  	// for namespace which do not have replication config set, will default to
   179  	// use current cluster as active, with current cluster as all clusters
   180  	resp1, err1 := m.GetNamespace(id, "")
   181  	m.NoError(err1)
   182  	m.NotNil(resp1)
   183  	m.EqualValues(id, resp1.Namespace.Info.Id)
   184  	m.Equal(name, resp1.Namespace.Info.Name)
   185  	m.Equal(state, resp1.Namespace.Info.State)
   186  	m.Equal(description, resp1.Namespace.Info.Description)
   187  	m.Equal(owner, resp1.Namespace.Info.Owner)
   188  	m.Equal(data, resp1.Namespace.Info.Data)
   189  	m.EqualValues(time.Duration(retention)*time.Hour*24, resp1.Namespace.Config.Retention.AsDuration())
   190  	m.Equal(historyArchivalState, resp1.Namespace.Config.HistoryArchivalState)
   191  	m.Equal(historyArchivalURI, resp1.Namespace.Config.HistoryArchivalUri)
   192  	m.Equal(visibilityArchivalState, resp1.Namespace.Config.VisibilityArchivalState)
   193  	m.Equal(visibilityArchivalURI, resp1.Namespace.Config.VisibilityArchivalUri)
   194  	m.Equal(badBinaries, resp1.Namespace.Config.BadBinaries)
   195  	m.Equal(cluster.TestCurrentClusterName, resp1.Namespace.ReplicationConfig.ActiveClusterName)
   196  	m.Equal(1, len(resp1.Namespace.ReplicationConfig.Clusters))
   197  	m.Equal(isGlobalNamespace, resp1.IsGlobalNamespace)
   198  	m.Equal(configVersion, resp1.Namespace.ConfigVersion)
   199  	m.Equal(failoverVersion, resp1.Namespace.FailoverVersion)
   200  	m.True(resp1.Namespace.ReplicationConfig.Clusters[0] == cluster.TestCurrentClusterName)
   201  	m.Equal(p.InitialFailoverNotificationVersion, resp1.Namespace.FailoverNotificationVersion)
   202  	m.truncatePartialNamespace()
   203  }
   204  
   205  func (m *MetadataPersistenceSuiteV2) TestCreateWithPartialNamespaceSameNameDifferentID() {
   206  	// This is only relevant for cassandra
   207  	switch m.DefaultTestCluster.(type) {
   208  	case *cassandra.TestCluster:
   209  	default:
   210  		return
   211  	}
   212  
   213  	id := uuid.New()
   214  	partialID := uuid.New()
   215  	name := "create-partial-namespace-test-name"
   216  	m.createPartialNamespace(partialID, name)
   217  	state := enumspb.NAMESPACE_STATE_REGISTERED
   218  	description := "create-namespace-test-description"
   219  	owner := "create-namespace-test-owner"
   220  	data := map[string]string{"k1": "v1"}
   221  	retention := int32(10)
   222  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   223  	historyArchivalURI := "test://history/uri"
   224  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   225  	visibilityArchivalURI := "test://visibility/uri"
   226  	badBinaries := &namespacepb.BadBinaries{Binaries: map[string]*namespacepb.BadBinaryInfo{}}
   227  	isGlobalNamespace := false
   228  	configVersion := int64(0)
   229  	failoverVersion := int64(0)
   230  
   231  	resp0, err0 := m.CreateNamespace(
   232  		&persistencespb.NamespaceInfo{
   233  			Id:          id,
   234  			Name:        name,
   235  			State:       state,
   236  			Description: description,
   237  			Owner:       owner,
   238  			Data:        data,
   239  		},
   240  		&persistencespb.NamespaceConfig{
   241  			Retention:               timestamp.DurationFromDays(retention),
   242  			HistoryArchivalState:    historyArchivalState,
   243  			HistoryArchivalUri:      historyArchivalURI,
   244  			VisibilityArchivalState: visibilityArchivalState,
   245  			VisibilityArchivalUri:   visibilityArchivalURI,
   246  			BadBinaries:             badBinaries,
   247  		},
   248  		&persistencespb.NamespaceReplicationConfig{},
   249  		isGlobalNamespace,
   250  		configVersion,
   251  		failoverVersion,
   252  	)
   253  	m.NoError(err0)
   254  	m.NotNil(resp0)
   255  	m.EqualValues(id, resp0.ID)
   256  
   257  	// for namespace which do not have replication config set, will default to
   258  	// use current cluster as active, with current cluster as all clusters
   259  	resp1, err1 := m.GetNamespace(id, "")
   260  	m.NoError(err1)
   261  	m.NotNil(resp1)
   262  	m.EqualValues(id, resp1.Namespace.Info.Id)
   263  	m.Equal(name, resp1.Namespace.Info.Name)
   264  	m.Equal(state, resp1.Namespace.Info.State)
   265  	m.Equal(description, resp1.Namespace.Info.Description)
   266  	m.Equal(owner, resp1.Namespace.Info.Owner)
   267  	m.Equal(data, resp1.Namespace.Info.Data)
   268  	m.EqualValues(time.Duration(retention)*time.Hour*24, resp1.Namespace.Config.Retention.AsDuration())
   269  	m.Equal(historyArchivalState, resp1.Namespace.Config.HistoryArchivalState)
   270  	m.Equal(historyArchivalURI, resp1.Namespace.Config.HistoryArchivalUri)
   271  	m.Equal(visibilityArchivalState, resp1.Namespace.Config.VisibilityArchivalState)
   272  	m.Equal(visibilityArchivalURI, resp1.Namespace.Config.VisibilityArchivalUri)
   273  	m.Equal(badBinaries, resp1.Namespace.Config.BadBinaries)
   274  	m.Equal(cluster.TestCurrentClusterName, resp1.Namespace.ReplicationConfig.ActiveClusterName)
   275  	m.Equal(1, len(resp1.Namespace.ReplicationConfig.Clusters))
   276  	m.Equal(isGlobalNamespace, resp1.IsGlobalNamespace)
   277  	m.Equal(configVersion, resp1.Namespace.ConfigVersion)
   278  	m.Equal(failoverVersion, resp1.Namespace.FailoverVersion)
   279  	m.True(resp1.Namespace.ReplicationConfig.Clusters[0] == cluster.TestCurrentClusterName)
   280  	m.Equal(p.InitialFailoverNotificationVersion, resp1.Namespace.FailoverNotificationVersion)
   281  	m.truncatePartialNamespace()
   282  }
   283  
   284  func (m *MetadataPersistenceSuiteV2) TestCreateWithPartialNamespaceDifferentNameSameID() {
   285  	// This is only relevant for cassandra
   286  	switch m.DefaultTestCluster.(type) {
   287  	case *cassandra.TestCluster:
   288  	default:
   289  		return
   290  	}
   291  	id := uuid.New()
   292  	name := "create-namespace-test-name-for-partial-test"
   293  	partialName := "create-partial-namespace-test-name"
   294  	m.createPartialNamespace(id, partialName)
   295  	state := enumspb.NAMESPACE_STATE_REGISTERED
   296  	description := "create-namespace-test-description"
   297  	owner := "create-namespace-test-owner"
   298  	data := map[string]string{"k1": "v1"}
   299  	retention := int32(10)
   300  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   301  	historyArchivalURI := "test://history/uri"
   302  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   303  	visibilityArchivalURI := "test://visibility/uri"
   304  	badBinaries := &namespacepb.BadBinaries{Binaries: map[string]*namespacepb.BadBinaryInfo{}}
   305  	isGlobalNamespace := false
   306  	configVersion := int64(0)
   307  	failoverVersion := int64(0)
   308  
   309  	resp0, err0 := m.CreateNamespace(
   310  		&persistencespb.NamespaceInfo{
   311  			Id:          id,
   312  			Name:        name,
   313  			State:       state,
   314  			Description: description,
   315  			Owner:       owner,
   316  			Data:        data,
   317  		},
   318  		&persistencespb.NamespaceConfig{
   319  			Retention:               timestamp.DurationFromDays(retention),
   320  			HistoryArchivalState:    historyArchivalState,
   321  			HistoryArchivalUri:      historyArchivalURI,
   322  			VisibilityArchivalState: visibilityArchivalState,
   323  			VisibilityArchivalUri:   visibilityArchivalURI,
   324  			BadBinaries:             badBinaries,
   325  		},
   326  		&persistencespb.NamespaceReplicationConfig{},
   327  		isGlobalNamespace,
   328  		configVersion,
   329  		failoverVersion,
   330  	)
   331  	m.Error(err0)
   332  	m.IsType(&serviceerror.NamespaceAlreadyExists{}, err0)
   333  	m.Nil(resp0)
   334  	m.truncatePartialNamespace()
   335  }
   336  
   337  // TestCreateNamespace test
   338  func (m *MetadataPersistenceSuiteV2) TestCreateNamespace() {
   339  	id := uuid.New()
   340  	name := "create-namespace-test-name-for-partial-test"
   341  	state := enumspb.NAMESPACE_STATE_REGISTERED
   342  	description := "create-namespace-test-description"
   343  	owner := "create-namespace-test-owner"
   344  	data := map[string]string{"k1": "v1"}
   345  	retention := int32(10)
   346  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   347  	historyArchivalURI := "test://history/uri"
   348  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   349  	visibilityArchivalURI := "test://visibility/uri"
   350  	badBinaries := &namespacepb.BadBinaries{Binaries: map[string]*namespacepb.BadBinaryInfo{}}
   351  	isGlobalNamespace := false
   352  	configVersion := int64(0)
   353  	failoverVersion := int64(0)
   354  
   355  	resp0, err0 := m.CreateNamespace(
   356  		&persistencespb.NamespaceInfo{
   357  			Id:          id,
   358  			Name:        name,
   359  			State:       state,
   360  			Description: description,
   361  			Owner:       owner,
   362  			Data:        data,
   363  		},
   364  		&persistencespb.NamespaceConfig{
   365  			Retention:               timestamp.DurationFromDays(retention),
   366  			HistoryArchivalState:    historyArchivalState,
   367  			HistoryArchivalUri:      historyArchivalURI,
   368  			VisibilityArchivalState: visibilityArchivalState,
   369  			VisibilityArchivalUri:   visibilityArchivalURI,
   370  			BadBinaries:             badBinaries,
   371  		},
   372  		&persistencespb.NamespaceReplicationConfig{},
   373  		isGlobalNamespace,
   374  		configVersion,
   375  		failoverVersion,
   376  	)
   377  	m.NoError(err0)
   378  	m.NotNil(resp0)
   379  	m.EqualValues(id, resp0.ID)
   380  
   381  	// for namespace which do not have replication config set, will default to
   382  	// use current cluster as active, with current cluster as all clusters
   383  	resp1, err1 := m.GetNamespace(id, "")
   384  	m.NoError(err1)
   385  	m.NotNil(resp1)
   386  	m.EqualValues(id, resp1.Namespace.Info.Id)
   387  	m.Equal(name, resp1.Namespace.Info.Name)
   388  	m.Equal(state, resp1.Namespace.Info.State)
   389  	m.Equal(description, resp1.Namespace.Info.Description)
   390  	m.Equal(owner, resp1.Namespace.Info.Owner)
   391  	m.Equal(data, resp1.Namespace.Info.Data)
   392  	m.EqualValues(time.Duration(retention)*time.Hour*24, resp1.Namespace.Config.Retention.AsDuration())
   393  	m.Equal(historyArchivalState, resp1.Namespace.Config.HistoryArchivalState)
   394  	m.Equal(historyArchivalURI, resp1.Namespace.Config.HistoryArchivalUri)
   395  	m.Equal(visibilityArchivalState, resp1.Namespace.Config.VisibilityArchivalState)
   396  	m.Equal(visibilityArchivalURI, resp1.Namespace.Config.VisibilityArchivalUri)
   397  	m.Equal(badBinaries, resp1.Namespace.Config.BadBinaries)
   398  	m.Equal(cluster.TestCurrentClusterName, resp1.Namespace.ReplicationConfig.ActiveClusterName)
   399  	m.Equal(1, len(resp1.Namespace.ReplicationConfig.Clusters))
   400  	m.Equal(isGlobalNamespace, resp1.IsGlobalNamespace)
   401  	m.Equal(configVersion, resp1.Namespace.ConfigVersion)
   402  	m.Equal(failoverVersion, resp1.Namespace.FailoverVersion)
   403  	m.True(resp1.Namespace.ReplicationConfig.Clusters[0] == cluster.TestCurrentClusterName)
   404  	m.Equal(p.InitialFailoverNotificationVersion, resp1.Namespace.FailoverNotificationVersion)
   405  
   406  	resp2, err2 := m.CreateNamespace(
   407  		&persistencespb.NamespaceInfo{
   408  			Id:          uuid.New(),
   409  			Name:        name,
   410  			State:       state,
   411  			Description: "fail",
   412  			Owner:       "fail",
   413  			Data:        map[string]string{},
   414  		},
   415  		&persistencespb.NamespaceConfig{
   416  			Retention:               timestamp.DurationFromDays(100),
   417  			HistoryArchivalState:    enumspb.ARCHIVAL_STATE_DISABLED,
   418  			HistoryArchivalUri:      "",
   419  			VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
   420  			VisibilityArchivalUri:   "",
   421  		},
   422  		&persistencespb.NamespaceReplicationConfig{},
   423  		isGlobalNamespace,
   424  		configVersion,
   425  		failoverVersion,
   426  	)
   427  	m.Error(err2)
   428  	m.IsType(&serviceerror.NamespaceAlreadyExists{}, err2)
   429  	m.Nil(resp2)
   430  }
   431  
   432  // TestGetNamespace test
   433  func (m *MetadataPersistenceSuiteV2) TestGetNamespace() {
   434  	id := uuid.New()
   435  	name := "get-namespace-test-name"
   436  	state := enumspb.NAMESPACE_STATE_REGISTERED
   437  	description := "get-namespace-test-description"
   438  	owner := "get-namespace-test-owner"
   439  	data := map[string]string{"k1": "v1"}
   440  	retention := int32(10)
   441  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   442  	historyArchivalURI := "test://history/uri"
   443  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   444  	visibilityArchivalURI := "test://visibility/uri"
   445  
   446  	clusterActive := "some random active cluster name"
   447  	clusterStandby := "some random standby cluster name"
   448  	configVersion := int64(11)
   449  	failoverVersion := int64(59)
   450  	isGlobalNamespace := true
   451  	clusters := []string{clusterActive, clusterStandby}
   452  
   453  	resp0, err0 := m.GetNamespace("", "does-not-exist")
   454  	m.Nil(resp0)
   455  	m.Error(err0)
   456  	m.IsType(&serviceerror.NamespaceNotFound{}, err0)
   457  	testBinaries := &namespacepb.BadBinaries{
   458  		Binaries: map[string]*namespacepb.BadBinaryInfo{
   459  			"abc": {
   460  				Reason:     "test-reason",
   461  				Operator:   "test-operator",
   462  				CreateTime: timestamppb.New(time.Date(2020, 8, 22, 0, 0, 0, 0, time.UTC)),
   463  			},
   464  		},
   465  	}
   466  
   467  	resp1, err1 := m.CreateNamespace(
   468  		&persistencespb.NamespaceInfo{
   469  			Id:          id,
   470  			Name:        name,
   471  			State:       state,
   472  			Description: description,
   473  			Owner:       owner,
   474  			Data:        data,
   475  		},
   476  		&persistencespb.NamespaceConfig{
   477  			Retention:               timestamp.DurationFromDays(retention),
   478  			HistoryArchivalState:    historyArchivalState,
   479  			HistoryArchivalUri:      historyArchivalURI,
   480  			VisibilityArchivalState: visibilityArchivalState,
   481  			VisibilityArchivalUri:   visibilityArchivalURI,
   482  			BadBinaries:             testBinaries,
   483  		},
   484  		&persistencespb.NamespaceReplicationConfig{
   485  			ActiveClusterName: clusterActive,
   486  			Clusters:          clusters,
   487  		},
   488  		isGlobalNamespace,
   489  		configVersion,
   490  		failoverVersion,
   491  	)
   492  	m.NoError(err1)
   493  	m.NotNil(resp1)
   494  	m.EqualValues(id, resp1.ID)
   495  
   496  	resp2, err2 := m.GetNamespace(id, "")
   497  	m.NoError(err2)
   498  	m.NotNil(resp2)
   499  	m.EqualValues(id, resp2.Namespace.Info.Id)
   500  	m.Equal(name, resp2.Namespace.Info.Name)
   501  	m.Equal(state, resp2.Namespace.Info.State)
   502  	m.Equal(description, resp2.Namespace.Info.Description)
   503  	m.Equal(owner, resp2.Namespace.Info.Owner)
   504  	m.Equal(data, resp2.Namespace.Info.Data)
   505  	m.EqualValues(time.Duration(retention)*time.Hour*24, resp2.Namespace.Config.Retention.AsDuration())
   506  	m.Equal(historyArchivalState, resp2.Namespace.Config.HistoryArchivalState)
   507  	m.Equal(historyArchivalURI, resp2.Namespace.Config.HistoryArchivalUri)
   508  	m.Equal(visibilityArchivalState, resp2.Namespace.Config.VisibilityArchivalState)
   509  	m.Equal(visibilityArchivalURI, resp2.Namespace.Config.VisibilityArchivalUri)
   510  	m.ProtoEqual(testBinaries, resp2.Namespace.Config.BadBinaries)
   511  	m.Equal(clusterActive, resp2.Namespace.ReplicationConfig.ActiveClusterName)
   512  	m.Equal(len(clusters), len(resp2.Namespace.ReplicationConfig.Clusters))
   513  	for index := range clusters {
   514  		m.Equal(clusters[index], resp2.Namespace.ReplicationConfig.Clusters[index])
   515  	}
   516  	m.Equal(isGlobalNamespace, resp2.IsGlobalNamespace)
   517  	m.Equal(configVersion, resp2.Namespace.ConfigVersion)
   518  	m.Equal(failoverVersion, resp2.Namespace.FailoverVersion)
   519  	m.Equal(p.InitialFailoverNotificationVersion, resp2.Namespace.FailoverNotificationVersion)
   520  
   521  	resp3, err3 := m.GetNamespace("", name)
   522  	m.NoError(err3)
   523  	m.NotNil(resp3)
   524  	m.EqualValues(id, resp3.Namespace.Info.Id)
   525  	m.Equal(name, resp3.Namespace.Info.Name)
   526  	m.Equal(state, resp3.Namespace.Info.State)
   527  	m.Equal(description, resp3.Namespace.Info.Description)
   528  	m.Equal(owner, resp3.Namespace.Info.Owner)
   529  	m.Equal(data, resp3.Namespace.Info.Data)
   530  	m.EqualValues(time.Duration(retention)*time.Hour*24, resp3.Namespace.Config.Retention.AsDuration())
   531  	m.Equal(historyArchivalState, resp3.Namespace.Config.HistoryArchivalState)
   532  	m.Equal(historyArchivalURI, resp3.Namespace.Config.HistoryArchivalUri)
   533  	m.Equal(visibilityArchivalState, resp3.Namespace.Config.VisibilityArchivalState)
   534  	m.Equal(visibilityArchivalURI, resp3.Namespace.Config.VisibilityArchivalUri)
   535  	m.Equal(clusterActive, resp3.Namespace.ReplicationConfig.ActiveClusterName)
   536  	m.Equal(len(clusters), len(resp3.Namespace.ReplicationConfig.Clusters))
   537  	for index := range clusters {
   538  		m.Equal(clusters[index], resp3.Namespace.ReplicationConfig.Clusters[index])
   539  	}
   540  	m.Equal(isGlobalNamespace, resp3.IsGlobalNamespace)
   541  	m.Equal(configVersion, resp3.Namespace.ConfigVersion)
   542  	m.Equal(failoverVersion, resp3.Namespace.FailoverVersion)
   543  	m.Equal(p.InitialFailoverNotificationVersion, resp3.Namespace.FailoverNotificationVersion)
   544  
   545  	resp4, err4 := m.GetNamespace(id, name)
   546  	m.Error(err4)
   547  	m.IsType(&serviceerror.InvalidArgument{}, err4)
   548  	m.Nil(resp4)
   549  
   550  	resp5, err5 := m.GetNamespace("", "")
   551  	m.Nil(resp5)
   552  	m.IsType(&serviceerror.InvalidArgument{}, err5)
   553  }
   554  
   555  // TestConcurrentCreateNamespace test
   556  func (m *MetadataPersistenceSuiteV2) TestConcurrentCreateNamespace() {
   557  	id := uuid.New()
   558  
   559  	name := "concurrent-create-namespace-test-name"
   560  	state := enumspb.NAMESPACE_STATE_REGISTERED
   561  	description := "concurrent-create-namespace-test-description"
   562  	owner := "create-namespace-test-owner"
   563  	retention := int32(10)
   564  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   565  	historyArchivalURI := "test://history/uri"
   566  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   567  	visibilityArchivalURI := "test://visibility/uri"
   568  
   569  	clusterActive := "some random active cluster name"
   570  	clusterStandby := "some random standby cluster name"
   571  	configVersion := int64(10)
   572  	failoverVersion := int64(59)
   573  	isGlobalNamespace := true
   574  	clusters := []string{clusterActive, clusterStandby}
   575  
   576  	testBinaries := &namespacepb.BadBinaries{
   577  		Binaries: map[string]*namespacepb.BadBinaryInfo{
   578  			"abc": {
   579  				Reason:     "test-reason",
   580  				Operator:   "test-operator",
   581  				CreateTime: timestamppb.New(time.Date(2020, 8, 22, 0, 0, 0, 0, time.UTC)),
   582  			},
   583  		},
   584  	}
   585  	concurrency := 16
   586  	successCount := int32(0)
   587  	var wg sync.WaitGroup
   588  	for i := 1; i <= concurrency; i++ {
   589  		newValue := fmt.Sprintf("v-%v", i)
   590  		wg.Add(1)
   591  		go func(data map[string]string) {
   592  			_, err1 := m.CreateNamespace(
   593  				&persistencespb.NamespaceInfo{
   594  					Id:          id,
   595  					Name:        name,
   596  					State:       state,
   597  					Description: description,
   598  					Owner:       owner,
   599  					Data:        data,
   600  				},
   601  				&persistencespb.NamespaceConfig{
   602  					Retention:               timestamp.DurationFromDays(retention),
   603  					HistoryArchivalState:    historyArchivalState,
   604  					HistoryArchivalUri:      historyArchivalURI,
   605  					VisibilityArchivalState: visibilityArchivalState,
   606  					VisibilityArchivalUri:   visibilityArchivalURI,
   607  					BadBinaries:             testBinaries,
   608  				},
   609  				&persistencespb.NamespaceReplicationConfig{
   610  					ActiveClusterName: clusterActive,
   611  					Clusters:          clusters,
   612  				},
   613  				isGlobalNamespace,
   614  				configVersion,
   615  				failoverVersion,
   616  			)
   617  			if err1 == nil {
   618  				atomic.AddInt32(&successCount, 1)
   619  			}
   620  			wg.Done()
   621  		}(map[string]string{"k0": newValue})
   622  	}
   623  	wg.Wait()
   624  	m.Equal(int32(1), successCount)
   625  
   626  	resp, err3 := m.GetNamespace("", name)
   627  	m.NoError(err3)
   628  	m.NotNil(resp)
   629  	m.Equal(name, resp.Namespace.Info.Name)
   630  	m.Equal(state, resp.Namespace.Info.State)
   631  	m.Equal(description, resp.Namespace.Info.Description)
   632  	m.Equal(owner, resp.Namespace.Info.Owner)
   633  	m.EqualValues(time.Duration(retention)*time.Hour*24, resp.Namespace.Config.Retention.AsDuration())
   634  	m.Equal(historyArchivalState, resp.Namespace.Config.HistoryArchivalState)
   635  	m.Equal(historyArchivalURI, resp.Namespace.Config.HistoryArchivalUri)
   636  	m.Equal(visibilityArchivalState, resp.Namespace.Config.VisibilityArchivalState)
   637  	m.Equal(visibilityArchivalURI, resp.Namespace.Config.VisibilityArchivalUri)
   638  	m.ProtoEqual(testBinaries, resp.Namespace.Config.BadBinaries)
   639  	m.Equal(clusterActive, resp.Namespace.ReplicationConfig.ActiveClusterName)
   640  	m.Equal(len(clusters), len(resp.Namespace.ReplicationConfig.Clusters))
   641  	for index := range clusters {
   642  		m.Equal(clusters[index], resp.Namespace.ReplicationConfig.Clusters[index])
   643  	}
   644  	m.Equal(isGlobalNamespace, resp.IsGlobalNamespace)
   645  	m.Equal(configVersion, resp.Namespace.ConfigVersion)
   646  	m.Equal(failoverVersion, resp.Namespace.FailoverVersion)
   647  
   648  	// check namespace data
   649  	ss := strings.Split(resp.Namespace.Info.Data["k0"], "-")
   650  	m.Equal(2, len(ss))
   651  	vi, err := strconv.Atoi(ss[1])
   652  	m.NoError(err)
   653  	m.Equal(true, vi > 0 && vi <= concurrency)
   654  }
   655  
   656  // TestConcurrentUpdateNamespace test
   657  func (m *MetadataPersistenceSuiteV2) TestConcurrentUpdateNamespace() {
   658  	id := uuid.New()
   659  	name := "concurrent-update-namespace-test-name"
   660  	state := enumspb.NAMESPACE_STATE_REGISTERED
   661  	description := "update-namespace-test-description"
   662  	owner := "update-namespace-test-owner"
   663  	data := map[string]string{"k1": "v1"}
   664  	retention := int32(10)
   665  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   666  	historyArchivalURI := "test://history/uri"
   667  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   668  	visibilityArchivalURI := "test://visibility/uri"
   669  	badBinaries := &namespacepb.BadBinaries{Binaries: map[string]*namespacepb.BadBinaryInfo{}}
   670  
   671  	clusterActive := "some random active cluster name"
   672  	clusterStandby := "some random standby cluster name"
   673  	configVersion := int64(10)
   674  	failoverVersion := int64(59)
   675  	isGlobalNamespace := true
   676  	clusters := []string{clusterActive, clusterStandby}
   677  
   678  	resp1, err1 := m.CreateNamespace(
   679  		&persistencespb.NamespaceInfo{
   680  			Id:          id,
   681  			Name:        name,
   682  			State:       state,
   683  			Description: description,
   684  			Owner:       owner,
   685  			Data:        data,
   686  		},
   687  		&persistencespb.NamespaceConfig{
   688  			Retention:               timestamp.DurationFromDays(retention),
   689  			HistoryArchivalState:    historyArchivalState,
   690  			HistoryArchivalUri:      historyArchivalURI,
   691  			VisibilityArchivalState: visibilityArchivalState,
   692  			VisibilityArchivalUri:   visibilityArchivalURI,
   693  			BadBinaries:             badBinaries,
   694  		},
   695  		&persistencespb.NamespaceReplicationConfig{
   696  			ActiveClusterName: clusterActive,
   697  			Clusters:          clusters,
   698  		},
   699  		isGlobalNamespace,
   700  		configVersion,
   701  		failoverVersion,
   702  	)
   703  	m.NoError(err1)
   704  	m.EqualValues(id, resp1.ID)
   705  
   706  	resp2, err2 := m.GetNamespace(id, "")
   707  	m.NoError(err2)
   708  	m.Equal(badBinaries, resp2.Namespace.Config.BadBinaries)
   709  	metadata, err := m.MetadataManager.GetMetadata(m.ctx)
   710  	m.NoError(err)
   711  	notificationVersion := metadata.NotificationVersion
   712  
   713  	testBinaries := &namespacepb.BadBinaries{
   714  		Binaries: map[string]*namespacepb.BadBinaryInfo{
   715  			"abc": {
   716  				Reason:     "test-reason",
   717  				Operator:   "test-operator",
   718  				CreateTime: timestamppb.New(time.Date(2020, 8, 22, 0, 0, 0, 0, time.UTC)),
   719  			},
   720  		},
   721  	}
   722  	concurrency := 16
   723  	successCount := int32(0)
   724  	var wg sync.WaitGroup
   725  	for i := 1; i <= concurrency; i++ {
   726  		newValue := fmt.Sprintf("v-%v", i)
   727  		wg.Add(1)
   728  		go func(updatedData map[string]string) {
   729  			err3 := m.UpdateNamespace(
   730  				&persistencespb.NamespaceInfo{
   731  					Id:          resp2.Namespace.Info.Id,
   732  					Name:        resp2.Namespace.Info.Name,
   733  					State:       resp2.Namespace.Info.State,
   734  					Description: resp2.Namespace.Info.Description,
   735  					Owner:       resp2.Namespace.Info.Owner,
   736  					Data:        updatedData,
   737  				},
   738  				&persistencespb.NamespaceConfig{
   739  					Retention:               resp2.Namespace.Config.Retention,
   740  					HistoryArchivalState:    resp2.Namespace.Config.HistoryArchivalState,
   741  					HistoryArchivalUri:      resp2.Namespace.Config.HistoryArchivalUri,
   742  					VisibilityArchivalState: resp2.Namespace.Config.VisibilityArchivalState,
   743  					VisibilityArchivalUri:   resp2.Namespace.Config.VisibilityArchivalUri,
   744  					BadBinaries:             testBinaries,
   745  				},
   746  				&persistencespb.NamespaceReplicationConfig{
   747  					ActiveClusterName: resp2.Namespace.ReplicationConfig.ActiveClusterName,
   748  					Clusters:          resp2.Namespace.ReplicationConfig.Clusters,
   749  				},
   750  				resp2.Namespace.ConfigVersion,
   751  				resp2.Namespace.FailoverVersion,
   752  				resp2.Namespace.FailoverNotificationVersion,
   753  				time.Time{},
   754  				notificationVersion,
   755  				isGlobalNamespace,
   756  			)
   757  			if err3 == nil {
   758  				atomic.AddInt32(&successCount, 1)
   759  			}
   760  			wg.Done()
   761  		}(map[string]string{"k0": newValue})
   762  	}
   763  	wg.Wait()
   764  	m.Equal(int32(1), successCount)
   765  
   766  	resp3, err3 := m.GetNamespace("", name)
   767  	m.NoError(err3)
   768  	m.NotNil(resp3)
   769  	m.EqualValues(id, resp3.Namespace.Info.Id)
   770  	m.Equal(name, resp3.Namespace.Info.Name)
   771  	m.Equal(state, resp3.Namespace.Info.State)
   772  	m.Equal(isGlobalNamespace, resp3.IsGlobalNamespace)
   773  	m.Equal(description, resp3.Namespace.Info.Description)
   774  	m.Equal(owner, resp3.Namespace.Info.Owner)
   775  
   776  	m.EqualValues(time.Duration(retention)*time.Hour*24, resp3.Namespace.Config.Retention.AsDuration())
   777  	m.Equal(historyArchivalState, resp3.Namespace.Config.HistoryArchivalState)
   778  	m.Equal(historyArchivalURI, resp3.Namespace.Config.HistoryArchivalUri)
   779  	m.Equal(visibilityArchivalState, resp3.Namespace.Config.VisibilityArchivalState)
   780  	m.Equal(visibilityArchivalURI, resp3.Namespace.Config.VisibilityArchivalUri)
   781  	m.ProtoEqual(testBinaries, resp3.Namespace.Config.BadBinaries)
   782  	m.Equal(clusterActive, resp3.Namespace.ReplicationConfig.ActiveClusterName)
   783  	m.Equal(len(clusters), len(resp3.Namespace.ReplicationConfig.Clusters))
   784  	for index := range clusters {
   785  		m.Equal(clusters[index], resp3.Namespace.ReplicationConfig.Clusters[index])
   786  	}
   787  	m.Equal(isGlobalNamespace, resp3.IsGlobalNamespace)
   788  	m.Equal(configVersion, resp3.Namespace.ConfigVersion)
   789  	m.Equal(failoverVersion, resp3.Namespace.FailoverVersion)
   790  
   791  	// check namespace data
   792  	ss := strings.Split(resp3.Namespace.Info.Data["k0"], "-")
   793  	m.Equal(2, len(ss))
   794  	vi, err := strconv.Atoi(ss[1])
   795  	m.NoError(err)
   796  	m.Equal(true, vi > 0 && vi <= concurrency)
   797  }
   798  
   799  // TestUpdateNamespace test
   800  func (m *MetadataPersistenceSuiteV2) TestUpdateNamespace() {
   801  	id := uuid.New()
   802  	name := "update-namespace-test-name"
   803  	state := enumspb.NAMESPACE_STATE_REGISTERED
   804  	description := "update-namespace-test-description"
   805  	owner := "update-namespace-test-owner"
   806  	data := map[string]string{"k1": "v1"}
   807  	retention := int32(10)
   808  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   809  	historyArchivalURI := "test://history/uri"
   810  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
   811  	visibilityArchivalURI := "test://visibility/uri"
   812  
   813  	clusterActive := "some random active cluster name"
   814  	clusterStandby := "some random standby cluster name"
   815  	configVersion := int64(10)
   816  	failoverVersion := int64(59)
   817  	failoverEndTime := time.Now().UTC()
   818  	isGlobalNamespace := true
   819  	clusters := []string{clusterActive, clusterStandby}
   820  
   821  	resp1, err1 := m.CreateNamespace(
   822  		&persistencespb.NamespaceInfo{
   823  			Id:          id,
   824  			Name:        name,
   825  			State:       state,
   826  			Description: description,
   827  			Owner:       owner,
   828  			Data:        data,
   829  		},
   830  		&persistencespb.NamespaceConfig{
   831  			Retention:               timestamp.DurationFromDays(retention),
   832  			HistoryArchivalState:    historyArchivalState,
   833  			HistoryArchivalUri:      historyArchivalURI,
   834  			VisibilityArchivalState: visibilityArchivalState,
   835  			VisibilityArchivalUri:   visibilityArchivalURI,
   836  		},
   837  		&persistencespb.NamespaceReplicationConfig{
   838  			ActiveClusterName: clusterActive,
   839  			Clusters:          clusters,
   840  		},
   841  		isGlobalNamespace,
   842  		configVersion,
   843  		failoverVersion,
   844  	)
   845  	m.NoError(err1)
   846  	m.EqualValues(id, resp1.ID)
   847  
   848  	resp2, err2 := m.GetNamespace(id, "")
   849  	m.NoError(err2)
   850  	metadata, err := m.MetadataManager.GetMetadata(m.ctx)
   851  	m.NoError(err)
   852  	notificationVersion := metadata.NotificationVersion
   853  
   854  	updatedState := enumspb.NAMESPACE_STATE_DEPRECATED
   855  	updatedDescription := "description-updated"
   856  	updatedOwner := "owner-updated"
   857  	// This will overriding the previous key-value pair
   858  	updatedData := map[string]string{"k1": "v2"}
   859  	updatedRetention := timestamp.DurationFromDays(20)
   860  	updatedHistoryArchivalState := enumspb.ARCHIVAL_STATE_DISABLED
   861  	updatedHistoryArchivalURI := ""
   862  	updatedVisibilityArchivalState := enumspb.ARCHIVAL_STATE_DISABLED
   863  	updatedVisibilityArchivalURI := ""
   864  
   865  	updateClusterActive := "other random active cluster name"
   866  	updateClusterStandby := "other random standby cluster name"
   867  	updateConfigVersion := int64(12)
   868  	updateFailoverVersion := int64(28)
   869  	updateFailoverNotificationVersion := int64(14)
   870  	updateClusters := []string{updateClusterActive, updateClusterStandby}
   871  
   872  	testBinaries := &namespacepb.BadBinaries{
   873  		Binaries: map[string]*namespacepb.BadBinaryInfo{
   874  			"abc": {
   875  				Reason:     "test-reason",
   876  				Operator:   "test-operator",
   877  				CreateTime: timestamppb.New(time.Date(2020, 8, 22, 0, 0, 0, 0, time.UTC)),
   878  			},
   879  		},
   880  	}
   881  
   882  	err3 := m.UpdateNamespace(
   883  		&persistencespb.NamespaceInfo{
   884  			Id:          resp2.Namespace.Info.Id,
   885  			Name:        resp2.Namespace.Info.Name,
   886  			State:       updatedState,
   887  			Description: updatedDescription,
   888  			Owner:       updatedOwner,
   889  			Data:        updatedData,
   890  		},
   891  		&persistencespb.NamespaceConfig{
   892  			Retention:               updatedRetention,
   893  			HistoryArchivalState:    updatedHistoryArchivalState,
   894  			HistoryArchivalUri:      updatedHistoryArchivalURI,
   895  			VisibilityArchivalState: updatedVisibilityArchivalState,
   896  			VisibilityArchivalUri:   updatedVisibilityArchivalURI,
   897  			BadBinaries:             testBinaries,
   898  		},
   899  		&persistencespb.NamespaceReplicationConfig{
   900  			ActiveClusterName: updateClusterActive,
   901  			Clusters:          updateClusters,
   902  		},
   903  		updateConfigVersion,
   904  		updateFailoverVersion,
   905  		updateFailoverNotificationVersion,
   906  		failoverEndTime,
   907  		notificationVersion,
   908  		isGlobalNamespace,
   909  	)
   910  	m.NoError(err3)
   911  
   912  	resp4, err4 := m.GetNamespace("", name)
   913  	m.NoError(err4)
   914  	m.NotNil(resp4)
   915  	m.EqualValues(id, resp4.Namespace.Info.Id)
   916  	m.Equal(name, resp4.Namespace.Info.Name)
   917  	m.Equal(isGlobalNamespace, resp4.IsGlobalNamespace)
   918  	m.Equal(updatedState, resp4.Namespace.Info.State)
   919  	m.Equal(updatedDescription, resp4.Namespace.Info.Description)
   920  	m.Equal(updatedOwner, resp4.Namespace.Info.Owner)
   921  	m.Equal(updatedData, resp4.Namespace.Info.Data)
   922  	m.ProtoEqual(updatedRetention, resp4.Namespace.Config.Retention)
   923  	m.Equal(updatedHistoryArchivalState, resp4.Namespace.Config.HistoryArchivalState)
   924  	m.Equal(updatedHistoryArchivalURI, resp4.Namespace.Config.HistoryArchivalUri)
   925  	m.Equal(updatedVisibilityArchivalState, resp4.Namespace.Config.VisibilityArchivalState)
   926  	m.Equal(updatedVisibilityArchivalURI, resp4.Namespace.Config.VisibilityArchivalUri)
   927  	m.ProtoEqual(testBinaries, resp4.Namespace.Config.BadBinaries)
   928  	m.Equal(updateClusterActive, resp4.Namespace.ReplicationConfig.ActiveClusterName)
   929  	m.Equal(len(updateClusters), len(resp4.Namespace.ReplicationConfig.Clusters))
   930  	for index := range clusters {
   931  		m.Equal(updateClusters[index], resp4.Namespace.ReplicationConfig.Clusters[index])
   932  	}
   933  	m.Equal(updateConfigVersion, resp4.Namespace.ConfigVersion)
   934  	m.Equal(updateFailoverVersion, resp4.Namespace.FailoverVersion)
   935  	m.Equal(updateFailoverNotificationVersion, resp4.Namespace.FailoverNotificationVersion)
   936  	m.Equal(notificationVersion, resp4.NotificationVersion)
   937  	m.EqualTimes(failoverEndTime, resp4.Namespace.FailoverEndTime.AsTime())
   938  
   939  	resp5, err5 := m.GetNamespace(id, "")
   940  	m.NoError(err5)
   941  	m.NotNil(resp5)
   942  	m.EqualValues(id, resp5.Namespace.Info.Id)
   943  	m.Equal(name, resp5.Namespace.Info.Name)
   944  	m.Equal(isGlobalNamespace, resp5.IsGlobalNamespace)
   945  	m.Equal(updatedState, resp5.Namespace.Info.State)
   946  	m.Equal(updatedDescription, resp5.Namespace.Info.Description)
   947  	m.Equal(updatedOwner, resp5.Namespace.Info.Owner)
   948  	m.Equal(updatedData, resp5.Namespace.Info.Data)
   949  	m.ProtoEqual(updatedRetention, resp5.Namespace.Config.Retention)
   950  	m.Equal(updatedHistoryArchivalState, resp5.Namespace.Config.HistoryArchivalState)
   951  	m.Equal(updatedHistoryArchivalURI, resp5.Namespace.Config.HistoryArchivalUri)
   952  	m.Equal(updatedVisibilityArchivalState, resp5.Namespace.Config.VisibilityArchivalState)
   953  	m.Equal(updatedVisibilityArchivalURI, resp5.Namespace.Config.VisibilityArchivalUri)
   954  	m.Equal(updateClusterActive, resp5.Namespace.ReplicationConfig.ActiveClusterName)
   955  	m.Equal(len(updateClusters), len(resp5.Namespace.ReplicationConfig.Clusters))
   956  	for index := range clusters {
   957  		m.Equal(updateClusters[index], resp5.Namespace.ReplicationConfig.Clusters[index])
   958  	}
   959  	m.Equal(updateConfigVersion, resp5.Namespace.ConfigVersion)
   960  	m.Equal(updateFailoverVersion, resp5.Namespace.FailoverVersion)
   961  	m.Equal(updateFailoverNotificationVersion, resp5.Namespace.FailoverNotificationVersion)
   962  	m.Equal(notificationVersion, resp5.NotificationVersion)
   963  	m.EqualTimes(failoverEndTime, resp4.Namespace.FailoverEndTime.AsTime())
   964  
   965  	notificationVersion++
   966  	err6 := m.UpdateNamespace(
   967  		&persistencespb.NamespaceInfo{
   968  			Id:          resp2.Namespace.Info.Id,
   969  			Name:        resp2.Namespace.Info.Name,
   970  			State:       updatedState,
   971  			Description: updatedDescription,
   972  			Owner:       updatedOwner,
   973  			Data:        updatedData,
   974  		},
   975  		&persistencespb.NamespaceConfig{
   976  			Retention:               updatedRetention,
   977  			HistoryArchivalState:    updatedHistoryArchivalState,
   978  			HistoryArchivalUri:      updatedHistoryArchivalURI,
   979  			VisibilityArchivalState: updatedVisibilityArchivalState,
   980  			VisibilityArchivalUri:   updatedVisibilityArchivalURI,
   981  			BadBinaries:             testBinaries,
   982  		},
   983  		&persistencespb.NamespaceReplicationConfig{
   984  			ActiveClusterName: updateClusterActive,
   985  			Clusters:          updateClusters,
   986  		},
   987  		updateConfigVersion,
   988  		updateFailoverVersion,
   989  		updateFailoverNotificationVersion,
   990  		time.Time{},
   991  		notificationVersion,
   992  		isGlobalNamespace,
   993  	)
   994  	m.NoError(err6)
   995  
   996  	resp6, err6 := m.GetNamespace(id, "")
   997  	m.NoError(err6)
   998  	m.NotNil(resp6)
   999  	m.EqualValues(id, resp6.Namespace.Info.Id)
  1000  	m.Equal(name, resp6.Namespace.Info.Name)
  1001  	m.Equal(isGlobalNamespace, resp6.IsGlobalNamespace)
  1002  	m.Equal(updatedState, resp6.Namespace.Info.State)
  1003  	m.Equal(updatedDescription, resp6.Namespace.Info.Description)
  1004  	m.Equal(updatedOwner, resp6.Namespace.Info.Owner)
  1005  	m.Equal(updatedData, resp6.Namespace.Info.Data)
  1006  	m.ProtoEqual(updatedRetention, resp6.Namespace.Config.Retention)
  1007  	m.Equal(updatedHistoryArchivalState, resp6.Namespace.Config.HistoryArchivalState)
  1008  	m.Equal(updatedHistoryArchivalURI, resp6.Namespace.Config.HistoryArchivalUri)
  1009  	m.Equal(updatedVisibilityArchivalState, resp6.Namespace.Config.VisibilityArchivalState)
  1010  	m.Equal(updatedVisibilityArchivalURI, resp6.Namespace.Config.VisibilityArchivalUri)
  1011  	m.ProtoEqual(testBinaries, resp6.Namespace.Config.BadBinaries)
  1012  	m.Equal(updateClusterActive, resp6.Namespace.ReplicationConfig.ActiveClusterName)
  1013  	m.Equal(len(updateClusters), len(resp6.Namespace.ReplicationConfig.Clusters))
  1014  	for index := range clusters {
  1015  		m.Equal(updateClusters[index], resp4.Namespace.ReplicationConfig.Clusters[index])
  1016  	}
  1017  	m.Equal(updateConfigVersion, resp6.Namespace.ConfigVersion)
  1018  	m.Equal(updateFailoverVersion, resp6.Namespace.FailoverVersion)
  1019  	m.Equal(updateFailoverNotificationVersion, resp6.Namespace.FailoverNotificationVersion)
  1020  	m.Equal(notificationVersion, resp6.NotificationVersion)
  1021  	m.EqualTimes(time.Unix(0, 0).UTC(), resp6.Namespace.FailoverEndTime.AsTime())
  1022  }
  1023  
  1024  func (m *MetadataPersistenceSuiteV2) TestRenameNamespace() {
  1025  	id := uuid.New()
  1026  	name := "rename-namespace-test-name"
  1027  	newName := "rename-namespace-test-new-name"
  1028  	newNewName := "rename-namespace-test-new-new-name"
  1029  	state := enumspb.NAMESPACE_STATE_REGISTERED
  1030  	description := "rename-namespace-test-description"
  1031  	owner := "rename-namespace-test-owner"
  1032  	data := map[string]string{"k1": "v1"}
  1033  	retention := int32(10)
  1034  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
  1035  	historyArchivalURI := "test://history/uri"
  1036  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
  1037  	visibilityArchivalURI := "test://visibility/uri"
  1038  
  1039  	clusterActive := "some random active cluster name"
  1040  	clusterStandby := "some random standby cluster name"
  1041  	configVersion := int64(10)
  1042  	failoverVersion := int64(59)
  1043  	isGlobalNamespace := true
  1044  	clusters := []string{clusterActive, clusterStandby}
  1045  
  1046  	resp1, err1 := m.CreateNamespace(
  1047  		&persistencespb.NamespaceInfo{
  1048  			Id:          id,
  1049  			Name:        name,
  1050  			State:       state,
  1051  			Description: description,
  1052  			Owner:       owner,
  1053  			Data:        data,
  1054  		},
  1055  		&persistencespb.NamespaceConfig{
  1056  			Retention:               timestamp.DurationFromDays(retention),
  1057  			HistoryArchivalState:    historyArchivalState,
  1058  			HistoryArchivalUri:      historyArchivalURI,
  1059  			VisibilityArchivalState: visibilityArchivalState,
  1060  			VisibilityArchivalUri:   visibilityArchivalURI,
  1061  		},
  1062  		&persistencespb.NamespaceReplicationConfig{
  1063  			ActiveClusterName: clusterActive,
  1064  			Clusters:          clusters,
  1065  		},
  1066  		isGlobalNamespace,
  1067  		configVersion,
  1068  		failoverVersion,
  1069  	)
  1070  	m.NoError(err1)
  1071  	m.EqualValues(id, resp1.ID)
  1072  
  1073  	_, err2 := m.GetNamespace(id, "")
  1074  	m.NoError(err2)
  1075  
  1076  	err3 := m.MetadataManager.RenameNamespace(m.ctx, &p.RenameNamespaceRequest{
  1077  		PreviousName: name,
  1078  		NewName:      newName,
  1079  	})
  1080  	m.NoError(err3)
  1081  
  1082  	resp4, err4 := m.GetNamespace("", newName)
  1083  	m.NoError(err4)
  1084  	m.NotNil(resp4)
  1085  	m.EqualValues(id, resp4.Namespace.Info.Id)
  1086  	m.Equal(newName, resp4.Namespace.Info.Name)
  1087  	m.Equal(isGlobalNamespace, resp4.IsGlobalNamespace)
  1088  
  1089  	resp5, err5 := m.GetNamespace(id, "")
  1090  	m.NoError(err5)
  1091  	m.NotNil(resp5)
  1092  	m.EqualValues(id, resp5.Namespace.Info.Id)
  1093  	m.Equal(newName, resp5.Namespace.Info.Name)
  1094  	m.Equal(isGlobalNamespace, resp5.IsGlobalNamespace)
  1095  
  1096  	err6 := m.MetadataManager.RenameNamespace(m.ctx, &p.RenameNamespaceRequest{
  1097  		PreviousName: newName,
  1098  		NewName:      newNewName,
  1099  	})
  1100  	m.NoError(err6)
  1101  
  1102  	resp6, err6 := m.GetNamespace(id, "")
  1103  	m.NoError(err6)
  1104  	m.NotNil(resp6)
  1105  	m.EqualValues(id, resp6.Namespace.Info.Id)
  1106  	m.Equal(newNewName, resp6.Namespace.Info.Name)
  1107  	m.Equal(isGlobalNamespace, resp6.IsGlobalNamespace)
  1108  }
  1109  
  1110  // TestDeleteNamespace test
  1111  func (m *MetadataPersistenceSuiteV2) TestDeleteNamespace() {
  1112  	id := uuid.New()
  1113  	name := "delete-namespace-test-name"
  1114  	state := enumspb.NAMESPACE_STATE_REGISTERED
  1115  	description := "delete-namespace-test-description"
  1116  	owner := "delete-namespace-test-owner"
  1117  	data := map[string]string{"k1": "v1"}
  1118  	retention := timestamp.DurationFromDays(10)
  1119  	historyArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
  1120  	historyArchivalURI := "test://history/uri"
  1121  	visibilityArchivalState := enumspb.ARCHIVAL_STATE_ENABLED
  1122  	visibilityArchivalURI := "test://visibility/uri"
  1123  
  1124  	clusterActive := "some random active cluster name"
  1125  	clusterStandby := "some random standby cluster name"
  1126  	configVersion := int64(10)
  1127  	failoverVersion := int64(59)
  1128  	isGlobalNamespace := true
  1129  	clusters := []string{clusterActive, clusterStandby}
  1130  
  1131  	resp1, err1 := m.CreateNamespace(
  1132  		&persistencespb.NamespaceInfo{
  1133  			Id:          id,
  1134  			Name:        name,
  1135  			State:       state,
  1136  			Description: description,
  1137  			Owner:       owner,
  1138  			Data:        data,
  1139  		},
  1140  		&persistencespb.NamespaceConfig{
  1141  			Retention:               retention,
  1142  			HistoryArchivalState:    historyArchivalState,
  1143  			HistoryArchivalUri:      historyArchivalURI,
  1144  			VisibilityArchivalState: visibilityArchivalState,
  1145  			VisibilityArchivalUri:   visibilityArchivalURI,
  1146  		},
  1147  		&persistencespb.NamespaceReplicationConfig{
  1148  			ActiveClusterName: clusterActive,
  1149  			Clusters:          clusters,
  1150  		},
  1151  		isGlobalNamespace,
  1152  		configVersion,
  1153  		failoverVersion,
  1154  	)
  1155  	m.NoError(err1)
  1156  	m.EqualValues(id, resp1.ID)
  1157  
  1158  	resp2, err2 := m.GetNamespace("", name)
  1159  	m.NoError(err2)
  1160  	m.NotNil(resp2)
  1161  
  1162  	err3 := m.DeleteNamespace("", name)
  1163  	m.NoError(err3)
  1164  
  1165  	// May need to loop here to avoid potential inconsistent read-after-write in cassandra
  1166  	var err4 error
  1167  	var resp4 *p.GetNamespaceResponse
  1168  	for i := 0; i < 3; i++ {
  1169  		resp4, err4 = m.GetNamespace("", name)
  1170  		if err4 != nil {
  1171  			break
  1172  		}
  1173  		time.Sleep(time.Second * time.Duration(i))
  1174  	}
  1175  	m.Error(err4)
  1176  	m.IsType(&serviceerror.NamespaceNotFound{}, err4)
  1177  	m.Nil(resp4)
  1178  
  1179  	resp5, err5 := m.GetNamespace(id, "")
  1180  	m.Error(err5)
  1181  	m.IsType(&serviceerror.NamespaceNotFound{}, err5)
  1182  	m.Nil(resp5)
  1183  
  1184  	id = uuid.New()
  1185  	resp6, err6 := m.CreateNamespace(
  1186  		&persistencespb.NamespaceInfo{
  1187  			Id:          id,
  1188  			Name:        name,
  1189  			State:       state,
  1190  			Description: description,
  1191  			Owner:       owner,
  1192  			Data:        data,
  1193  		},
  1194  		&persistencespb.NamespaceConfig{
  1195  			Retention:               retention,
  1196  			HistoryArchivalState:    historyArchivalState,
  1197  			HistoryArchivalUri:      historyArchivalURI,
  1198  			VisibilityArchivalState: visibilityArchivalState,
  1199  			VisibilityArchivalUri:   visibilityArchivalURI,
  1200  		},
  1201  		&persistencespb.NamespaceReplicationConfig{
  1202  			ActiveClusterName: clusterActive,
  1203  			Clusters:          clusters,
  1204  		},
  1205  		isGlobalNamespace,
  1206  		configVersion,
  1207  		failoverVersion,
  1208  	)
  1209  	m.NoError(err6)
  1210  	m.EqualValues(id, resp6.ID)
  1211  
  1212  	err7 := m.DeleteNamespace(id, "")
  1213  	m.NoError(err7)
  1214  
  1215  	resp8, err8 := m.GetNamespace("", name)
  1216  	m.Error(err8)
  1217  	m.IsType(&serviceerror.NamespaceNotFound{}, err8)
  1218  	m.Nil(resp8)
  1219  
  1220  	resp9, err9 := m.GetNamespace(id, "")
  1221  	m.Error(err9)
  1222  	m.IsType(&serviceerror.NamespaceNotFound{}, err9)
  1223  	m.Nil(resp9)
  1224  }
  1225  
  1226  // TestListNamespaces test
  1227  func (m *MetadataPersistenceSuiteV2) TestListNamespaces() {
  1228  	clusterActive1 := "some random active cluster name"
  1229  	clusterStandby1 := "some random standby cluster name"
  1230  	clusters1 := []string{clusterActive1, clusterStandby1}
  1231  
  1232  	clusterActive2 := "other random active cluster name"
  1233  	clusterStandby2 := "other random standby cluster name"
  1234  	clusters2 := []string{clusterActive2, clusterStandby2}
  1235  
  1236  	testBinaries1 := &namespacepb.BadBinaries{
  1237  		Binaries: map[string]*namespacepb.BadBinaryInfo{
  1238  			"abc": {
  1239  				Reason:     "test-reason1",
  1240  				Operator:   "test-operator1",
  1241  				CreateTime: timestamppb.New(time.Date(2020, 8, 22, 0, 0, 0, 0, time.UTC)),
  1242  			},
  1243  		},
  1244  	}
  1245  	testBinaries2 := &namespacepb.BadBinaries{
  1246  		Binaries: map[string]*namespacepb.BadBinaryInfo{
  1247  			"efg": {
  1248  				Reason:     "test-reason2",
  1249  				Operator:   "test-operator2",
  1250  				CreateTime: timestamppb.New(time.Date(2020, 8, 22, 0, 0, 0, 0, time.UTC)),
  1251  			},
  1252  		},
  1253  	}
  1254  
  1255  	inputNamespaces := []*p.GetNamespaceResponse{
  1256  		{
  1257  			Namespace: &persistencespb.NamespaceDetail{
  1258  				Info: &persistencespb.NamespaceInfo{
  1259  					Id:          uuid.New(),
  1260  					Name:        "list-namespace-test-name-1",
  1261  					State:       enumspb.NAMESPACE_STATE_REGISTERED,
  1262  					Description: "list-namespace-test-description-1",
  1263  					Owner:       "list-namespace-test-owner-1",
  1264  					Data:        map[string]string{"k1": "v1"},
  1265  				},
  1266  				Config: &persistencespb.NamespaceConfig{
  1267  					Retention:               timestamp.DurationFromDays(109),
  1268  					HistoryArchivalState:    enumspb.ARCHIVAL_STATE_ENABLED,
  1269  					HistoryArchivalUri:      "test://history/uri",
  1270  					VisibilityArchivalState: enumspb.ARCHIVAL_STATE_ENABLED,
  1271  					VisibilityArchivalUri:   "test://visibility/uri",
  1272  					BadBinaries:             testBinaries1,
  1273  				},
  1274  				ReplicationConfig: &persistencespb.NamespaceReplicationConfig{
  1275  					ActiveClusterName: clusterActive1,
  1276  					Clusters:          clusters1,
  1277  				},
  1278  
  1279  				ConfigVersion:   133,
  1280  				FailoverVersion: 266,
  1281  			},
  1282  			IsGlobalNamespace: true,
  1283  		},
  1284  		{
  1285  			Namespace: &persistencespb.NamespaceDetail{
  1286  				Info: &persistencespb.NamespaceInfo{
  1287  					Id:          uuid.New(),
  1288  					Name:        "list-namespace-test-name-2",
  1289  					State:       enumspb.NAMESPACE_STATE_REGISTERED,
  1290  					Description: "list-namespace-test-description-2",
  1291  					Owner:       "list-namespace-test-owner-2",
  1292  					Data:        map[string]string{"k1": "v2"},
  1293  				},
  1294  				Config: &persistencespb.NamespaceConfig{
  1295  					Retention:               timestamp.DurationFromDays(326),
  1296  					HistoryArchivalState:    enumspb.ARCHIVAL_STATE_DISABLED,
  1297  					HistoryArchivalUri:      "",
  1298  					VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
  1299  					VisibilityArchivalUri:   "",
  1300  					BadBinaries:             testBinaries2,
  1301  				},
  1302  				ReplicationConfig: &persistencespb.NamespaceReplicationConfig{
  1303  					ActiveClusterName: clusterActive2,
  1304  					Clusters:          clusters2,
  1305  				},
  1306  				ConfigVersion:   400,
  1307  				FailoverVersion: 667,
  1308  			},
  1309  			IsGlobalNamespace: false,
  1310  		},
  1311  	}
  1312  	for _, namespace := range inputNamespaces {
  1313  		_, err := m.CreateNamespace(
  1314  			namespace.Namespace.Info,
  1315  			namespace.Namespace.Config,
  1316  			namespace.Namespace.ReplicationConfig,
  1317  			namespace.IsGlobalNamespace,
  1318  			namespace.Namespace.ConfigVersion,
  1319  			namespace.Namespace.FailoverVersion,
  1320  		)
  1321  		m.NoError(err)
  1322  	}
  1323  
  1324  	var token []byte
  1325  	const pageSize = 1
  1326  	pageCount := 0
  1327  	outputNamespaces := make(map[string]*p.GetNamespaceResponse)
  1328  	for {
  1329  		resp, err := m.ListNamespaces(pageSize, token)
  1330  		m.NoError(err)
  1331  		token = resp.NextPageToken
  1332  		for _, namespace := range resp.Namespaces {
  1333  			outputNamespaces[namespace.Namespace.Info.Id] = namespace
  1334  			// global notification version is already tested, so here we make it 0
  1335  			// so we can test == easily
  1336  			namespace.NotificationVersion = 0
  1337  		}
  1338  		pageCount++
  1339  		if len(token) == 0 {
  1340  			break
  1341  		}
  1342  	}
  1343  
  1344  	// 2 pages with data and 1 empty page which is unavoidable.
  1345  	m.Equal(pageCount, 3)
  1346  	m.Equal(len(inputNamespaces), len(outputNamespaces))
  1347  	for _, namespace := range inputNamespaces {
  1348  		m.DeepEqual(namespace, outputNamespaces[namespace.Namespace.Info.Id])
  1349  	}
  1350  }
  1351  
  1352  func (m *MetadataPersistenceSuiteV2) TestListNamespaces_DeletedNamespace() {
  1353  	inputNamespaces := []*p.GetNamespaceResponse{
  1354  		{
  1355  			Namespace: &persistencespb.NamespaceDetail{
  1356  				Info: &persistencespb.NamespaceInfo{
  1357  					Id:    uuid.New(),
  1358  					Name:  "list-namespace-test-name-1",
  1359  					State: enumspb.NAMESPACE_STATE_REGISTERED,
  1360  				},
  1361  				Config:            &persistencespb.NamespaceConfig{},
  1362  				ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
  1363  			},
  1364  		},
  1365  		{
  1366  			Namespace: &persistencespb.NamespaceDetail{
  1367  				Info: &persistencespb.NamespaceInfo{
  1368  					Id:    uuid.New(),
  1369  					Name:  "list-namespace-test-name-2",
  1370  					State: enumspb.NAMESPACE_STATE_DELETED,
  1371  				},
  1372  				Config:            &persistencespb.NamespaceConfig{},
  1373  				ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
  1374  			},
  1375  		},
  1376  		{
  1377  			Namespace: &persistencespb.NamespaceDetail{
  1378  				Info: &persistencespb.NamespaceInfo{
  1379  					Id:    uuid.New(),
  1380  					Name:  "list-namespace-test-name-3",
  1381  					State: enumspb.NAMESPACE_STATE_REGISTERED,
  1382  				},
  1383  				Config:            &persistencespb.NamespaceConfig{},
  1384  				ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
  1385  			},
  1386  		},
  1387  		{
  1388  			Namespace: &persistencespb.NamespaceDetail{
  1389  				Info: &persistencespb.NamespaceInfo{
  1390  					Id:    uuid.New(),
  1391  					Name:  "list-namespace-test-name-4",
  1392  					State: enumspb.NAMESPACE_STATE_DELETED,
  1393  				},
  1394  				Config:            &persistencespb.NamespaceConfig{},
  1395  				ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
  1396  			},
  1397  		},
  1398  	}
  1399  	for _, namespace := range inputNamespaces {
  1400  		_, err := m.CreateNamespace(
  1401  			namespace.Namespace.Info,
  1402  			namespace.Namespace.Config,
  1403  			namespace.Namespace.ReplicationConfig,
  1404  			namespace.IsGlobalNamespace,
  1405  			namespace.Namespace.ConfigVersion,
  1406  			namespace.Namespace.FailoverVersion,
  1407  		)
  1408  		m.NoError(err)
  1409  	}
  1410  
  1411  	var token []byte
  1412  	var listNamespacesPageSize2 []*p.GetNamespaceResponse
  1413  	pageCount := 0
  1414  	for {
  1415  		resp, err := m.ListNamespaces(2, token)
  1416  		m.NoError(err)
  1417  		token = resp.NextPageToken
  1418  		listNamespacesPageSize2 = append(listNamespacesPageSize2, resp.Namespaces...)
  1419  		pageCount++
  1420  		if len(token) == 0 {
  1421  			break
  1422  		}
  1423  	}
  1424  
  1425  	// 1 page with data and 1 empty page which is unavoidable.
  1426  	m.Equal(2, pageCount)
  1427  	m.Len(listNamespacesPageSize2, 2)
  1428  	for _, namespace := range listNamespacesPageSize2 {
  1429  		m.NotEqual(namespace.Namespace.Info.State, enumspb.NAMESPACE_STATE_DELETED)
  1430  	}
  1431  
  1432  	pageCount = 0
  1433  	var listNamespacesPageSize1 []*p.GetNamespaceResponse
  1434  	for {
  1435  		resp, err := m.ListNamespaces(1, token)
  1436  		m.NoError(err)
  1437  		token = resp.NextPageToken
  1438  		listNamespacesPageSize1 = append(listNamespacesPageSize1, resp.Namespaces...)
  1439  		pageCount++
  1440  		if len(token) == 0 {
  1441  			break
  1442  		}
  1443  	}
  1444  
  1445  	// 2 pages with data and 1 empty page which is unavoidable.
  1446  	m.Equal(3, pageCount)
  1447  	m.Len(listNamespacesPageSize1, 2)
  1448  	for _, namespace := range listNamespacesPageSize1 {
  1449  		m.NotEqual(namespace.Namespace.Info.State, enumspb.NAMESPACE_STATE_DELETED)
  1450  	}
  1451  }
  1452  
  1453  // CreateNamespace helper method
  1454  func (m *MetadataPersistenceSuiteV2) CreateNamespace(info *persistencespb.NamespaceInfo, config *persistencespb.NamespaceConfig,
  1455  	replicationConfig *persistencespb.NamespaceReplicationConfig, isGlobalnamespace bool, configVersion int64, failoverVersion int64) (*p.CreateNamespaceResponse, error) {
  1456  	return m.MetadataManager.CreateNamespace(m.ctx, &p.CreateNamespaceRequest{
  1457  		Namespace: &persistencespb.NamespaceDetail{
  1458  			Info:              info,
  1459  			Config:            config,
  1460  			ReplicationConfig: replicationConfig,
  1461  
  1462  			ConfigVersion:   configVersion,
  1463  			FailoverVersion: failoverVersion,
  1464  		}, IsGlobalNamespace: isGlobalnamespace,
  1465  	})
  1466  }
  1467  
  1468  // GetNamespace helper method
  1469  func (m *MetadataPersistenceSuiteV2) GetNamespace(id string, name string) (*p.GetNamespaceResponse, error) {
  1470  	return m.MetadataManager.GetNamespace(m.ctx, &p.GetNamespaceRequest{
  1471  		ID:   id,
  1472  		Name: name,
  1473  	})
  1474  }
  1475  
  1476  // UpdateNamespace helper method
  1477  func (m *MetadataPersistenceSuiteV2) UpdateNamespace(
  1478  	info *persistencespb.NamespaceInfo,
  1479  	config *persistencespb.NamespaceConfig,
  1480  	replicationConfig *persistencespb.NamespaceReplicationConfig,
  1481  	configVersion int64,
  1482  	failoverVersion int64,
  1483  	failoverNotificationVersion int64,
  1484  	failoverEndTime time.Time,
  1485  	notificationVersion int64,
  1486  	isGlobalNamespace bool,
  1487  ) error {
  1488  	return m.MetadataManager.UpdateNamespace(m.ctx, &p.UpdateNamespaceRequest{
  1489  		Namespace: &persistencespb.NamespaceDetail{
  1490  			Info:                        info,
  1491  			Config:                      config,
  1492  			ReplicationConfig:           replicationConfig,
  1493  			ConfigVersion:               configVersion,
  1494  			FailoverVersion:             failoverVersion,
  1495  			FailoverEndTime:             timestamppb.New(failoverEndTime),
  1496  			FailoverNotificationVersion: failoverNotificationVersion,
  1497  		},
  1498  		NotificationVersion: notificationVersion,
  1499  		IsGlobalNamespace:   isGlobalNamespace,
  1500  	})
  1501  }
  1502  
  1503  // DeleteNamespace helper method
  1504  func (m *MetadataPersistenceSuiteV2) DeleteNamespace(id string, name string) error {
  1505  	if len(id) > 0 {
  1506  		return m.MetadataManager.DeleteNamespace(m.ctx, &p.DeleteNamespaceRequest{ID: id})
  1507  	}
  1508  	return m.MetadataManager.DeleteNamespaceByName(m.ctx, &p.DeleteNamespaceByNameRequest{Name: name})
  1509  }
  1510  
  1511  // ListNamespaces helper method
  1512  func (m *MetadataPersistenceSuiteV2) ListNamespaces(pageSize int, pageToken []byte) (*p.ListNamespacesResponse, error) {
  1513  	return m.MetadataManager.ListNamespaces(m.ctx, &p.ListNamespacesRequest{
  1514  		PageSize:      pageSize,
  1515  		NextPageToken: pageToken,
  1516  	})
  1517  }