mcpField
E
encore-go-cache

encore-go-cache

github.com/encoredevデータ・データベース30314 回インストール2 日前に更新
リポジトリ

encore-go-cache について

Go サービス開発者向けに、Encore Go の型付き Redis キャッシュの使い方を説明するガイドです。キースペース、期限、削除ポリシー、キャッシュ操作を扱います。

主な機能

  1. 01型付き Redis キースペース
  2. 02整数・浮動小数点カウンター
  3. 03リストとセットの操作
  4. 04有効期限と削除ポリシーの設定
  5. 05キャッシュミスと競合の処理

活用シーン

  1. 01構造化された Go 値のキャッシュ
  2. 02リクエスト数のアトミックな計測
  3. 03Redis でのリストやセットの保存

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/encore-go-cacheを入力して読み込まれたか確認します。

詳細

Encore Go キャッシュ (Redis)

手順

Encore Go のキャッシュは、Redis の型付きラッパーです。cache.Cluster を一度宣言し、必要なデータの形ごとに Keyspace オブジェクトを作成します。

クラスター
package mycache

import "encore.dev/storage/cache"

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

削除ポリシー: cache.AllKeysLRU (デフォルト)、cache.NoEviction、cache.AllKeysLFU、cache.AllKeysRandom、cache.VolatileLRU、cache.VolatileLFU、cache.VolatileTTL、cache.VolatileRandom。

Keyspace の種類

各 keyspace にはキーの形 (KeyPattern から Redis キーを構築するために使用) と値の型があります。

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: "[email protected]",
    })
}
その他の Keyspace の種類

すべて encore.dev/storage/cache から提供されています:

  • NewFloatKeyspace — float64 の値、Increment を持ちます。
  • NewListKeyspace — リストの値、PushLeft/PushRight/PopLeft/PopRight/GetRange を持ちます。
  • NewSetKeyspace — セットの値、Add/Remove/Contains/Items を持ちます。
複数フィールドのキーパターン
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),
})
有効期限のヘルパー
import (
    "encore.dev/storage/cache"
    "time"
)

cache.ExpireIn(time.Hour)              // relative
cache.ExpireDailyAt(2, 0, 0, time.UTC) // specific UTC time each day
cache.NeverExpire                      // no expiry
cache.KeepTTL                          // keep existing TTL when updating
エラー
import "encore.dev/storage/cache"

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

err = keyspace.SetIfNotExists(ctx, key, value)
if errors.Is(err, cache.KeyExists) {
    // already there
}

ガイドライン

  • cache.Cluster と keyspace はパッケージレベルの変数として宣言します。
  • 最も適切な keyspace の種類を選びます — カウンターに IntKeyspace を使うと、アトミックな Increment/Decrement をそのまま利用できます。
  • Get() はミス時に cache.Miss を返します。Replace() と SetIfNotExists() は競合時に cache.Miss/cache.KeyExists を返します。
  • ローカル開発では約 100 キーの上限があるインメモリ Redis を使用します — 負荷テストには使用しないでください。
  • 永続ストレージには、代わりに encore-go-database (Postgres) または encore-go-bucket (オブジェクトストレージ) を使用してください。

コメント