Files
root c1ef717d17
Deployment Config CI / Deployment Config (push) Successful in 24s
Backend CI / Backend (push) Successful in 14m33s
feat(cache,worker): overhaul cache layer and add generation task lease recovery
- shared/cache: add Options/L1/async/metrics/prefix decorators, multi-key ops, Redis pool tuning, and JSON readthrough metrics
- worker-generate: claim tasks via DB lease + heartbeat, requeue stale queued tasks, expire dead leases with refund/cache invalidation
- tenant: version article cache keys so worker recovery invalidations propagate cleanly
- shared/config: expand Redis (pool/timeouts/TLS) and Generation (lease/recovery) configs with defaults

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 02:02:39 +08:00

92 lines
2.1 KiB
Go

package cache
import (
"context"
"strings"
"time"
)
type prefixCache struct {
inner Cache
prefix string
}
func newPrefixCache(inner Cache, namespace string) Cache {
namespace = strings.Trim(strings.TrimSpace(namespace), ":")
if namespace == "" {
return inner
}
return &prefixCache{inner: inner, prefix: namespace + ":"}
}
func (c *prefixCache) Get(ctx context.Context, key string) ([]byte, error) {
return c.inner.Get(ctx, c.key(key))
}
func (c *prefixCache) GetMulti(ctx context.Context, keys []string) (map[string][]byte, error) {
if len(keys) == 0 {
return map[string][]byte{}, nil
}
prefixed := make([]string, len(keys))
originalByPrefixed := make(map[string]string, len(keys))
for idx, key := range keys {
prefixedKey := c.key(key)
prefixed[idx] = prefixedKey
originalByPrefixed[prefixedKey] = key
}
values, err := c.inner.GetMulti(ctx, prefixed)
if err != nil {
return nil, err
}
result := make(map[string][]byte, len(values))
for prefixedKey, value := range values {
key, ok := originalByPrefixed[prefixedKey]
if !ok {
continue
}
result[key] = value
}
return result, nil
}
func (c *prefixCache) Set(ctx context.Context, key string, value []byte, ttl time.Duration) error {
return c.inner.Set(ctx, c.key(key), value, ttl)
}
func (c *prefixCache) SetMulti(ctx context.Context, items []Item) error {
if len(items) == 0 {
return nil
}
prefixed := make([]Item, len(items))
for idx, item := range items {
item.Key = c.key(item.Key)
prefixed[idx] = item
}
return c.inner.SetMulti(ctx, prefixed)
}
func (c *prefixCache) Delete(ctx context.Context, key string) error {
return c.inner.Delete(ctx, c.key(key))
}
func (c *prefixCache) DeleteMany(ctx context.Context, keys []string) error {
if len(keys) == 0 {
return nil
}
prefixed := make([]string, len(keys))
for idx, key := range keys {
prefixed[idx] = c.key(key)
}
return c.inner.DeleteMany(ctx, prefixed)
}
func (c *prefixCache) DeletePrefix(ctx context.Context, prefix string) error {
return c.inner.DeletePrefix(ctx, c.key(prefix))
}
func (c *prefixCache) key(key string) string {
return c.prefix + strings.TrimPrefix(key, c.prefix)
}