refactor(store): align AX examples and terminology

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-03-30 18:49:17 +00:00
parent a80e352b43
commit 4edd7dd0ca
8 changed files with 43 additions and 43 deletions

View file

@ -30,19 +30,19 @@ func main() {
}
defer storeInstance.Close()
if err := storeInstance.Set("config", "theme", "dark"); err != nil {
if err := storeInstance.Set("config", "colour", "blue"); err != nil {
return
}
if err := storeInstance.SetWithTTL("session", "token", "abc123", 24*time.Hour); err != nil {
return
}
themeValue, err := storeInstance.Get("config", "theme")
colourValue, err := storeInstance.Get("config", "colour")
if err != nil {
return
}
fmt.Println(themeValue)
fmt.Println(colourValue)
// Watch "config" changes and print each event as it arrives.
// Watch "config" mutations and print each event as it arrives.
watcher := storeInstance.Watch("config", "*")
defer storeInstance.Unwatch(watcher)
go func() {
@ -51,12 +51,12 @@ func main() {
}
}()
// Prefix tenant-42 preferences with "tenant-42:".
// Store tenant-42 preferences under the "tenant-42:" prefix.
scopedStore, err := store.NewScoped(storeInstance, "tenant-42")
if err != nil {
return
}
if err := scopedStore.Set("prefs", "locale", "en-GB"); err != nil {
if err := scopedStore.Set("preferences", "locale", "en-GB"); err != nil {
return
}
}

10
doc.go
View file

@ -10,20 +10,20 @@
// }
// defer storeInstance.Close()
//
// if err := storeInstance.Set("config", "theme", "dark"); err != nil {
// if err := storeInstance.Set("config", "colour", "blue"); err != nil {
// return
// }
// themeValue, err := storeInstance.Get("config", "theme")
// colourValue, err := storeInstance.Get("config", "colour")
// if err != nil {
// return
// }
// fmt.Println(themeValue)
// fmt.Println(colourValue)
//
// scopedStore, err := store.NewScoped(storeInstance, "tenant-a")
// if err != nil {
// return
// }
// if err := scopedStore.Set("config", "theme", "dark"); err != nil {
// if err := scopedStore.Set("config", "colour", "blue"); err != nil {
// return
// }
//
@ -31,7 +31,7 @@
// if err != nil {
// return
// }
// if err := quotaScopedStore.Set("prefs", "locale", "en-GB"); err != nil {
// if err := quotaScopedStore.Set("preferences", "locale", "en-GB"); err != nil {
// return
// }
//

View file

@ -157,7 +157,7 @@ func main() {
if err != nil {
return
}
if err := scopedStore.Set("prefs", "locale", "en-GB"); err != nil {
if err := scopedStore.Set("preferences", "locale", "en-GB"); err != nil {
return
}
}

View file

@ -49,7 +49,7 @@ Keys are addressed by a two-level path: `(group, key)`. Groups act as logical na
This model maps naturally to domain concepts:
```
group: "user:42:config" key: "theme"
group: "user:42:config" key: "colour"
group: "user:42:config" key: "language"
group: "session:abc" key: "token"
```
@ -198,10 +198,10 @@ scopedStore, err := store.NewScoped(storeInstance, "tenant-42")
if err != nil {
return
}
if err := scopedStore.Set("config", "theme", "dark"); err != nil {
if err := scopedStore.Set("config", "colour", "blue"); err != nil {
return
}
// Stored in underlying store as group="tenant-42:config", key="theme"
// Stored in underlying store as group="tenant-42:config", key="colour"
```
Namespace strings must match `^[a-zA-Z0-9-]+$`. Invalid namespaces are rejected at construction time.

View file

@ -33,27 +33,27 @@ func main() {
}
defer storeInstance.Close()
// Store and read back a theme value.
if err := storeInstance.Set("config", "theme", "dark"); err != nil {
// Store "blue" under config/colour and read it back.
if err := storeInstance.Set("config", "colour", "blue"); err != nil {
return
}
themeValue, err := storeInstance.Get("config", "theme")
colourValue, err := storeInstance.Get("config", "colour")
if err != nil {
return
}
fmt.Println(themeValue) // "dark"
fmt.Println(colourValue) // "blue"
// Store a session token that expires after 24 hours.
if err := storeInstance.SetWithTTL("session", "token", "abc123", 24*time.Hour); err != nil {
return
}
// Read the config group into a map.
// Read config/colour back into a map.
configEntries, err := storeInstance.GetAll("config")
if err != nil {
return
}
fmt.Println(configEntries) // map[theme:dark]
fmt.Println(configEntries) // map[colour:blue]
// Render the mail host and port into smtp.example.com:587.
if err := storeInstance.Set("mail", "host", "smtp.example.com"); err != nil {
@ -68,15 +68,15 @@ func main() {
}
fmt.Println(renderedTemplate) // "smtp.example.com:587"
// Prefix tenant-42 preferences with tenant-42:.
// Store tenant-42 preferences under the tenant-42: namespace prefix.
scopedStore, err := store.NewScoped(storeInstance, "tenant-42")
if err != nil {
return
}
if err := scopedStore.Set("prefs", "locale", "en-GB"); err != nil {
if err := scopedStore.Set("preferences", "locale", "en-GB"); err != nil {
return
}
// Stored internally as group "tenant-42:prefs", key "locale"
// Stored internally as group "tenant-42:preferences", key "locale"
// Cap tenant-99 at 100 keys and 5 groups.
quotaScopedStore, err := store.NewScopedWithQuota(storeInstance, "tenant-99", store.QuotaConfig{MaxKeys: 100, MaxGroups: 5})

View file

@ -33,16 +33,16 @@ func (t EventType) String() string {
}
}
// Usage example: `event := store.Event{Type: store.EventSet, Group: "config", Key: "theme", Value: "dark"}`
// Usage example: `event := store.Event{Type: store.EventSet, Group: "config", Key: "colour", Value: "blue"}`
// Usage example: `event := store.Event{Type: store.EventDeleteGroup, Group: "config"}`
type Event struct {
// Usage example: `if event.Type == store.EventDeleteGroup { return }`
Type EventType
// Usage example: `if event.Group == "config" { return }`
Group string
// Usage example: `if event.Key == "theme" { return }`
// Usage example: `if event.Key == "colour" { return }`
Key string
// Usage example: `if event.Value == "dark" { return }`
// Usage example: `if event.Value == "blue" { return }`
Value string
// Usage example: `if event.Timestamp.IsZero() { return }`
Timestamp time.Time
@ -50,7 +50,7 @@ type Event struct {
// Usage example: `watcher := storeInstance.Watch("config", "*"); defer storeInstance.Unwatch(watcher); for event := range watcher.Events { if event.Type == EventDeleteGroup { return } }`
type Watcher struct {
// Usage example: `for event := range watcher.Events { if event.Key == "theme" { return } }`
// Usage example: `for event := range watcher.Events { if event.Key == "colour" { return } }`
Events <-chan Event
// eventChannel is the internal write channel (same underlying channel as Events).
@ -130,7 +130,7 @@ func (storeInstance *Store) OnChange(callback func(Event)) func() {
}
}
// notify(Event{Type: EventSet, Group: "config", Key: "theme", Value: "dark"})
// notify(Event{Type: EventSet, Group: "config", Key: "colour", Value: "blue"})
// dispatches matching watchers and callbacks after a successful write. If a
// watcher buffer is full, the event is dropped instead of blocking the writer.
// Callbacks are copied under a separate lock and invoked after the lock is
@ -160,7 +160,7 @@ func (storeInstance *Store) notify(event Event) {
}
// watcherMatches reports whether Watch("config", "*") should receive
// Event{Group: "config", Key: "theme"}.
// Event{Group: "config", Key: "colour"}.
func watcherMatches(watcher *Watcher, event Event) bool {
if watcher.group != "*" && watcher.group != event.Group {
return false

View file

@ -19,7 +19,7 @@ type QuotaConfig struct {
MaxGroups int
}
// Usage example: `scopedStore, err := store.NewScoped(storeInstance, "tenant-a"); if err != nil { return }; if err := scopedStore.Set("config", "theme", "dark"); err != nil { return }`
// Usage example: `scopedStore, err := store.NewScoped(storeInstance, "tenant-a"); if err != nil { return }; if err := scopedStore.Set("config", "colour", "blue"); err != nil { return }`
type ScopedStore struct {
storeInstance *Store
namespace string
@ -54,12 +54,12 @@ func (scopedStore *ScopedStore) Namespace() string {
return scopedStore.namespace
}
// Usage example: `themeValue, err := scopedStore.Get("config", "theme")`
// Usage example: `colourValue, err := scopedStore.Get("config", "colour")`
func (scopedStore *ScopedStore) Get(group, key string) (string, error) {
return scopedStore.storeInstance.Get(scopedStore.namespacedGroup(group), key)
}
// Usage example: `if err := scopedStore.Set("config", "theme", "dark"); err != nil { return }`
// Usage example: `if err := scopedStore.Set("config", "colour", "blue"); err != nil { return }`
func (scopedStore *ScopedStore) Set(group, key, value string) error {
if err := scopedStore.checkQuota("store.ScopedStore.Set", group, key); err != nil {
return err
@ -75,7 +75,7 @@ func (scopedStore *ScopedStore) SetWithTTL(group, key, value string, timeToLive
return scopedStore.storeInstance.SetWithTTL(scopedStore.namespacedGroup(group), key, value, timeToLive)
}
// Usage example: `if err := scopedStore.Delete("config", "theme"); err != nil { return }`
// Usage example: `if err := scopedStore.Delete("config", "colour"); err != nil { return }`
func (scopedStore *ScopedStore) Delete(group, key string) error {
return scopedStore.storeInstance.Delete(scopedStore.namespacedGroup(group), key)
}
@ -85,7 +85,7 @@ func (scopedStore *ScopedStore) DeleteGroup(group string) error {
return scopedStore.storeInstance.DeleteGroup(scopedStore.namespacedGroup(group))
}
// Usage example: `configEntries, err := scopedStore.GetAll("config")`
// Usage example: `colourEntries, err := scopedStore.GetAll("config")`
func (scopedStore *ScopedStore) GetAll(group string) (map[string]string, error) {
return scopedStore.storeInstance.GetAll(scopedStore.namespacedGroup(group))
}
@ -105,7 +105,7 @@ func (scopedStore *ScopedStore) Render(templateSource, group string) (string, er
return scopedStore.storeInstance.Render(templateSource, scopedStore.namespacedGroup(group))
}
// checkQuota("store.ScopedStore.Set", "config", "theme") returns nil when the
// checkQuota("store.ScopedStore.Set", "config", "colour") returns nil when the
// namespace still has quota available and QuotaExceededError when a new key or
// group would exceed the configured limit. Existing keys are treated as
// upserts and do not consume quota.

View file

@ -27,7 +27,7 @@ const (
entryValueColumn = "entry_value"
)
// Usage example: `storeInstance, err := store.New(":memory:"); if err != nil { return }; if err := storeInstance.Set("config", "theme", "dark"); err != nil { return }`
// Usage example: `storeInstance, err := store.New(":memory:"); if err != nil { return }; if err := storeInstance.Set("config", "colour", "blue"); err != nil { return }`
type Store struct {
database *sql.DB
cancelPurge context.CancelFunc
@ -83,7 +83,7 @@ func (storeInstance *Store) Close() error {
return nil
}
// Usage example: `themeValue, err := storeInstance.Get("config", "theme")`
// Usage example: `colourValue, err := storeInstance.Get("config", "colour")`
func (storeInstance *Store) Get(group, key string) (string, error) {
var value string
var expiresAt sql.NullInt64
@ -106,7 +106,7 @@ func (storeInstance *Store) Get(group, key string) (string, error) {
return value, nil
}
// Usage example: `if err := storeInstance.Set("config", "theme", "dark"); err != nil { return }`
// Usage example: `if err := storeInstance.Set("config", "colour", "blue"); err != nil { return }`
func (storeInstance *Store) Set(group, key, value string) error {
_, err := storeInstance.database.Exec(
"INSERT INTO "+entriesTableName+" ("+entryGroupColumn+", "+entryKeyColumn+", "+entryValueColumn+", expires_at) VALUES (?, ?, ?, NULL) "+
@ -135,7 +135,7 @@ func (storeInstance *Store) SetWithTTL(group, key, value string, timeToLive time
return nil
}
// Usage example: `if err := storeInstance.Delete("config", "theme"); err != nil { return }`
// Usage example: `if err := storeInstance.Delete("config", "colour"); err != nil { return }`
func (storeInstance *Store) Delete(group, key string) error {
_, err := storeInstance.database.Exec("DELETE FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ? AND "+entryKeyColumn+" = ?", group, key)
if err != nil {
@ -170,13 +170,13 @@ func (storeInstance *Store) DeleteGroup(group string) error {
// Usage example: `for entry, err := range storeInstance.All("config") { if err != nil { break }; fmt.Println(entry.Key, entry.Value) }`
type KeyValue struct {
// Usage example: `if entry.Key == "theme" { return }`
// Usage example: `if entry.Key == "colour" { return }`
Key string
// Usage example: `if entry.Value == "dark" { return }`
// Usage example: `if entry.Value == "blue" { return }`
Value string
}
// Usage example: `configEntries, err := storeInstance.GetAll("config")`
// Usage example: `colourEntries, err := storeInstance.GetAll("config")`
func (storeInstance *Store) GetAll(group string) (map[string]string, error) {
entriesByKey := make(map[string]string)
for entry, err := range storeInstance.All(group) {