Documentation
¶
Overview ¶
Package valkey is the Valkey driver of the legacy adapter (internal/port/legacy): the connection, its failover handling, and the one State that the issuer's logins in progress, the hub's snapshots and the refresh leases are all kept in.
Business code does not import it: it names the ports of internal/port.
Nothing here is a source of truth. Everything in this store can be rebuilt by reading the directory again, which is what makes it safe to lose: an empty cache is a hub with no snapshots, which answers "not authoritative" until the next refresh, and a non-authoritative answer removes nobody's access.
Index ¶
- Constants
- func Revision(value []byte) string
- type Config
- type Entry
- type Outcome
- type State
- func (s *State) Add(ctx context.Context, key, member string, ttl time.Duration) error
- func (s *State) Close() error
- func (s *State) Delete(ctx context.Context, key string) error
- func (s *State) DropIf(ctx context.Context, key, expected string) (Outcome, error)
- func (s *State) Dump(ctx context.Context, prefix string) ([]Entry, error)
- func (s *State) Get(ctx context.Context, key string) ([]byte, bool, error)
- func (s *State) Keys(ctx context.Context, prefix string) ([]string, error)
- func (s *State) Members(ctx context.Context, key string) ([]string, error)
- func (s *State) Ping(ctx context.Context) error
- func (s *State) Remove(ctx context.Context, key, member string) error
- func (s *State) Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
- func (s *State) SetIfAbsent(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error)
- func (s *State) Swap(ctx context.Context, key, expected string, value []byte, ttl time.Duration) (Outcome, error)
Constants ¶
const DefaultTTL = 7 * 24 * time.Hour
DefaultTTL is how long a snapshot outlives its last write.
It is not the freshness window — that is the hub's, and much shorter. This is only so that a workspace disconnected while a replica was down does not leave a copy of a company's directory sitting in a cache for ever.
Variables ¶
This section is empty.
Functions ¶
func Revision ¶
Revision is what State calls a value's version: the SHA-256 of its bytes. It is a content tag, not a counter -- Valkey keeps no version of a key, and adding one would change what is written -- and it lives only in the process that read the value, between that read and the conditional write that follows: it is never stored. The comparison with the live value is made in Go, and the script then re-checks the bytes themselves.
Types ¶
type Config ¶
type Config struct {
// Address is host:port. Empty means "no Valkey": the caller keeps
// snapshots in memory instead.
Address string
// Password is optional.
Password string
// TLS turns on TLS to the server.
TLS bool
// Cluster speaks the cluster protocol. The fleet's Valkeys are
// ValkeyClusters even at one shard, so this is the usual answer; a
// plain single server needs it off, and a mismatch shows up as a
// refused command at start rather than as a subtle failure later.
Cluster bool
// Prefix namespaces every key, so that one Valkey can serve more than
// one installation.
Prefix string
// TTL overrides DefaultTTL.
TTL time.Duration
}
Config is how to reach the Valkey the deployment points at.
type Entry ¶
type Entry struct {
Key string
// Set is true for a set; Members is then its members and Value is nil.
Set bool
Value []byte
Members []string
// TTL is the remaining lifetime; 0 is none.
TTL time.Duration
}
Entry is one key as State.Dump reads it: a string value or a set of members, with what is left of its lifetime.
type Outcome ¶
type Outcome int
Outcome is what a conditional write did.
const ( // Gone: there was no live value to compare. Gone Outcome = -1 // Moved: the value's revision was not the one expected. Moved Outcome = 0 // Done: the condition held and the command ran. Done Outcome = 1 )
The outcomes of State.Swap and State.DropIf.
type State ¶
type State struct {
// contains filtered or unexported fields
}
State is a login in progress, shared by every replica: the authorization request a browser is part-way through, the code it comes back with, the tokens that follow, the device flow a CLI is polling.
It is here rather than in the issuer because the issuer must not know what a cache is, and here rather than beside the snapshots because the two have nothing to do with each other beyond the address they dial. Everything carries its own expiry, so nothing sweeps.
func NewState ¶
func NewState(client redis.UniversalClient, prefix string) *State
NewState wraps a client that is already open. For tests.
func OpenState ¶
OpenState connects and proves it can talk, so that a misconfigured address is a startup failure rather than a failed login.
func (*State) Add ¶
Add implements issuer.State.
SADD then EXPIRE, and the expiry is refreshed on every add: a set of sessions should outlive its newest member, not its oldest. Without the refresh an identity that signs in daily would have its whole index vanish on the anniversary of its first login.
func (*State) Delete ¶
Delete implements issuer.State.
func (*State) Dump ¶
Dump reads every key that starts with prefix, strings and sets, with the lifetime each has left, sorted by key. A key of another type is skipped, and one that expires between the scan and the read is gone. It is a SCAN, for an operator and not a request: it is what `sluis migrate` copies a login state with.
func (*State) Get ¶
Get implements issuer.State.
func (*State) Keys ¶
Keys lists the keys that start with prefix, sorted, without this State's own namespace. It is a SCAN of every primary: right for a listing an operator or a watcher asks for, and not a path a request takes.
func (*State) Members ¶
Members implements issuer.State.
func (*State) Ping ¶
Ping reports whether the store answers. See [Snapshots.Ping] for why this is readiness and never liveness.
func (*State) Remove ¶
Remove implements issuer.State.
func (*State) Set ¶
Set implements issuer.State.
func (*State) SetIfAbsent ¶
func (s *State) SetIfAbsent( ctx context.Context, key string, value []byte, ttl time.Duration, ) (bool, error)
SetIfAbsent implements issuer.State.
func (*State) Swap ¶
func (s *State) Swap(ctx context.Context, key, expected string, value []byte, ttl time.Duration) (Outcome, error)
Swap replaces the value at key with a new one for ttl, only if the current value's Revision is expected. It is one script, so two replicas swapping from one revision cannot both win.