Files
go-eve-pi/esi/cached.go
2025-10-11 10:51:52 +02:00

171 lines
5.1 KiB
Go

package esi
import (
"context"
"encoding/json"
"fmt"
"os"
"time"
"go-eve-pi/options"
"go-eve-pi/types"
logger "git.site.quack-lab.dev/dave/cylogger"
)
type CacheDB interface {
GetCacheEntry(hash string) (*types.CacheEntry, error)
SaveCacheEntry(entry *types.CacheEntry) error
}
// CachedESI implements ESIInterface with caching
type CachedESI struct {
direct ESIInterface
db CacheDB
cacheValidity time.Duration
}
// NewCachedESI creates a new CachedESI instance
func NewCachedESI(direct ESIInterface, db CacheDB) *CachedESI {
// Parse cache validity ONCE at initialization
cacheValidity, err := time.ParseDuration(options.GlobalOptions.CacheValidity)
if err != nil {
logger.Error("Invalid cache validity duration %s: %v", options.GlobalOptions.CacheValidity, err)
os.Exit(1)
}
logger.Info("Initializing CachedESI with cache validity: %v", cacheValidity)
return &CachedESI{
direct: direct,
db: db,
cacheValidity: cacheValidity,
}
}
// GetPlanetPI retrieves detailed information about a specific planet with caching
func (c *CachedESI) GetPlanetPI(ctx context.Context, characterID int, planetID int64, accessToken string) (*PlanetPI, error) {
funclog := logger.Default.WithPrefix("CachedESI.GetPlanetPI").WithPrefix(fmt.Sprintf("characterID=%d", characterID)).WithPrefix(fmt.Sprintf("planetID=%d", planetID))
funclog.Info("Starting")
hash := fmt.Sprintf("GetPlanetPI-%d-%d", characterID, planetID)
cached, err := c.db.GetCacheEntry(hash)
if err != nil {
funclog.Warning("Failed to get cache entry: %v", err)
}
if cached != nil {
funclog.Info("Cache hit for GetPlanetPI-%d-%d", characterID, planetID)
var planetPI PlanetPI
if err := json.Unmarshal([]byte(cached.Data), &planetPI); err != nil {
funclog.Error("Failed to unmarshal cached data: %v", err)
return nil, err
}
return &planetPI, nil
}
funclog.Info("Cache miss for GetPlanetPI-%d-%d", characterID, planetID)
apiresp, err := c.direct.GetPlanetPI(ctx, characterID, planetID, accessToken)
if err != nil {
funclog.Error("Failed to get planet PI: %v", err)
return nil, err
}
apirespjson, err := json.Marshal(apiresp)
if err != nil {
funclog.Error("Failed to marshal planet PI: %v", err)
return nil, err
}
cacheEntry := &types.CacheEntry{
Hash: hash,
Data: string(apirespjson),
CachedAt: time.Now(),
}
err = c.db.SaveCacheEntry(cacheEntry)
if err != nil {
funclog.Warning("Failed to save cache entry: %v", err)
}
return apiresp, nil
}
// GetPlanetName retrieves planet name with caching
func (c *CachedESI) GetPlanetName(ctx context.Context, planetID int64) (*PlanetName, error) {
funclog := logger.Default.WithPrefix("CachedESI.GetPlanetName").WithPrefix(fmt.Sprintf("planetID=%d", planetID))
funclog.Info("Starting")
hash := fmt.Sprintf("GetPlanetName-%d", planetID)
cached, err := c.db.GetCacheEntry(hash)
if err != nil {
funclog.Warning("Failed to get cache entry: %v", err)
}
if cached != nil {
funclog.Info("Cache hit for GetPlanetName-%d", planetID)
var planetPI PlanetName
if err := json.Unmarshal([]byte(cached.Data), &planetPI); err != nil {
funclog.Error("Failed to unmarshal cached data: %v", err)
return nil, err
}
return &planetPI, nil
}
funclog.Info("Cache miss for GetPlanetName-%d", planetID)
apiresp, err := c.direct.GetPlanetName(ctx, planetID)
if err != nil {
funclog.Error("Failed to get planet name: %v", err)
return nil, err
}
apirespjson, err := json.Marshal(apiresp)
if err != nil {
funclog.Error("Failed to marshal planet name: %v", err)
return nil, err
}
cacheEntry := &types.CacheEntry{
Hash: hash,
Data: string(apirespjson),
CachedAt: time.Now(),
}
err = c.db.SaveCacheEntry(cacheEntry)
if err != nil {
funclog.Warning("Failed to save cache entry: %v", err)
}
return apiresp, nil
}
func (c *CachedESI) GetCharacterPlanets(ctx context.Context, characterID int, accessToken string) ([]Planet, error) {
funclog := logger.Default.WithPrefix("CachedESI.GetCharacterPlanets").WithPrefix(fmt.Sprintf("characterID=%d", characterID))
funclog.Info("Starting")
hash := fmt.Sprintf("GetCharacterPlanets-%d", characterID)
cached, err := c.db.GetCacheEntry(hash)
if err != nil {
funclog.Warning("Failed to get cache entry: %v", err)
}
if cached != nil {
funclog.Info("Cache hit for GetCharacterPlanets-%d", characterID)
var planets []Planet
if err := json.Unmarshal([]byte(cached.Data), &planets); err != nil {
funclog.Error("Failed to unmarshal cached data: %v", err)
return nil, err
}
return planets, nil
}
funclog.Info("Cache miss for GetCharacterPlanets-%d", characterID)
apiresp, err := c.direct.GetCharacterPlanets(ctx, characterID, accessToken)
if err != nil {
funclog.Error("Failed to get character planets: %v", err)
return nil, err
}
apirespjson, err := json.Marshal(apiresp)
if err != nil {
funclog.Error("Failed to marshal character planets: %v", err)
return nil, err
}
cacheEntry := &types.CacheEntry{
Hash: hash,
Data: string(apirespjson),
CachedAt: time.Now(),
}
err = c.db.SaveCacheEntry(cacheEntry)
if err != nil {
funclog.Warning("Failed to save cache entry: %v", err)
}
return apiresp, nil
}
var _ ESIInterface = &CachedESI{}