go.temporal.io/server@v1.23.0/common/cluster/metadata_test.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2021 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2021 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  package cluster
    25  
    26  import (
    27  	"context"
    28  	"testing"
    29  	"time"
    30  
    31  	"go.temporal.io/server/common/dynamicconfig"
    32  
    33  	"github.com/golang/mock/gomock"
    34  	"github.com/pborman/uuid"
    35  	"github.com/stretchr/testify/require"
    36  	"github.com/stretchr/testify/suite"
    37  
    38  	persistencespb "go.temporal.io/server/api/persistence/v1"
    39  	"go.temporal.io/server/common/log"
    40  	"go.temporal.io/server/common/persistence"
    41  )
    42  
    43  type (
    44  	metadataSuite struct {
    45  		suite.Suite
    46  		*require.Assertions
    47  
    48  		controller               *gomock.Controller
    49  		mockClusterMetadataStore *persistence.MockClusterMetadataManager
    50  		metadata                 *metadataImpl
    51  
    52  		isGlobalNamespaceEnabled bool
    53  		failoverVersionIncrement int64
    54  		clusterName              string
    55  		secondClusterName        string
    56  		thirdClusterName         string
    57  	}
    58  )
    59  
    60  func TestMetadataSuite(t *testing.T) {
    61  	s := new(metadataSuite)
    62  	suite.Run(t, s)
    63  }
    64  
    65  func (s *metadataSuite) SetupSuite() {
    66  }
    67  
    68  func (s *metadataSuite) TearDownSuite() {
    69  
    70  }
    71  
    72  func (s *metadataSuite) SetupTest() {
    73  	s.Assertions = require.New(s.T())
    74  	s.controller = gomock.NewController(s.T())
    75  	s.mockClusterMetadataStore = persistence.NewMockClusterMetadataManager(s.controller)
    76  
    77  	s.isGlobalNamespaceEnabled = true
    78  	s.failoverVersionIncrement = 100
    79  	s.clusterName = uuid.New()
    80  	s.secondClusterName = uuid.New()
    81  	s.thirdClusterName = uuid.New()
    82  
    83  	clusterInfo := map[string]ClusterInformation{
    84  		s.clusterName: {
    85  			Enabled:                true,
    86  			InitialFailoverVersion: int64(1),
    87  			RPCAddress:             uuid.New(),
    88  			ShardCount:             1,
    89  			version:                1,
    90  		},
    91  		s.secondClusterName: {
    92  			Enabled:                true,
    93  			InitialFailoverVersion: int64(4),
    94  			RPCAddress:             uuid.New(),
    95  			ShardCount:             2,
    96  			version:                1,
    97  		},
    98  		s.thirdClusterName: {
    99  			Enabled:                true,
   100  			InitialFailoverVersion: int64(5),
   101  			RPCAddress:             uuid.New(),
   102  			ShardCount:             1,
   103  			version:                1,
   104  		},
   105  	}
   106  	s.metadata = NewMetadata(
   107  		s.isGlobalNamespaceEnabled,
   108  		s.failoverVersionIncrement,
   109  		s.clusterName,
   110  		s.clusterName,
   111  		clusterInfo,
   112  		s.mockClusterMetadataStore,
   113  		dynamicconfig.GetDurationPropertyFn(time.Second),
   114  		log.NewNoopLogger(),
   115  	).(*metadataImpl)
   116  }
   117  
   118  func (s *metadataSuite) TearDownTest() {
   119  	s.controller.Finish()
   120  }
   121  
   122  func (s *metadataSuite) Test_Initialization() {
   123  	s.Equal(s.isGlobalNamespaceEnabled, s.metadata.IsGlobalNamespaceEnabled())
   124  	s.Equal(s.clusterName, s.metadata.GetMasterClusterName())
   125  	s.Equal(s.clusterName, s.metadata.GetCurrentClusterName())
   126  	s.True(s.metadata.IsMasterCluster())
   127  	s.Equal(s.failoverVersionIncrement, s.metadata.GetFailoverVersionIncrement())
   128  }
   129  
   130  func (s *metadataSuite) Test_GetNextFailoverVersion() {
   131  	currentVersion := int64(102)
   132  	s.Equal(currentVersion+s.failoverVersionIncrement-1, s.metadata.GetNextFailoverVersion(s.clusterName, currentVersion))
   133  }
   134  
   135  func (s *metadataSuite) Test_IsVersionFromSameCluster() {
   136  	s.True(s.metadata.IsVersionFromSameCluster(101, 1001))
   137  	s.False(s.metadata.IsVersionFromSameCluster(101, 103))
   138  }
   139  
   140  func (s *metadataSuite) Test_ClusterNameForFailoverVersion() {
   141  	clusterName := s.metadata.ClusterNameForFailoverVersion(true, 101)
   142  	s.Equal(s.clusterName, clusterName)
   143  
   144  	clusterName2 := s.metadata.ClusterNameForFailoverVersion(true, 204)
   145  	s.Equal(s.secondClusterName, clusterName2)
   146  
   147  	clusterName3 := s.metadata.ClusterNameForFailoverVersion(true, 217)
   148  	s.Equal(unknownClusterNamePrefix+"17", clusterName3)
   149  }
   150  
   151  func (s *metadataSuite) Test_RegisterMetadataChangeCallback() {
   152  	s.metadata.RegisterMetadataChangeCallback(
   153  		s,
   154  		func(oldClusterMetadata map[string]*ClusterInformation, newClusterMetadata map[string]*ClusterInformation) {
   155  			s.Equal(3, len(newClusterMetadata))
   156  		})
   157  
   158  	s.metadata.UnRegisterMetadataChangeCallback(s)
   159  	s.Equal(0, len(s.metadata.clusterChangeCallback))
   160  }
   161  
   162  func (s *metadataSuite) Test_RefreshClusterMetadata_Success() {
   163  	id := uuid.New()
   164  	s.metadata.clusterChangeCallback[id] = func(oldClusterMetadata map[string]*ClusterInformation, newClusterMetadata map[string]*ClusterInformation) {
   165  		oldMetadata, ok := oldClusterMetadata[id]
   166  		s.True(ok)
   167  		s.Nil(oldMetadata)
   168  		newMetadata, ok := newClusterMetadata[id]
   169  		s.True(ok)
   170  		s.NotNil(newMetadata)
   171  
   172  		oldMetadata, ok = oldClusterMetadata[s.secondClusterName]
   173  		s.True(ok)
   174  		s.NotNil(oldMetadata)
   175  		newMetadata, ok = newClusterMetadata[s.secondClusterName]
   176  		s.True(ok)
   177  		s.Nil(newMetadata)
   178  
   179  		oldMetadata, ok = oldClusterMetadata[s.thirdClusterName]
   180  		s.True(ok)
   181  		s.NotNil(oldMetadata)
   182  		newMetadata, ok = newClusterMetadata[s.thirdClusterName]
   183  		s.True(ok)
   184  		s.NotNil(newMetadata)
   185  	}
   186  
   187  	s.mockClusterMetadataStore.EXPECT().ListClusterMetadata(gomock.Any(), gomock.Any()).Return(
   188  		&persistence.ListClusterMetadataResponse{
   189  			ClusterMetadata: []*persistence.GetClusterMetadataResponse{
   190  				{
   191  					// No change and not include in callback
   192  					ClusterMetadata: &persistencespb.ClusterMetadata{
   193  						ClusterName:            s.clusterName,
   194  						IsConnectionEnabled:    true,
   195  						InitialFailoverVersion: 1,
   196  						HistoryShardCount:      1,
   197  						ClusterAddress:         uuid.New(),
   198  					},
   199  					Version: 1,
   200  				},
   201  				{
   202  					// Updated, included in callback
   203  					ClusterMetadata: &persistencespb.ClusterMetadata{
   204  						ClusterName:            s.thirdClusterName,
   205  						IsConnectionEnabled:    true,
   206  						InitialFailoverVersion: 1,
   207  						HistoryShardCount:      1,
   208  						ClusterAddress:         uuid.New(),
   209  						Tags:                   map[string]string{"test": "test"},
   210  					},
   211  					Version: 2,
   212  				},
   213  				{
   214  					// Newly added, included in callback
   215  					ClusterMetadata: &persistencespb.ClusterMetadata{
   216  						ClusterName:            id,
   217  						IsConnectionEnabled:    true,
   218  						InitialFailoverVersion: 2,
   219  						HistoryShardCount:      2,
   220  						ClusterAddress:         uuid.New(),
   221  						Tags:                   map[string]string{"test": "test"},
   222  					},
   223  					Version: 2,
   224  				},
   225  			},
   226  		}, nil)
   227  	err := s.metadata.refreshClusterMetadata(context.Background())
   228  	s.NoError(err)
   229  	clusterInfo := s.metadata.GetAllClusterInfo()
   230  	s.Equal("test", clusterInfo[s.thirdClusterName].Tags["test"])
   231  	s.Equal("test", clusterInfo[id].Tags["test"])
   232  }
   233  
   234  func (s *metadataSuite) Test_ListAllClusterMetadataFromDB_Success() {
   235  	nextPageSizeToken := []byte{1}
   236  	newClusterName := uuid.New()
   237  	s.mockClusterMetadataStore.EXPECT().ListClusterMetadata(gomock.Any(), &persistence.ListClusterMetadataRequest{
   238  		PageSize:      defaultClusterMetadataPageSize,
   239  		NextPageToken: nil,
   240  	}).Return(
   241  		&persistence.ListClusterMetadataResponse{
   242  			ClusterMetadata: []*persistence.GetClusterMetadataResponse{
   243  				{
   244  					ClusterMetadata: &persistencespb.ClusterMetadata{
   245  						ClusterName:            s.clusterName,
   246  						IsConnectionEnabled:    true,
   247  						InitialFailoverVersion: 1,
   248  						HistoryShardCount:      1,
   249  						ClusterAddress:         uuid.New(),
   250  					},
   251  					Version: 1,
   252  				},
   253  			},
   254  			NextPageToken: nextPageSizeToken,
   255  		}, nil).Times(1)
   256  	s.mockClusterMetadataStore.EXPECT().ListClusterMetadata(gomock.Any(), &persistence.ListClusterMetadataRequest{
   257  		PageSize:      defaultClusterMetadataPageSize,
   258  		NextPageToken: nextPageSizeToken,
   259  	}).Return(
   260  		&persistence.ListClusterMetadataResponse{
   261  			ClusterMetadata: []*persistence.GetClusterMetadataResponse{
   262  				{
   263  					ClusterMetadata: &persistencespb.ClusterMetadata{
   264  						ClusterName:            newClusterName,
   265  						IsConnectionEnabled:    true,
   266  						InitialFailoverVersion: 2,
   267  						HistoryShardCount:      2,
   268  						ClusterAddress:         uuid.New(),
   269  					},
   270  					Version: 2,
   271  				},
   272  			},
   273  		}, nil).Times(1)
   274  
   275  	resp, err := s.metadata.listAllClusterMetadataFromDB(context.Background())
   276  	s.NoError(err)
   277  	s.Equal(2, len(resp))
   278  }