go.temporal.io/server@v1.23.0/common/persistence/client/factory.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 client
    26  
    27  import (
    28  	"go.temporal.io/api/serviceerror"
    29  	"go.temporal.io/server/common"
    30  	"go.temporal.io/server/common/config"
    31  	"go.temporal.io/server/common/log"
    32  	"go.temporal.io/server/common/metrics"
    33  	p "go.temporal.io/server/common/persistence"
    34  	"go.temporal.io/server/common/persistence/serialization"
    35  	"go.temporal.io/server/common/quotas"
    36  )
    37  
    38  var (
    39  	retryPolicy = common.CreatePersistenceClientRetryPolicy()
    40  )
    41  
    42  type (
    43  	// Factory defines the interface for any implementation that can vend
    44  	// persistence layer objects backed by a datastore. The actual datastore
    45  	// is implementation detail hidden behind this interface
    46  	Factory interface {
    47  		// Close the factory
    48  		Close()
    49  		// NewTaskManager returns a new task manager
    50  		NewTaskManager() (p.TaskManager, error)
    51  		// NewShardManager returns a new shard manager
    52  		NewShardManager() (p.ShardManager, error)
    53  		// NewMetadataManager returns a new metadata manager
    54  		NewMetadataManager() (p.MetadataManager, error)
    55  		// NewExecutionManager returns a new execution manager
    56  		NewExecutionManager() (p.ExecutionManager, error)
    57  		// NewNamespaceReplicationQueue returns a new queue for namespace replication
    58  		NewNamespaceReplicationQueue() (p.NamespaceReplicationQueue, error)
    59  		// NewClusterMetadataManager returns a new manager for cluster specific metadata
    60  		NewClusterMetadataManager() (p.ClusterMetadataManager, error)
    61  		// NewHistoryTaskQueueManager returns a new manager for history task queues
    62  		NewHistoryTaskQueueManager() (p.HistoryTaskQueueManager, error)
    63  	}
    64  
    65  	factoryImpl struct {
    66  		dataStoreFactory DataStoreFactory
    67  		config           *config.Persistence
    68  		serializer       serialization.Serializer
    69  		eventBlobCache   p.XDCCache
    70  		metricsHandler   metrics.Handler
    71  		logger           log.Logger
    72  		clusterName      string
    73  		ratelimiter      quotas.RequestRateLimiter
    74  		healthSignals    p.HealthSignalAggregator
    75  	}
    76  )
    77  
    78  // NewFactory returns an implementation of factory that vends persistence objects based on
    79  // specified configuration. This factory takes as input a config.Persistence object
    80  // which specifies the datastore to be used for a given type of object. This config
    81  // also contains config for individual datastores themselves.
    82  //
    83  // The objects returned by this factory enforce ratelimit and maxconns according to
    84  // given configuration. In addition, all objects will emit metrics automatically
    85  func NewFactory(
    86  	dataStoreFactory DataStoreFactory,
    87  	cfg *config.Persistence,
    88  	ratelimiter quotas.RequestRateLimiter,
    89  	serializer serialization.Serializer,
    90  	eventBlobCache p.XDCCache,
    91  	clusterName string,
    92  	metricsHandler metrics.Handler,
    93  	logger log.Logger,
    94  	healthSignals p.HealthSignalAggregator,
    95  ) Factory {
    96  	factory := &factoryImpl{
    97  		dataStoreFactory: dataStoreFactory,
    98  		config:           cfg,
    99  		serializer:       serializer,
   100  		eventBlobCache:   eventBlobCache,
   101  		metricsHandler:   metricsHandler,
   102  		logger:           logger,
   103  		clusterName:      clusterName,
   104  		ratelimiter:      ratelimiter,
   105  		healthSignals:    healthSignals,
   106  	}
   107  	factory.initDependencies()
   108  	return factory
   109  }
   110  
   111  // NewTaskManager returns a new task manager
   112  func (f *factoryImpl) NewTaskManager() (p.TaskManager, error) {
   113  	taskStore, err := f.dataStoreFactory.NewTaskStore()
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	result := p.NewTaskManager(taskStore, f.serializer)
   119  	if f.ratelimiter != nil {
   120  		result = p.NewTaskPersistenceRateLimitedClient(result, f.ratelimiter, f.logger)
   121  	}
   122  	if f.metricsHandler != nil && f.healthSignals != nil {
   123  		result = p.NewTaskPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger)
   124  	}
   125  	result = p.NewTaskPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
   126  	return result, nil
   127  }
   128  
   129  // NewShardManager returns a new shard manager
   130  func (f *factoryImpl) NewShardManager() (p.ShardManager, error) {
   131  	shardStore, err := f.dataStoreFactory.NewShardStore()
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  
   136  	result := p.NewShardManager(shardStore, f.serializer)
   137  	if f.ratelimiter != nil {
   138  		result = p.NewShardPersistenceRateLimitedClient(result, f.ratelimiter, f.logger)
   139  	}
   140  	if f.metricsHandler != nil && f.healthSignals != nil {
   141  		result = p.NewShardPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger)
   142  	}
   143  	result = p.NewShardPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
   144  	return result, nil
   145  }
   146  
   147  // NewMetadataManager returns a new metadata manager
   148  func (f *factoryImpl) NewMetadataManager() (p.MetadataManager, error) {
   149  	store, err := f.dataStoreFactory.NewMetadataStore()
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  
   154  	result := p.NewMetadataManagerImpl(store, f.serializer, f.logger, f.clusterName)
   155  	if f.ratelimiter != nil {
   156  		result = p.NewMetadataPersistenceRateLimitedClient(result, f.ratelimiter, f.logger)
   157  	}
   158  	if f.metricsHandler != nil && f.healthSignals != nil {
   159  		result = p.NewMetadataPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger)
   160  	}
   161  	result = p.NewMetadataPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
   162  	return result, nil
   163  }
   164  
   165  // NewClusterMetadataManager returns a new cluster metadata manager
   166  func (f *factoryImpl) NewClusterMetadataManager() (p.ClusterMetadataManager, error) {
   167  	store, err := f.dataStoreFactory.NewClusterMetadataStore()
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  
   172  	result := p.NewClusterMetadataManagerImpl(store, f.serializer, f.clusterName, f.logger)
   173  	if f.ratelimiter != nil {
   174  		result = p.NewClusterMetadataPersistenceRateLimitedClient(result, f.ratelimiter, f.logger)
   175  	}
   176  	if f.metricsHandler != nil && f.healthSignals != nil {
   177  		result = p.NewClusterMetadataPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger)
   178  	}
   179  	result = p.NewClusterMetadataPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
   180  	return result, nil
   181  }
   182  
   183  // NewExecutionManager returns a new execution manager
   184  func (f *factoryImpl) NewExecutionManager() (p.ExecutionManager, error) {
   185  	store, err := f.dataStoreFactory.NewExecutionStore()
   186  	if err != nil {
   187  		return nil, err
   188  	}
   189  
   190  	result := p.NewExecutionManager(store, f.serializer, f.eventBlobCache, f.logger, f.config.TransactionSizeLimit)
   191  	if f.ratelimiter != nil {
   192  		result = p.NewExecutionPersistenceRateLimitedClient(result, f.ratelimiter, f.logger)
   193  	}
   194  	if f.metricsHandler != nil && f.healthSignals != nil {
   195  		result = p.NewExecutionPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger)
   196  	}
   197  	result = p.NewExecutionPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
   198  	return result, nil
   199  }
   200  
   201  func (f *factoryImpl) NewNamespaceReplicationQueue() (p.NamespaceReplicationQueue, error) {
   202  	result, err := f.dataStoreFactory.NewQueue(p.NamespaceReplicationQueueType)
   203  	if err != nil {
   204  		return nil, err
   205  	}
   206  
   207  	if f.ratelimiter != nil {
   208  		result = p.NewQueuePersistenceRateLimitedClient(result, f.ratelimiter, f.logger)
   209  	}
   210  	if f.metricsHandler != nil && f.healthSignals != nil {
   211  		result = p.NewQueuePersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger)
   212  	}
   213  	result = p.NewQueuePersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
   214  	return p.NewNamespaceReplicationQueue(result, f.serializer, f.clusterName, f.metricsHandler, f.logger)
   215  }
   216  
   217  func (f *factoryImpl) NewHistoryTaskQueueManager() (p.HistoryTaskQueueManager, error) {
   218  	q, err := f.dataStoreFactory.NewQueueV2()
   219  	if err != nil {
   220  		return nil, err
   221  	}
   222  	return p.NewHistoryTaskQueueManager(q), nil
   223  }
   224  
   225  // Close closes this factory
   226  func (f *factoryImpl) Close() {
   227  	f.dataStoreFactory.Close()
   228  	if f.healthSignals != nil {
   229  		f.healthSignals.Stop()
   230  	}
   231  }
   232  
   233  func IsPersistenceTransientError(err error) bool {
   234  	switch err.(type) {
   235  	case *serviceerror.Unavailable:
   236  		return true
   237  	}
   238  
   239  	return false
   240  }
   241  
   242  func (f *factoryImpl) initDependencies() {
   243  	if f.metricsHandler == nil && f.healthSignals == nil {
   244  		return
   245  	}
   246  
   247  	if f.metricsHandler == nil {
   248  		f.metricsHandler = metrics.NoopMetricsHandler
   249  	}
   250  	if f.healthSignals == nil {
   251  		f.healthSignals = p.NoopHealthSignalAggregator
   252  	}
   253  	f.healthSignals.Start()
   254  }