Deretardify the caching
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
var PI_TYPES_MAP = map[int]string{
|
var PITypesMap = map[int64]string{
|
||||||
44: "Enriched Uranium",
|
44: "Enriched Uranium",
|
||||||
2073: "Microorganisms",
|
2073: "Microorganisms",
|
||||||
2256: "Temperate Launchpad",
|
2256: "Temperate Launchpad",
|
||||||
@@ -126,7 +126,7 @@ var PI_TYPES_MAP = map[int]string{
|
|||||||
17392: "Data Chips",
|
17392: "Data Chips",
|
||||||
17898: "High-Tech Transmitters",
|
17898: "High-Tech Transmitters",
|
||||||
28974: "Vaccines",
|
28974: "Vaccines",
|
||||||
}
|
}
|
||||||
|
|
||||||
var PITypes = map[int]string{
|
var PITypes = map[int]string{
|
||||||
2469: "Lava Basic Industry Facility",
|
2469: "Lava Basic Industry Facility",
|
||||||
@@ -275,7 +275,7 @@ var StorageIDs = []int{
|
|||||||
2557, // Storm Launchpad
|
2557, // Storm Launchpad
|
||||||
}
|
}
|
||||||
|
|
||||||
var PIProductVolumes = map[int]float64{
|
var PIProductVolumes = map[int64]float64{
|
||||||
44: 0.75, // Enriched Uranium
|
44: 0.75, // Enriched Uranium
|
||||||
2073: 0.005, // Microorganisms
|
2073: 0.005, // Microorganisms
|
||||||
2256: 0.0, // Temperate Launchpad
|
2256: 0.0, // Temperate Launchpad
|
||||||
@@ -403,7 +403,7 @@ var PIProductVolumes = map[int]float64{
|
|||||||
28974: 3.0, // Vaccines
|
28974: 3.0, // Vaccines
|
||||||
}
|
}
|
||||||
|
|
||||||
var StorageCapacities = map[int]int{
|
var StorageCapacities = map[int64]int{
|
||||||
2257: 12000, // Ice Storage Facility
|
2257: 12000, // Ice Storage Facility
|
||||||
2535: 12000, // Oceanic Storage Facility
|
2535: 12000, // Oceanic Storage Facility
|
||||||
2536: 12000, // Gas Storage Facility
|
2536: 12000, // Gas Storage Facility
|
||||||
@@ -422,7 +422,7 @@ var StorageCapacities = map[int]int{
|
|||||||
2557: 10000, // Storm Launchpad
|
2557: 10000, // Storm Launchpad
|
||||||
}
|
}
|
||||||
|
|
||||||
var LaunchpadIDs = map[int]struct{}{
|
var LaunchpadIDs = map[int64]struct{}{
|
||||||
2256: {},
|
2256: {},
|
||||||
2542: {},
|
2542: {},
|
||||||
2543: {},
|
2543: {},
|
||||||
|
|||||||
198
esi/cached.go
198
esi/cached.go
@@ -2,8 +2,6 @@ package esi
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@@ -16,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type CacheDB interface {
|
type CacheDB interface {
|
||||||
GetCacheEntry(urlHash string) (*types.CacheEntry, error)
|
GetCacheEntry(hash string) (*types.CacheEntry, error)
|
||||||
SaveCacheEntry(entry *types.CacheEntry) error
|
SaveCacheEntry(entry *types.CacheEntry) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,135 +45,127 @@ func NewCachedESI(direct ESIInterface, db CacheDB) *CachedESI {
|
|||||||
// GetPlanetPI retrieves detailed information about a specific planet with caching
|
// 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) {
|
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 := logger.Default.WithPrefix("CachedESI.GetPlanetPI").WithPrefix(fmt.Sprintf("characterID=%d", characterID)).WithPrefix(fmt.Sprintf("planetID=%d", planetID))
|
||||||
|
|
||||||
url := fmt.Sprintf("/v3/characters/%d/planets/%d/", characterID, planetID)
|
|
||||||
funclog.Info("Starting")
|
funclog.Info("Starting")
|
||||||
|
|
||||||
fetchFunc := func() (*PlanetPI, error) {
|
hash := fmt.Sprintf("GetPlanetPI-%d-%d", characterID, planetID)
|
||||||
funclog.Info("Calling direct ESI")
|
cached, err := c.db.GetCacheEntry(hash)
|
||||||
result, err := c.direct.GetPlanetPI(ctx, characterID, planetID, accessToken)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
funclog.Error("Direct ESI call failed: %v", err)
|
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 nil, err
|
||||||
}
|
}
|
||||||
if result != nil {
|
return &planetPI, nil
|
||||||
funclog.Info("Direct ESI returned planet details with %d pins", len(result.Pins))
|
|
||||||
} else {
|
|
||||||
funclog.Info("Direct ESI returned nil planet details")
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
funclog.Info("Cache miss for GetPlanetPI-%d-%d", characterID, planetID)
|
||||||
|
|
||||||
result, err := getCachedResponse(c, url, fetchFunc)
|
apiresp, err := c.direct.GetPlanetPI(ctx, characterID, planetID, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
funclog.Error("Failed to get planet details: %v", err)
|
funclog.Error("Failed to get planet PI: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
apirespjson, err := json.Marshal(apiresp)
|
||||||
if result != nil {
|
|
||||||
funclog.Info("Successfully retrieved planet details with %d pins", len(result.Pins))
|
|
||||||
} else {
|
|
||||||
funclog.Info("Successfully retrieved nil planet details")
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getCachedResponse handles caching logic with generics
|
|
||||||
func getCachedResponse[T any](c *CachedESI, url string, fetchFunc func() (T, error)) (T, error) {
|
|
||||||
funclog := logger.Default.WithPrefix("getCachedResponse").WithPrefix(fmt.Sprintf("url=%s", url))
|
|
||||||
// Generate cache key
|
|
||||||
hash := sha256.Sum256([]byte(url))
|
|
||||||
urlHash := hex.EncodeToString(hash[:])
|
|
||||||
funclog.Debug("Generated cache key %s for URL: %s", urlHash[:8], url)
|
|
||||||
|
|
||||||
// Check cache using the interface
|
|
||||||
funclog.Debug("Checking cache for URL: %s", url)
|
|
||||||
cacheEntry, err := c.db.GetCacheEntry(urlHash)
|
|
||||||
if err == nil {
|
|
||||||
// Check if cache is still valid
|
|
||||||
age := time.Since(cacheEntry.CachedAt)
|
|
||||||
if age < c.cacheValidity {
|
|
||||||
funclog.Info("Cache HIT for URL: %s (cached %v ago, valid for %v more)", url, age, c.cacheValidity-age)
|
|
||||||
// Parse cached response
|
|
||||||
var result T
|
|
||||||
if err := json.Unmarshal([]byte(cacheEntry.Response), &result); err == nil {
|
|
||||||
funclog.Debug("Successfully unmarshaled cached response for URL: %s", url)
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
funclog.Warning("Failed to unmarshal cached response for URL: %s: %v", url, err)
|
|
||||||
} else {
|
|
||||||
logger.Info("Cache EXPIRED for URL: %s (cached %v ago, validity: %v)", url, age, c.cacheValidity)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
funclog.Info("Cache MISS for URL: %s (no cache entry found): %v", url, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache miss or invalid, fetch from API
|
|
||||||
funclog.Info("Fetching from API for URL: %s", url)
|
|
||||||
result, err := fetchFunc()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
funclog.Error("API fetch failed for URL: %s: %v", url, err)
|
funclog.Error("Failed to marshal planet PI: %v", err)
|
||||||
var zero T
|
return nil, err
|
||||||
return zero, err
|
|
||||||
}
|
}
|
||||||
funclog.Debug("API fetch successful for URL: %s", url)
|
cacheEntry := &types.CacheEntry{
|
||||||
|
Hash: hash,
|
||||||
// Store in cache
|
Data: string(apirespjson),
|
||||||
funclog.Debug("Marshaling response for caching URL: %s", url)
|
|
||||||
responseBytes, err := json.Marshal(result)
|
|
||||||
if err != nil {
|
|
||||||
funclog.Warning("Failed to marshal response for caching URL: %s: %v", url, err)
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
funclog.Debug("Response marshaled successfully for URL: %s (%d bytes)", url, len(responseBytes))
|
|
||||||
|
|
||||||
cacheEntry = &types.CacheEntry{
|
|
||||||
URLHash: urlHash,
|
|
||||||
Response: string(responseBytes),
|
|
||||||
CachedAt: time.Now(),
|
CachedAt: time.Now(),
|
||||||
}
|
}
|
||||||
|
err = c.db.SaveCacheEntry(cacheEntry)
|
||||||
funclog.Debug("Saving cache entry for URL: %s", url)
|
if err != nil {
|
||||||
if err := c.db.SaveCacheEntry(cacheEntry); err != nil {
|
funclog.Warning("Failed to save cache entry: %v", err)
|
||||||
funclog.Warning("Failed to cache response for URL: %s: %v", url, err)
|
|
||||||
} else {
|
|
||||||
funclog.Info("Cached response for URL: %s (valid for %v, %d bytes)", url, c.cacheValidity, len(responseBytes))
|
|
||||||
}
|
}
|
||||||
|
return apiresp, nil
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPlanetName retrieves planet name with caching
|
// GetPlanetName retrieves planet name with caching
|
||||||
func (c *CachedESI) GetPlanetName(ctx context.Context, planetID int64) (*PlanetName, error) {
|
func (c *CachedESI) GetPlanetName(ctx context.Context, planetID int64) (*PlanetName, error) {
|
||||||
funclog := logger.Default.WithPrefix("CachedESI.GetPlanetName").WithPrefix(fmt.Sprintf("planetID=%d", planetID))
|
funclog := logger.Default.WithPrefix("CachedESI.GetPlanetName").WithPrefix(fmt.Sprintf("planetID=%d", planetID))
|
||||||
url := fmt.Sprintf("/v1/universe/planets/%d/", planetID)
|
|
||||||
funclog.Info("Starting")
|
funclog.Info("Starting")
|
||||||
|
|
||||||
fetchFunc := func() (*PlanetName, error) {
|
hash := fmt.Sprintf("GetPlanetName-%d", planetID)
|
||||||
funclog.Info("Calling direct ESI for planet %d name", planetID)
|
cached, err := c.db.GetCacheEntry(hash)
|
||||||
result, err := c.direct.GetPlanetName(ctx, planetID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
funclog.Error("Direct ESI call failed for planet %d: %v", planetID, err)
|
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 nil, err
|
||||||
}
|
}
|
||||||
if result != nil {
|
return &planetPI, nil
|
||||||
funclog.Info("Direct ESI returned planet name '%s' for planet %d", result.Name, planetID)
|
|
||||||
} else {
|
|
||||||
funclog.Info("Direct ESI returned nil planet name for planet %d", planetID)
|
|
||||||
}
|
}
|
||||||
return result, nil
|
funclog.Info("Cache miss for GetPlanetName-%d", planetID)
|
||||||
}
|
apiresp, err := c.direct.GetPlanetName(ctx, planetID)
|
||||||
|
|
||||||
result, err := getCachedResponse(c, url, fetchFunc)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
funclog.Error("Failed to get planet name for planet %d: %v", planetID, err)
|
funclog.Error("Failed to get planet name: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
apirespjson, err := json.Marshal(apiresp)
|
||||||
if result != nil {
|
if err != nil {
|
||||||
funclog.Info("Successfully retrieved planet name '%s' for planet %d", result.Name, planetID)
|
funclog.Error("Failed to marshal planet name: %v", err)
|
||||||
} else {
|
return nil, err
|
||||||
funclog.Info("Successfully retrieved nil planet name for planet %d", planetID)
|
|
||||||
}
|
}
|
||||||
return result, nil
|
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{}
|
||||||
133
esi/client.go
133
esi/client.go
@@ -20,69 +20,6 @@ const (
|
|||||||
ESIBaseURL = "https://esi.evetech.net"
|
ESIBaseURL = "https://esi.evetech.net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Planet struct {
|
|
||||||
PlanetID int `json:"planet_id"`
|
|
||||||
PlanetType string `json:"planet_type"`
|
|
||||||
SolarSystemID int `json:"solar_system_id"`
|
|
||||||
UpgradeLevel int `json:"upgrade_level"`
|
|
||||||
NumPins int `json:"num_pins"`
|
|
||||||
LastUpdate string `json:"last_update"`
|
|
||||||
OwnerID int `json:"owner_id"`
|
|
||||||
PlanetName string `json:"planet_name"`
|
|
||||||
PlanetTypeID int `json:"planet_type_id"`
|
|
||||||
Position struct {
|
|
||||||
X float64 `json:"x"`
|
|
||||||
Y float64 `json:"y"`
|
|
||||||
Z float64 `json:"z"`
|
|
||||||
} `json:"position"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PlanetDetail struct {
|
|
||||||
Links []Link `json:"links"`
|
|
||||||
Pins []Pin `json:"pins"`
|
|
||||||
Routes []Route `json:"routes"`
|
|
||||||
LastUpdate string `json:"last_update"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Link struct {
|
|
||||||
DestinationPinID int `json:"destination_pin_id"`
|
|
||||||
LinkLevel int `json:"link_level"`
|
|
||||||
SourcePinID int `json:"source_pin_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Pin struct {
|
|
||||||
Contents []StorageContent `json:"contents"`
|
|
||||||
ExpiryTime *string `json:"expiry_time"`
|
|
||||||
ExtractorDetails *ExtractorDetails `json:"extractor_details"`
|
|
||||||
FactoryDetails *FactoryDetails `json:"factory_details"`
|
|
||||||
InstallTime *string `json:"install_time"`
|
|
||||||
LastCycleStart *string `json:"last_cycle_start"`
|
|
||||||
Latitude float64 `json:"latitude"`
|
|
||||||
Longitude float64 `json:"longitude"`
|
|
||||||
PinID int `json:"pin_id"`
|
|
||||||
SchematicID *int `json:"schematic_id"`
|
|
||||||
TypeID int `json:"type_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type StorageContent struct {
|
|
||||||
Amount int `json:"amount"`
|
|
||||||
TypeID int `json:"type_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExtractorDetails struct {
|
|
||||||
CycleTime *int `json:"cycle_time"`
|
|
||||||
HeadRadius *float64 `json:"head_radius"`
|
|
||||||
Heads []Head `json:"heads"`
|
|
||||||
ProductTypeID *int `json:"product_type_id"`
|
|
||||||
QtyPerCycle *int `json:"qty_per_cycle"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Head struct {
|
|
||||||
HeadID int `json:"head_id"`
|
|
||||||
Latitude float64 `json:"latitude"`
|
|
||||||
Longitude float64 `json:"longitude"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PlanetName struct {
|
type PlanetName struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
PlanetID int `json:"planet_id"`
|
PlanetID int `json:"planet_id"`
|
||||||
@@ -99,20 +36,11 @@ type FactoryDetails struct {
|
|||||||
SchematicID int `json:"schematic_id"`
|
SchematicID int `json:"schematic_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Route struct {
|
|
||||||
ContentTypeID int `json:"content_type_id"`
|
|
||||||
DestinationPinID int `json:"destination_pin_id"`
|
|
||||||
Quantity float64 `json:"quantity"`
|
|
||||||
RouteID int `json:"route_id"`
|
|
||||||
SourcePinID int `json:"source_pin_id"`
|
|
||||||
Waypoints []int `json:"waypoints"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ESIInterface defines the contract for ESI API interactions
|
// ESIInterface defines the contract for ESI API interactions
|
||||||
type ESIInterface interface {
|
type ESIInterface interface {
|
||||||
GetCharacterPlanets(ctx context.Context, characterID int, accessToken string) ([]Planet, error)
|
GetCharacterPlanets(ctx context.Context, characterID int, accessToken string) ([]Planet, error)
|
||||||
GetPlanetDetails(ctx context.Context, characterID, planetID int, accessToken string) (*PlanetDetail, error)
|
GetPlanetPI(ctx context.Context, characterID int, planetID int64, accessToken string) (*PlanetPI, error)
|
||||||
GetPlanetName(ctx context.Context, planetID int) (*PlanetName, error)
|
GetPlanetName(ctx context.Context, planetID int64) (*PlanetName, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirectESI implements ESIInterface with direct API calls
|
// DirectESI implements ESIInterface with direct API calls
|
||||||
@@ -138,13 +66,14 @@ func NewDirectESI() *DirectESI {
|
|||||||
|
|
||||||
// GetCharacterPlanets retrieves a list of planets for a character
|
// GetCharacterPlanets retrieves a list of planets for a character
|
||||||
func (d *DirectESI) GetCharacterPlanets(ctx context.Context, characterID int, accessToken string) ([]Planet, error) {
|
func (d *DirectESI) GetCharacterPlanets(ctx context.Context, characterID int, accessToken string) ([]Planet, error) {
|
||||||
logger.Debug("Fetching planets for character ID %d", characterID)
|
funclog := logger.Default.WithPrefix("DirectESI.GetCharacterPlanets").WithPrefix(fmt.Sprintf("characterID=%d", characterID))
|
||||||
|
funclog.Debug("Fetching planets")
|
||||||
|
|
||||||
url := fmt.Sprintf("%s/v1/characters/%d/planets/", ESIBaseURL, characterID)
|
url := fmt.Sprintf("%s/v3/characters/%d/planets/", ESIBaseURL, characterID)
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to create request for character planets: %v", err)
|
funclog.Error("Failed to create request for character planets: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,36 +82,37 @@ func (d *DirectESI) GetCharacterPlanets(ctx context.Context, characterID int, ac
|
|||||||
|
|
||||||
resp, err := d.httpClient.Do(req)
|
resp, err := d.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to fetch character planets: %v", err)
|
funclog.Error("Failed to fetch character planets: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
body, _ := io.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
logger.Error("Character planets API returned status %d: %s", resp.StatusCode, string(body))
|
funclog.Error("Character planets API returned status %d: %s", resp.StatusCode, string(body))
|
||||||
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
|
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
var planets []Planet
|
var planets []Planet
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&planets); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&planets); err != nil {
|
||||||
logger.Error("Failed to decode character planets response: %v", err)
|
funclog.Error("Failed to decode character planets response: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Successfully fetched %d planets for character ID %d", len(planets), characterID)
|
funclog.Info("Successfully fetched %d planets", len(planets))
|
||||||
return planets, nil
|
return planets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPlanetDetails retrieves detailed information about a specific planet
|
// GetPlanetPI retrieves detailed information about a specific planet
|
||||||
func (d *DirectESI) GetPlanetDetails(ctx context.Context, characterID, planetID int, accessToken string) (*PlanetDetail, error) {
|
func (d *DirectESI) GetPlanetPI(ctx context.Context, characterID int, planetID int64, accessToken string) (*PlanetPI, error) {
|
||||||
logger.Debug("Fetching planet details for character ID %d, planet ID %d", characterID, planetID)
|
funclog := logger.Default.WithPrefix("DirectESI.GetPlanetPI").WithPrefix(fmt.Sprintf("characterID=%d", characterID)).WithPrefix(fmt.Sprintf("planetID=%d", planetID))
|
||||||
|
funclog.Debug("Fetching planet details")
|
||||||
|
|
||||||
url := fmt.Sprintf("%s/v3/characters/%d/planets/%d/", ESIBaseURL, characterID, planetID)
|
url := fmt.Sprintf("%s/v3/characters/%d/planets/%d/", ESIBaseURL, characterID, planetID)
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to create request for planet details: %v", err)
|
funclog.Error("Failed to create request for planet details: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,36 +121,37 @@ func (d *DirectESI) GetPlanetDetails(ctx context.Context, characterID, planetID
|
|||||||
|
|
||||||
resp, err := d.httpClient.Do(req)
|
resp, err := d.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to fetch planet details: %v", err)
|
funclog.Error("Failed to fetch planet details: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
body, _ := io.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
logger.Error("Planet details API returned status %d: %s", resp.StatusCode, string(body))
|
funclog.Error("Planet details API returned status %d: %s", resp.StatusCode, string(body))
|
||||||
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
|
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
var planetDetail PlanetDetail
|
var pi PlanetPI
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&planetDetail); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&pi); err != nil {
|
||||||
logger.Error("Failed to decode planet details response: %v", err)
|
funclog.Error("Failed to decode planet details response: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Successfully fetched planet details for character ID %d, planet ID %d", characterID, planetID)
|
funclog.Info("Successfully fetched planet details")
|
||||||
return &planetDetail, nil
|
return &pi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPlanetName retrieves planet name from universe endpoint
|
// GetPlanetName retrieves planet name from universe endpoint
|
||||||
func (d *DirectESI) GetPlanetName(ctx context.Context, planetID int) (*PlanetName, error) {
|
func (d *DirectESI) GetPlanetName(ctx context.Context, planetID int64) (*PlanetName, error) {
|
||||||
logger.Debug("Fetching planet name for planet ID %d", planetID)
|
funclog := logger.Default.WithPrefix("DirectESI.GetPlanetName").WithPrefix(fmt.Sprintf("planetID=%d", planetID))
|
||||||
|
funclog.Debug("Fetching planet name")
|
||||||
|
|
||||||
url := fmt.Sprintf("%s/v1/universe/planets/%d/", ESIBaseURL, planetID)
|
url := fmt.Sprintf("%s/v1/universe/planets/%d/", ESIBaseURL, planetID)
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to create request for planet name: %v", err)
|
funclog.Error("Failed to create request for planet name: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,28 +159,30 @@ func (d *DirectESI) GetPlanetName(ctx context.Context, planetID int) (*PlanetNam
|
|||||||
|
|
||||||
resp, err := d.httpClient.Do(req)
|
resp, err := d.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to fetch planet name: %v", err)
|
funclog.Error("Failed to fetch planet name: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to read planet name response body: %v", err)
|
funclog.Error("Failed to read planet name response body: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
logger.Error("API request failed with status %d: %s", resp.StatusCode, string(body))
|
funclog.Error("API request failed with status %d: %s", resp.StatusCode, string(body))
|
||||||
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
|
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
var planetName PlanetName
|
var planetName PlanetName
|
||||||
if err := json.NewDecoder(bytes.NewReader(body)).Decode(&planetName); err != nil {
|
if err := json.NewDecoder(bytes.NewReader(body)).Decode(&planetName); err != nil {
|
||||||
logger.Error("Failed to decode planet name response: %v", err)
|
funclog.Error("Failed to decode planet name response: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Successfully fetched planet name for planet ID %d: %s", planetID, planetName.Name)
|
funclog.Info("Successfully fetched planet name: %s", planetName.Name)
|
||||||
return &planetName, nil
|
return &planetName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ ESIInterface = &DirectESI{}
|
||||||
@@ -32,7 +32,7 @@ type Content struct {
|
|||||||
type Route struct {
|
type Route struct {
|
||||||
ContentTypeID int64 `json:"content_type_id"`
|
ContentTypeID int64 `json:"content_type_id"`
|
||||||
DestinationPinID int64 `json:"destination_pin_id"`
|
DestinationPinID int64 `json:"destination_pin_id"`
|
||||||
Quantity int64 `json:"quantity"`
|
Quantity float64 `json:"quantity"`
|
||||||
RouteID int64 `json:"route_id"`
|
RouteID int64 `json:"route_id"`
|
||||||
SourcePinID int64 `json:"source_pin_id"`
|
SourcePinID int64 `json:"source_pin_id"`
|
||||||
Waypoints []int64 `json:"waypoints"`
|
Waypoints []int64 `json:"waypoints"`
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package repositories
|
package repositories
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"go-eve-pi/types"
|
"go-eve-pi/types"
|
||||||
|
|
||||||
logger "git.site.quack-lab.dev/dave/cylogger"
|
logger "git.site.quack-lab.dev/dave/cylogger"
|
||||||
@@ -21,25 +22,27 @@ func NewCacheRepository(db *gorm.DB) *CacheRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCacheEntry retrieves a cache entry by URL hash
|
// GetCacheEntry retrieves a cache entry by URL hash
|
||||||
func (r *CacheRepository) GetCacheEntry(urlHash string) (*types.CacheEntry, error) {
|
func (r *CacheRepository) GetCacheEntry(hash string) (*types.CacheEntry, error) {
|
||||||
logger.Debug("Fetching cache entry for hash: %s", urlHash)
|
funclog := logger.Default.WithPrefix("CacheRepository.GetCacheEntry").WithPrefix(fmt.Sprintf("hash=%s", hash))
|
||||||
|
funclog.Info("Starting")
|
||||||
var entry types.CacheEntry
|
var entry types.CacheEntry
|
||||||
err := r.db.Where("url_hash = ?", urlHash).First(&entry).Error
|
err := r.db.Where("hash = ?", hash).First(&entry).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debug("No cache entry found for hash %s: %v", urlHash, err)
|
funclog.Debug("No cache entry found: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
logger.Debug("Cache entry found for hash %s", urlHash)
|
funclog.Debug("Cache entry found")
|
||||||
return &entry, nil
|
return &entry, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveCacheEntry saves a cache entry to the database
|
// SaveCacheEntry saves a cache entry to the database
|
||||||
func (r *CacheRepository) SaveCacheEntry(entry *types.CacheEntry) error {
|
func (r *CacheRepository) SaveCacheEntry(entry *types.CacheEntry) error {
|
||||||
logger.Debug("Saving cache entry for hash: %s", entry.URLHash)
|
funclog := logger.Default.WithPrefix("CacheRepository.SaveCacheEntry").WithPrefix(fmt.Sprintf("hash=%s", entry.Hash))
|
||||||
|
funclog.Info("Starting")
|
||||||
err := r.db.Save(entry).Error
|
err := r.db.Save(entry).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logger.Debug("Cache entry saved successfully for hash %s", entry.URLHash)
|
funclog.Debug("Cache entry saved successfully")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,9 @@ type Character struct {
|
|||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheEntry represents a cached API response
|
|
||||||
type CacheEntry struct {
|
type CacheEntry struct {
|
||||||
ID uint `gorm:"primaryKey"`
|
ID uint `gorm:"primaryKey"`
|
||||||
URLHash string `gorm:"uniqueIndex"`
|
Hash string `gorm:"uniqueIndex"`
|
||||||
Response string `gorm:"type:text"`
|
Data string `gorm:"type:text"`
|
||||||
CachedAt time.Time `gorm:"index"`
|
CachedAt time.Time `gorm:"index"`
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user