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

     1  package keys
     2  
     3  import (
     4  	"github.com/authzed/spicedb/pkg/caveats"
     5  	v1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1"
     6  	"github.com/authzed/spicedb/pkg/spiceerrors"
     7  	"github.com/authzed/spicedb/pkg/tuple"
     8  )
     9  
    10  type dispatchCacheKeyHashComputeOption int
    11  
    12  const (
    13  	computeOnlyStableHash dispatchCacheKeyHashComputeOption = 0
    14  	computeBothHashes     dispatchCacheKeyHashComputeOption = 1
    15  )
    16  
    17  // cachePrefix defines a unique prefix for a type of cache key.
    18  type cachePrefix string
    19  
    20  // Define the various prefixes for the cache entries. These must *all* be unique and must *all*
    21  // also be placed into the cachePrefixes slice below.
    22  const (
    23  	checkViaRelationPrefix   cachePrefix = "cr"
    24  	checkViaCanonicalPrefix  cachePrefix = "cc"
    25  	lookupPrefix             cachePrefix = "l"
    26  	expandPrefix             cachePrefix = "e"
    27  	reachableResourcesPrefix cachePrefix = "rr"
    28  	lookupSubjectsPrefix     cachePrefix = "ls"
    29  )
    30  
    31  var cachePrefixes = []cachePrefix{
    32  	checkViaRelationPrefix,
    33  	checkViaCanonicalPrefix,
    34  	lookupPrefix,
    35  	expandPrefix,
    36  	reachableResourcesPrefix,
    37  	lookupSubjectsPrefix,
    38  }
    39  
    40  // checkRequestToKey converts a check request into a cache key based on the relation
    41  func checkRequestToKey(req *v1.DispatchCheckRequest, option dispatchCacheKeyHashComputeOption) DispatchCacheKey {
    42  	return dispatchCacheKeyHash(checkViaRelationPrefix, req.Metadata.AtRevision, option,
    43  		hashableRelationReference{req.ResourceRelation},
    44  		hashableIds(req.ResourceIds),
    45  		hashableOnr{req.Subject},
    46  		hashableResultSetting(req.ResultsSetting),
    47  	)
    48  }
    49  
    50  // checkRequestToKeyWithCanonical converts a check request into a cache key based
    51  // on the canonical key.
    52  func checkRequestToKeyWithCanonical(req *v1.DispatchCheckRequest, canonicalKey string) (DispatchCacheKey, error) {
    53  	// NOTE: canonical cache keys are only unique *within* a version of a namespace.
    54  	cacheKey := dispatchCacheKeyHash(checkViaCanonicalPrefix, req.Metadata.AtRevision, computeBothHashes,
    55  		hashableString(req.ResourceRelation.Namespace),
    56  		hashableString(canonicalKey),
    57  		hashableIds(req.ResourceIds),
    58  		hashableOnr{req.Subject},
    59  		hashableResultSetting(req.ResultsSetting),
    60  	)
    61  
    62  	if canonicalKey == "" {
    63  		return cacheKey, spiceerrors.MustBugf("given empty canonical key for request: %s => %s", req.ResourceRelation, tuple.StringONR(req.Subject))
    64  	}
    65  
    66  	return cacheKey, nil
    67  }
    68  
    69  // expandRequestToKey converts an expand request into a cache key
    70  func expandRequestToKey(req *v1.DispatchExpandRequest, option dispatchCacheKeyHashComputeOption) DispatchCacheKey {
    71  	return dispatchCacheKeyHash(expandPrefix, req.Metadata.AtRevision, option,
    72  		hashableOnr{req.ResourceAndRelation},
    73  	)
    74  }
    75  
    76  // reachableResourcesRequestToKey converts a reachable resources request into a cache key
    77  func reachableResourcesRequestToKey(req *v1.DispatchReachableResourcesRequest, option dispatchCacheKeyHashComputeOption) DispatchCacheKey {
    78  	return dispatchCacheKeyHash(reachableResourcesPrefix, req.Metadata.AtRevision, option,
    79  		hashableRelationReference{req.ResourceRelation},
    80  		hashableRelationReference{req.SubjectRelation},
    81  		hashableIds(req.SubjectIds),
    82  		hashableCursor{req.OptionalCursor},
    83  		hashableLimit(req.OptionalLimit),
    84  	)
    85  }
    86  
    87  // lookupResourcesRequestToKey converts a lookup request into a cache key
    88  func lookupResourcesRequestToKey(req *v1.DispatchLookupResourcesRequest, option dispatchCacheKeyHashComputeOption) DispatchCacheKey {
    89  	return dispatchCacheKeyHash(lookupPrefix, req.Metadata.AtRevision, option,
    90  		hashableRelationReference{req.ObjectRelation},
    91  		hashableOnr{req.Subject},
    92  		hashableContext{HashableContext: caveats.HashableContext{Struct: req.Context}}, // NOTE: context is included here because lookup does a single dispatch
    93  		hashableCursor{req.OptionalCursor},
    94  		hashableLimit(req.OptionalLimit),
    95  	)
    96  }
    97  
    98  // lookupSubjectsRequestToKey converts a lookup subjects request into a cache key
    99  func lookupSubjectsRequestToKey(req *v1.DispatchLookupSubjectsRequest, option dispatchCacheKeyHashComputeOption) DispatchCacheKey {
   100  	return dispatchCacheKeyHash(lookupSubjectsPrefix, req.Metadata.AtRevision, option,
   101  		hashableRelationReference{req.ResourceRelation},
   102  		hashableRelationReference{req.SubjectRelation},
   103  		hashableIds(req.ResourceIds),
   104  		hashableCursor{req.OptionalCursor},
   105  		hashableLimit(req.OptionalLimit),
   106  	)
   107  }