github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/datastore/proxy/singleflight.go (about)

     1  package proxy
     2  
     3  import (
     4  	"context"
     5  
     6  	"resenje.org/singleflight"
     7  
     8  	"github.com/authzed/spicedb/pkg/datastore"
     9  	"github.com/authzed/spicedb/pkg/datastore/options"
    10  )
    11  
    12  // NewSingleflightDatastoreProxy creates a new Datastore proxy which
    13  // deduplicates calls to Datastore methods that can share results.
    14  func NewSingleflightDatastoreProxy(d datastore.Datastore) datastore.Datastore {
    15  	return &singleflightProxy{delegate: d}
    16  }
    17  
    18  type singleflightProxy struct {
    19  	headRevGroup  singleflight.Group[string, datastore.Revision]
    20  	optRevGroup   singleflight.Group[string, datastore.Revision]
    21  	checkRevGroup singleflight.Group[string, string]
    22  	statsGroup    singleflight.Group[string, datastore.Stats]
    23  	delegate      datastore.Datastore
    24  }
    25  
    26  var _ datastore.Datastore = (*singleflightProxy)(nil)
    27  
    28  func (p *singleflightProxy) SnapshotReader(rev datastore.Revision) datastore.Reader {
    29  	return p.delegate.SnapshotReader(rev)
    30  }
    31  
    32  func (p *singleflightProxy) ReadWriteTx(ctx context.Context, f datastore.TxUserFunc, opts ...options.RWTOptionsOption) (datastore.Revision, error) {
    33  	return p.delegate.ReadWriteTx(ctx, f, opts...)
    34  }
    35  
    36  func (p *singleflightProxy) OptimizedRevision(ctx context.Context) (datastore.Revision, error) {
    37  	rev, _, err := p.optRevGroup.Do(ctx, "", func(ctx context.Context) (datastore.Revision, error) {
    38  		return p.delegate.OptimizedRevision(ctx)
    39  	})
    40  	return rev, err
    41  }
    42  
    43  func (p *singleflightProxy) CheckRevision(ctx context.Context, revision datastore.Revision) error {
    44  	_, _, err := p.checkRevGroup.Do(ctx, revision.String(), func(ctx context.Context) (string, error) {
    45  		return "", p.delegate.CheckRevision(ctx, revision)
    46  	})
    47  	return err
    48  }
    49  
    50  func (p *singleflightProxy) HeadRevision(ctx context.Context) (datastore.Revision, error) {
    51  	rev, _, err := p.headRevGroup.Do(ctx, "", func(ctx context.Context) (datastore.Revision, error) {
    52  		return p.delegate.HeadRevision(ctx)
    53  	})
    54  	return rev, err
    55  }
    56  
    57  func (p *singleflightProxy) RevisionFromString(serialized string) (datastore.Revision, error) {
    58  	return p.delegate.RevisionFromString(serialized)
    59  }
    60  
    61  func (p *singleflightProxy) Watch(ctx context.Context, afterRevision datastore.Revision, options datastore.WatchOptions) (<-chan *datastore.RevisionChanges, <-chan error) {
    62  	return p.delegate.Watch(ctx, afterRevision, options)
    63  }
    64  
    65  func (p *singleflightProxy) Statistics(ctx context.Context) (datastore.Stats, error) {
    66  	stats, _, err := p.statsGroup.Do(ctx, "", func(ctx context.Context) (datastore.Stats, error) {
    67  		return p.delegate.Statistics(ctx)
    68  	})
    69  	return stats, err
    70  }
    71  
    72  func (p *singleflightProxy) Features(ctx context.Context) (*datastore.Features, error) {
    73  	return p.delegate.Features(ctx)
    74  }
    75  
    76  func (p *singleflightProxy) ReadyState(ctx context.Context) (datastore.ReadyState, error) {
    77  	return p.delegate.ReadyState(ctx)
    78  }
    79  
    80  func (p *singleflightProxy) Close() error                { return p.delegate.Close() }
    81  func (p *singleflightProxy) Unwrap() datastore.Datastore { return p.delegate }