Files
goclaw/internal/cache/memory.go
T
Viet Tran 6895e369f6 refactor: remove standalone mode, consolidate to managed-only (PostgreSQL) (#70)
- Remove standalone mode code: file-based stores, standalone gateway,
  heartbeat service, SQLite memory, standalone docker-compose
- Rename docker-compose.managed.yml → docker-compose.postgres.yml
- Clean up ~130 Go comments referencing "managed mode" qualifier
- Simplify docker-compose.yml env vars (providers/channels via web UI)
- Update .env.example to essential vars only (token + encryption key)
- Add setup wizard UI (provider → agent → channel bootstrap flow)
- Add logs.tail WebSocket handler for live log streaming
- Add cursor-pointer to interactive UI components
- Clean up config page (remove standalone-only sections)
- Update README and docs for managed-only architecture
2026-03-06 18:51:11 +07:00

72 lines
1.5 KiB
Go

package cache
import (
"context"
"strings"
"sync"
"time"
)
// entry wraps a cached value with expiration metadata.
type entry[V any] struct {
value V
expiresAt time.Time // zero means no expiry
}
func (e entry[V]) expired() bool {
return !e.expiresAt.IsZero() && time.Now().After(e.expiresAt)
}
// InMemoryCache is a thread-safe in-memory Cache implementation with TTL support.
type InMemoryCache[V any] struct {
data sync.Map
}
// NewInMemoryCache creates a new in-memory cache.
func NewInMemoryCache[V any]() *InMemoryCache[V] {
return &InMemoryCache[V]{}
}
func (c *InMemoryCache[V]) Get(_ context.Context, key string) (V, bool) {
raw, ok := c.data.Load(key)
if !ok {
var zero V
return zero, false
}
e := raw.(entry[V])
if e.expired() {
c.data.Delete(key)
var zero V
return zero, false
}
return e.value, true
}
func (c *InMemoryCache[V]) Set(_ context.Context, key string, value V, ttl time.Duration) {
e := entry[V]{value: value}
if ttl > 0 {
e.expiresAt = time.Now().Add(ttl)
}
c.data.Store(key, e)
}
func (c *InMemoryCache[V]) Delete(_ context.Context, key string) {
c.data.Delete(key)
}
func (c *InMemoryCache[V]) DeleteByPrefix(_ context.Context, prefix string) {
c.data.Range(func(key, _ any) bool {
if k, ok := key.(string); ok && strings.HasPrefix(k, prefix) {
c.data.Delete(key)
}
return true
})
}
func (c *InMemoryCache[V]) Clear(_ context.Context) {
c.data.Range(func(key, _ any) bool {
c.data.Delete(key)
return true
})
}