go.temporal.io/server@v1.23.0/common/persistence/cluster_metadata_store.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 persistence 26 27 import ( 28 "context" 29 "errors" 30 31 enumspb "go.temporal.io/api/enums/v1" 32 "go.temporal.io/api/serviceerror" 33 34 persistencespb "go.temporal.io/server/api/persistence/v1" 35 "go.temporal.io/server/common/log" 36 "go.temporal.io/server/common/persistence/serialization" 37 ) 38 39 const ( 40 clusterMetadataEncoding = enumspb.ENCODING_TYPE_PROTO3 41 ) 42 43 var ( 44 // ErrInvalidMembershipExpiry is used when upserting new cluster membership with an invalid duration 45 ErrInvalidMembershipExpiry = errors.New("membershipExpiry duration should be atleast 1 second") 46 47 // ErrIncompleteMembershipUpsert is used when upserting new cluster membership with missing fields 48 ErrIncompleteMembershipUpsert = errors.New("membership upserts require all fields") 49 ) 50 51 type ( 52 // clusterMetadataManagerImpl implements MetadataManager based on MetadataStore and Serializer 53 clusterMetadataManagerImpl struct { 54 serializer serialization.Serializer 55 persistence ClusterMetadataStore 56 currentClusterName string 57 logger log.Logger 58 } 59 ) 60 61 var _ ClusterMetadataManager = (*clusterMetadataManagerImpl)(nil) 62 63 // NewClusterMetadataManagerImpl returns new ClusterMetadataManager 64 func NewClusterMetadataManagerImpl( 65 persistence ClusterMetadataStore, 66 serializer serialization.Serializer, 67 currentClusterName string, 68 logger log.Logger, 69 ) ClusterMetadataManager { 70 return &clusterMetadataManagerImpl{ 71 serializer: serializer, 72 persistence: persistence, 73 currentClusterName: currentClusterName, 74 logger: logger, 75 } 76 } 77 78 func (m *clusterMetadataManagerImpl) GetName() string { 79 return m.persistence.GetName() 80 } 81 82 func (m *clusterMetadataManagerImpl) Close() { 83 m.persistence.Close() 84 } 85 86 func (m *clusterMetadataManagerImpl) GetClusterMembers( 87 ctx context.Context, 88 request *GetClusterMembersRequest, 89 ) (*GetClusterMembersResponse, error) { 90 return m.persistence.GetClusterMembers(ctx, request) 91 } 92 93 func (m *clusterMetadataManagerImpl) UpsertClusterMembership( 94 ctx context.Context, 95 request *UpsertClusterMembershipRequest, 96 ) error { 97 if request.RecordExpiry.Seconds() < 1 { 98 return ErrInvalidMembershipExpiry 99 } 100 if request.Role == All { 101 return ErrIncompleteMembershipUpsert 102 } 103 if request.RPCAddress == nil { 104 return ErrIncompleteMembershipUpsert 105 } 106 if request.RPCPort == 0 { 107 return ErrIncompleteMembershipUpsert 108 } 109 if request.SessionStart.IsZero() { 110 return ErrIncompleteMembershipUpsert 111 } 112 113 return m.persistence.UpsertClusterMembership(ctx, request) 114 } 115 116 func (m *clusterMetadataManagerImpl) PruneClusterMembership( 117 ctx context.Context, 118 request *PruneClusterMembershipRequest, 119 ) error { 120 return m.persistence.PruneClusterMembership(ctx, request) 121 } 122 123 func (m *clusterMetadataManagerImpl) ListClusterMetadata( 124 ctx context.Context, 125 request *ListClusterMetadataRequest, 126 ) (*ListClusterMetadataResponse, error) { 127 resp, err := m.persistence.ListClusterMetadata(ctx, &InternalListClusterMetadataRequest{ 128 PageSize: request.PageSize, 129 NextPageToken: request.NextPageToken, 130 }) 131 if err != nil { 132 return nil, err 133 } 134 135 clusterMetadata := make([]*GetClusterMetadataResponse, 0, len(resp.ClusterMetadata)) 136 for _, cm := range resp.ClusterMetadata { 137 res, err := m.convertInternalGetClusterMetadataResponse(cm) 138 if err != nil { 139 return nil, err 140 } 141 clusterMetadata = append(clusterMetadata, res) 142 } 143 return &ListClusterMetadataResponse{ClusterMetadata: clusterMetadata, NextPageToken: resp.NextPageToken}, nil 144 } 145 146 func (m *clusterMetadataManagerImpl) GetCurrentClusterMetadata( 147 ctx context.Context, 148 ) (*GetClusterMetadataResponse, error) { 149 resp, err := m.persistence.GetClusterMetadata(ctx, &InternalGetClusterMetadataRequest{ClusterName: m.currentClusterName}) 150 if err != nil { 151 return nil, err 152 } 153 154 mcm, err := m.serializer.DeserializeClusterMetadata(resp.ClusterMetadata) 155 if err != nil { 156 return nil, err 157 } 158 return &GetClusterMetadataResponse{ClusterMetadata: mcm, Version: resp.Version}, nil 159 } 160 161 func (m *clusterMetadataManagerImpl) GetClusterMetadata( 162 ctx context.Context, 163 request *GetClusterMetadataRequest, 164 ) (*GetClusterMetadataResponse, error) { 165 resp, err := m.persistence.GetClusterMetadata(ctx, &InternalGetClusterMetadataRequest{ClusterName: request.ClusterName}) 166 if err != nil { 167 return nil, err 168 } 169 170 mcm, err := m.serializer.DeserializeClusterMetadata(resp.ClusterMetadata) 171 if err != nil { 172 return nil, err 173 } 174 return &GetClusterMetadataResponse{ClusterMetadata: mcm, Version: resp.Version}, nil 175 } 176 177 func (m *clusterMetadataManagerImpl) SaveClusterMetadata( 178 ctx context.Context, 179 request *SaveClusterMetadataRequest, 180 ) (bool, error) { 181 mcm, err := m.serializer.SerializeClusterMetadata(request.ClusterMetadata, clusterMetadataEncoding) 182 if err != nil { 183 return false, err 184 } 185 186 oldClusterMetadata, err := m.GetClusterMetadata(ctx, &GetClusterMetadataRequest{ClusterName: request.GetClusterName()}) 187 if _, isNotFound := err.(*serviceerror.NotFound); isNotFound { 188 return m.persistence.SaveClusterMetadata(ctx, &InternalSaveClusterMetadataRequest{ 189 ClusterName: request.ClusterName, 190 ClusterMetadata: mcm, 191 Version: request.Version, 192 }) 193 } 194 if err != nil { 195 return false, err 196 } 197 if immutableFieldsChanged(oldClusterMetadata.ClusterMetadata, request.ClusterMetadata) { 198 return false, nil 199 } 200 201 return m.persistence.SaveClusterMetadata(ctx, &InternalSaveClusterMetadataRequest{ 202 ClusterName: request.ClusterName, 203 ClusterMetadata: mcm, 204 Version: request.Version, 205 }) 206 } 207 208 func (m *clusterMetadataManagerImpl) DeleteClusterMetadata( 209 ctx context.Context, 210 request *DeleteClusterMetadataRequest, 211 ) error { 212 if request.ClusterName == m.currentClusterName { 213 return serviceerror.NewInvalidArgument("Cannot delete current cluster metadata") 214 } 215 216 return m.persistence.DeleteClusterMetadata(ctx, &InternalDeleteClusterMetadataRequest{ClusterName: request.ClusterName}) 217 } 218 219 func (m *clusterMetadataManagerImpl) convertInternalGetClusterMetadataResponse( 220 resp *InternalGetClusterMetadataResponse, 221 ) (*GetClusterMetadataResponse, error) { 222 mcm, err := m.serializer.DeserializeClusterMetadata(resp.ClusterMetadata) 223 if err != nil { 224 return nil, err 225 } 226 227 return &GetClusterMetadataResponse{ 228 ClusterMetadata: mcm, 229 Version: resp.Version, 230 }, nil 231 } 232 233 // immutableFieldsChanged returns true if any of immutable fields changed. 234 func immutableFieldsChanged(old *persistencespb.ClusterMetadata, cur *persistencespb.ClusterMetadata) bool { 235 if (old.ClusterName != "" && old.ClusterName != cur.ClusterName) || 236 (old.ClusterId != "" && old.ClusterId != cur.ClusterId) || 237 (old.HistoryShardCount != 0 && old.HistoryShardCount != cur.HistoryShardCount) || 238 (old.IsGlobalNamespaceEnabled && !cur.IsGlobalNamespaceEnabled) { 239 return true 240 } 241 if old.IsGlobalNamespaceEnabled { 242 if (old.FailoverVersionIncrement != 0 && old.FailoverVersionIncrement != cur.FailoverVersionIncrement) || 243 (old.InitialFailoverVersion != 0 && old.InitialFailoverVersion != cur.InitialFailoverVersion) { 244 return true 245 } 246 } 247 return false 248 }