mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-04 16:13:47 +00:00
Migration 000023: - Migrate group_file_writers data into agent_config_permissions (config_type='file_writer') - Add FK CASCADE/SET NULL on 16 tables for agent hard delete - Clean up soft-deleted zombie agents - ALTER scope VARCHAR(100) → VARCHAR(255) - Partial unique index on agent_key (allows reuse after delete) Store layer: - Remove GroupWriterCache, GroupFileWriterData, 5 AgentStore methods - Add CheckFileWriterPermission (fail-open), ListFileWriters (cached) - Add scope filter to ConfigPermissionStore.List() Tools: Replace GroupWriterCache with ConfigPermissionStore in read_file, write_file, edit, cron, context_file_interceptor Agent loop: buildGroupWriterPrompt uses ListFileWriters + metadata parsing Channels: Telegram commands rewritten to use configPermStore.Grant/Revoke/List HTTP API: Writer endpoints rewired to configPermStore (same response shapes) Hard delete: agents.go DELETE FROM instead of soft delete
54 lines
1.6 KiB
Go
54 lines
1.6 KiB
Go
//go:build redis
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"log/slog"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/cache"
|
|
"github.com/nextlevelbuilder/goclaw/internal/config"
|
|
"github.com/nextlevelbuilder/goclaw/internal/store"
|
|
)
|
|
|
|
// initRedisClient creates a Redis client when built with -tags redis.
|
|
// Returns nil (typed as any) if GOCLAW_REDIS_DSN is empty or connection fails.
|
|
func initRedisClient(cfg *config.Config) any {
|
|
dsn := cfg.Database.RedisDSN
|
|
if dsn == "" {
|
|
slog.Debug("Redis available but not configured (set GOCLAW_REDIS_DSN)")
|
|
return nil
|
|
}
|
|
client, err := cache.NewRedisClient(dsn)
|
|
if err != nil {
|
|
slog.Warn("Redis connection failed, falling back to in-memory cache", "error", err)
|
|
return nil
|
|
}
|
|
slog.Info("Redis cache connected")
|
|
return client
|
|
}
|
|
|
|
// makeCaches creates typed cache instances backed by Redis (or in-memory if client is nil).
|
|
func makeCaches(raw any) (
|
|
agentCtxCache cache.Cache[[]store.AgentContextFileData],
|
|
userCtxCache cache.Cache[[]store.AgentContextFileData],
|
|
) {
|
|
client, _ := raw.(*redis.Client)
|
|
if client == nil {
|
|
slog.Info("cache backend: in-memory (Redis not connected)")
|
|
return cache.NewInMemoryCache[[]store.AgentContextFileData](),
|
|
cache.NewInMemoryCache[[]store.AgentContextFileData]()
|
|
}
|
|
slog.Info("cache backend: redis")
|
|
return cache.NewRedisCache[[]store.AgentContextFileData](client, "ctx:agent"),
|
|
cache.NewRedisCache[[]store.AgentContextFileData](client, "ctx:user")
|
|
}
|
|
|
|
// shutdownRedis closes the Redis client connection.
|
|
func shutdownRedis(raw any) {
|
|
if client, ok := raw.(*redis.Client); ok && client != nil {
|
|
client.Close()
|
|
}
|
|
}
|