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 }