encore-go-cache

Par encoredev · skills

Mettez en cache des données dans Redis depuis Encore Go en utilisant `cache.NewCluster` et des keyspaces typés issus de `encore.dev/storage/cache`. Accès clé/valeur type-safe avec TTLs, incréments atomiques et formes de données par keyspace.

npx skills add https://github.com/encoredev/skills --skill encore-go-cache

Mise en cache Encore Go (Redis)

Instructions

Le cache d'Encore Go est un wrapper typé autour de Redis. Déclarez un cache.Cluster une seule fois, puis créez des objets Keyspace pour chaque forme de données dont vous avez besoin.

Cluster

package mycache

import "encore.dev/storage/cache"

var Cluster = cache.NewCluster("my-cache", cache.ClusterConfig{
    EvictionPolicy: cache.AllKeysLRU,
})

Politiques d'éviction : cache.AllKeysLRU (par défaut), cache.NoEviction, cache.AllKeysLFU, cache.AllKeysRandom, cache.VolatileLRU, cache.VolatileLFU, cache.VolatileTTL, cache.VolatileRandom.

Types de keyspace

Chaque keyspace a une forme de clé (utilisée pour construire la clé Redis à partir de KeyPattern) et un type de valeur.

package mycache

import (
    "context"
    "time"
    "encore.dev/storage/cache"
)

type TokenKey struct {
    TokenID string
}

// Strings
var Tokens = cache.NewStringKeyspace[TokenKey](Cluster, cache.KeyspaceConfig{
    KeyPattern:    "token/:TokenID",
    DefaultExpiry: cache.ExpireIn(time.Hour),
})

func example(ctx context.Context) {
    _ = Tokens.Set(ctx, TokenKey{TokenID: "abc"}, "value")
    val, err := Tokens.Get(ctx, TokenKey{TokenID: "abc"}) // cache.Miss on miss
    _ = Tokens.Delete(ctx, TokenKey{TokenID: "abc"})
    _ = val
    _ = err
}
// Integers (atomic counters)
type CounterKey struct {
    UserID string
}

var Counters = cache.NewIntKeyspace[CounterKey](Cluster, cache.KeyspaceConfig{
    KeyPattern:    "requests/:UserID",
    DefaultExpiry: cache.ExpireIn(10 * time.Second),
})

func incr(ctx context.Context) {
    count, _ := Counters.Increment(ctx, CounterKey{UserID: "user123"}, 1)
    _, _ = Counters.Decrement(ctx, CounterKey{UserID: "user123"}, 1)
    _ = count
}
// Structs (JSON-encoded)
type ProfileKey struct {
    UserID string
}

type UserProfile struct {
    Name  string
    Email string
}

var Profiles = cache.NewStructKeyspace[ProfileKey, UserProfile](Cluster, cache.KeyspaceConfig{
    KeyPattern:    "profile/:UserID",
    DefaultExpiry: cache.ExpireIn(time.Hour),
})

func setProfile(ctx context.Context) {
    _ = Profiles.Set(ctx, ProfileKey{UserID: "123"}, UserProfile{
        Name: "Alice", Email: "alice@example.com",
    })
}

Autres types de keyspace

Tous depuis encore.dev/storage/cache :

  • NewFloatKeyspace — valeurs float64, avec Increment.
  • NewListKeyspace — valeurs de liste, avec PushLeft/PushRight/PopLeft/PopRight/GetRange.
  • NewSetKeyspace — valeurs d'ensemble, avec Add/Remove/Contains/Items.

Motifs de clés multi-champs

type ResourceKey struct {
    UserID       string
    ResourcePath string
}

var ResourceRequests = cache.NewIntKeyspace[ResourceKey](Cluster, cache.KeyspaceConfig{
    KeyPattern:    "requests/:UserID/:ResourcePath",
    DefaultExpiry: cache.ExpireIn(10 * time.Second),
})

Helpers d'expiration

import (
    "encore.dev/storage/cache"
    "time"
)

cache.ExpireIn(time.Hour)              // relative
cache.ExpireDailyAt(2, 0, 0, time.UTC) // heure UTC spécifique chaque jour
cache.NeverExpire                      // pas d'expiration
cache.KeepTTL                          // conserver le TTL existant lors de la mise à jour

Erreurs

import "encore.dev/storage/cache"

val, err := keyspace.Get(ctx, key)
if errors.Is(err, cache.Miss) {
    // pas en cache
}

err = keyspace.SetIfNotExists(ctx, key, value)
if errors.Is(err, cache.KeyExists) {
    // déjà présent
}

Recommandations

  • Déclarez cache.Cluster et les keyspaces comme variables au niveau du package.
  • Choisissez le type de keyspace le plus spécifique — IntKeyspace pour les compteurs vous donne Increment/Decrement atomiques gratuitement.
  • Get() retourne cache.Miss en cas d'absence ; Replace() et SetIfNotExists() retournent cache.Miss/cache.KeyExists en cas de conflit.
  • Le développement local utilise un Redis en mémoire avec un plafond d'environ 100 clés — ne le testez pas en charge.
  • Pour le stockage durable, utilisez encore-go-database (Postgres) ou encore-go-bucket (stockage d'objets) à la place.

Skills similaires