github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/dispatch/cluster/cluster.go (about)

     1  package cluster
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/authzed/spicedb/internal/dispatch"
     7  	"github.com/authzed/spicedb/internal/dispatch/caching"
     8  	"github.com/authzed/spicedb/internal/dispatch/graph"
     9  	"github.com/authzed/spicedb/internal/dispatch/keys"
    10  	"github.com/authzed/spicedb/pkg/cache"
    11  )
    12  
    13  // Option is a function-style option for configuring a combined Dispatcher.
    14  type Option func(*optionState)
    15  
    16  type optionState struct {
    17  	metricsEnabled        bool
    18  	prometheusSubsystem   string
    19  	cache                 cache.Cache
    20  	concurrencyLimits     graph.ConcurrencyLimits
    21  	remoteDispatchTimeout time.Duration
    22  }
    23  
    24  // MetricsEnabled enables issuing prometheus metrics
    25  func MetricsEnabled(enabled bool) Option {
    26  	return func(state *optionState) {
    27  		state.metricsEnabled = enabled
    28  	}
    29  }
    30  
    31  // PrometheusSubsystem sets the subsystem name for the prometheus metrics
    32  func PrometheusSubsystem(name string) Option {
    33  	return func(state *optionState) {
    34  		state.prometheusSubsystem = name
    35  	}
    36  }
    37  
    38  // Cache sets the cache for the remote dispatcher.
    39  func Cache(c cache.Cache) Option {
    40  	return func(state *optionState) {
    41  		state.cache = c
    42  	}
    43  }
    44  
    45  // ConcurrencyLimits sets the max number of goroutines per operation
    46  func ConcurrencyLimits(limits graph.ConcurrencyLimits) Option {
    47  	return func(state *optionState) {
    48  		state.concurrencyLimits = limits
    49  	}
    50  }
    51  
    52  // RemoteDispatchTimeout sets the maximum timeout for a remote dispatch.
    53  // Defaults to 60s (as defined in the remote dispatcher).
    54  func RemoteDispatchTimeout(remoteDispatchTimeout time.Duration) Option {
    55  	return func(state *optionState) {
    56  		state.remoteDispatchTimeout = remoteDispatchTimeout
    57  	}
    58  }
    59  
    60  // NewClusterDispatcher takes a dispatcher (such as one created by
    61  // combined.NewDispatcher) and returns a cluster dispatcher suitable for use as
    62  // the dispatcher for the dispatch grpc server.
    63  func NewClusterDispatcher(dispatch dispatch.Dispatcher, options ...Option) (dispatch.Dispatcher, error) {
    64  	var opts optionState
    65  	for _, fn := range options {
    66  		fn(&opts)
    67  	}
    68  
    69  	clusterDispatch := graph.NewDispatcher(dispatch, opts.concurrencyLimits)
    70  
    71  	if opts.prometheusSubsystem == "" {
    72  		opts.prometheusSubsystem = "dispatch"
    73  	}
    74  
    75  	cachingClusterDispatch, err := caching.NewCachingDispatcher(opts.cache, opts.metricsEnabled, opts.prometheusSubsystem, &keys.CanonicalKeyHandler{})
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	cachingClusterDispatch.SetDelegate(clusterDispatch)
    80  	return cachingClusterDispatch, nil
    81  }