feat: gamemaster

This commit is contained in:
Ilia Denisov
2026-05-03 07:59:03 +02:00
committed by GitHub
parent a7cee15115
commit 3e2622757e
229 changed files with 41521 additions and 1098 deletions
@@ -0,0 +1,38 @@
// Package redisstate hosts the Game Master Redis adapters that share a
// single keyspace. The sole sibling subpackage in v1 is
// `streamoffsets` (the per-consumer offset for the
// runtime:health_events stream); membership cache lives in process and
// does not touch Redis.
//
// The package itself only declares the keyspace; concrete stores live
// in nested packages so dependencies (miniredis, testcontainers) stay
// out of consumer build graphs that do not need them.
package redisstate
import "encoding/base64"
// defaultPrefix is the mandatory `gamemaster:` namespace prefix shared
// by every Game Master Redis key.
const defaultPrefix = "gamemaster:"
// Keyspace builds the Game Master Redis keys. The namespace covers
// stream consumer offsets in v1.
//
// Dynamic key segments are encoded with base64url so raw key structure
// does not depend on caller-provided characters; this matches the
// encoding chosen by `lobby/internal/adapters/redisstate.Keyspace` and
// `rtmanager/internal/adapters/redisstate.Keyspace`.
type Keyspace struct{}
// StreamOffset returns the Redis key that stores the last successfully
// processed entry id for one Redis Stream consumer. The streamLabel is
// the short logical identifier of the consumer (e.g. `health_events`),
// not the full stream name; it stays stable when the underlying stream
// key is renamed.
func (Keyspace) StreamOffset(streamLabel string) string {
return defaultPrefix + "stream_offsets:" + encodeKeyComponent(streamLabel)
}
func encodeKeyComponent(value string) string {
return base64.RawURLEncoding.EncodeToString([]byte(value))
}