Documentation
¶
Overview ¶
Package cache holds an endpoint's answers, compressed, until a model they read is rebuilt.
INVALIDATED BY THE DATA, NOT BY THE CLOCK. Every key folds in the generation of each model the endpoint's SQL reads -- written by `brevis-sql build` when it rebuilds one -- so the first request after a rebuild is a miss and every one before it is a hit, however long that is. The ttl is a ceiling for the day a build forgets to write a generation, not the thing that refreshes an answer.
A CACHE NEVER FAILS A REQUEST. Redis unreachable is a request answered from the warehouse and counted; the caller is owed an answer, not an opinion about the cache.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Decompress ¶
Decompress is a stored answer for a caller that does not accept Brotli.
func Key ¶
func Key(api, connection, endpoint, tenant, sql string, args []dialect.Arg, generations []string, shape string) string
Key is where one answer lives.
A HASH OF LENGTH-PREFIXED PARTS, so no two different inputs can concatenate alike: a tenant ending in what an endpoint begins with is a different pair, not the same string. The argument's Go type is in it, so the int 1 and the string "1" are two answers. The `{brevis}` hash tag keeps every key on one Redis Cluster slot, beside the generations.
THE API AND ITS CONNECTION ARE IN IT. Found in the ship review: two APIs share one Redis by design -- the generations live there -- and staging and production serving an `orders` endpoint with the same SQL answered each other's rows. The API's name is in the prefix, so one API's entries can be flushed alone; the connection's identity is in the hash.
AND SO IS THE SHAPE: which after hook made the answer, and in which build -- empty when none did. The same rows are a different answer through a different hook, or through the same name after a deploy changed it.
Types ¶
type Group ¶
type Group[T any] struct { // contains filtered or unexported fields }
Group runs one function per key at a time, and hands its result to every caller that asked meanwhile -- the misses after a rebuild, collapsed.
x/sync's singleflight, in thirty lines, for the reason the Redis client is in this module: a dependency is a conversation, and this is not one worth having.
type KV ¶
type KV interface {
Get(ctx context.Context, key string) ([]byte, bool, error)
Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
MGet(ctx context.Context, keys ...string) ([][]byte, error)
}
KV is the three commands this needs, which generation.Client has.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is one API's cache.
func New ¶
New is a store over kv. ttl is every entry's ceiling; maxEntry is the most compressed bytes one answer may take.
func (*Store) Generations ¶
Generations is each model's current generation, in one round trip.