// 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)) }