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  }