From 22b218c7d39722ac5d868607c756fdae43d9230b Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Sat, 11 Oct 2025 10:33:03 +0200 Subject: [PATCH] Deretardify the caching --- constants/storage.go | 512 +++++++++++++++---------------- esi/cached.go | 208 ++++++------- esi/client.go | 133 ++------ esi/types.go | 2 +- repositories/cache.go | 17 +- types/{character.go => types.go} | 5 +- 6 files changed, 401 insertions(+), 476 deletions(-) rename types/{character.go => types.go} (78%) diff --git a/constants/storage.go b/constants/storage.go index 24741b1..c791677 100644 --- a/constants/storage.go +++ b/constants/storage.go @@ -1,132 +1,132 @@ package constants -var PI_TYPES_MAP = map[int]string{ - 44: "Enriched Uranium", - 2073: "Microorganisms", - 2256: "Temperate Launchpad", - 2257: "Ice Storage Facility", - 2267: "Base Metals", - 2268: "Aqueous Liquids", - 2270: "Noble Metals", - 2272: "Heavy Metals", - 2286: "Planktic Colonies", - 2287: "Complex Organisms", - 2288: "Carbon Compounds", - 2305: "Autotrophs", - 2306: "Non-CS Crystals", - 2307: "Felsic Magma", - 2308: "Suspended Plasma", - 2309: "Ionic Solutions", - 2310: "Noble Gas", - 2311: "Reactive Gas", - 2312: "Supertensile Plastics", - 2317: "Oxides", - 2319: "Test Cultures", - 2321: "Polyaramids", - 2327: "Microfiber Shielding", - 2328: "Water-Cooled CPU", - 2329: "Biocells", - 2344: "Condensates", - 2345: "Camera Drones", - 2346: "Synthetic Synapses", - 2348: "Gel-Matrix Biopaste", - 2349: "Supercomputers", - 2351: "Smartfab Units", - 2352: "Nuclear Reactors", - 2354: "Neocoms", - 2358: "Biotech Research Reports", - 2360: "Industrial Explosives", - 2361: "Hermetic Membranes", - 2366: "Hazmat Detection Systems", - 2367: "Cryoprotectant Solution", - 2389: "Plasmoids", - 2390: "Electrolytes", - 2392: "Oxidizing Compound", - 2393: "Bacteria", - 2395: "Proteins", - 2396: "Biofuels", - 2397: "Industrial Fibers", - 2398: "Reactive Metals", - 2399: "Precious Metals", - 2400: "Toxic Metals", - 2401: "Chiral Structures", - 2463: "Nanites", - 2469: "Lava Basic Industry Facility", - 2470: "Lava Advanced Industry Facility", - 2471: "Plasma Basic Industry Facility", - 2472: "Plasma Advanced Industry Facility", - 2473: "Barren Basic Industry Facility", - 2474: "Barren Advanced Industry Facility", - 2475: "Barren High-Tech Production Plant", - 2480: "Temperate Advanced Industry Facility", - 2481: "Temperate Basic Industry Facility", - 2482: "Temperate High-Tech Production Plant", - 2483: "Storm Basic Industry Facility", - 2484: "Storm Advanced Industry Facility", - 2485: "Oceanic Advanced Industry Facility", - 2490: "Oceanic Basic Industry Facility", - 2491: "Ice Advanced Industry Facility", - 2492: "Gas Basic Industry Facility", - 2493: "Ice Basic Industry Facility", - 2494: "Gas Advanced Industry Facility", - 2535: "Oceanic Storage Facility", - 2536: "Gas Storage Facility", - 2541: "Barren Storage Facility", - 2542: "Oceanic Launchpad", - 2543: "Gas Launchpad", - 2544: "Barren Launchpad", - 2552: "Ice Launchpad", - 2555: "Lava Launchpad", - 2556: "Plasma Launchpad", - 2557: "Storm Launchpad", - 2558: "Lava Storage Facility", - 2560: "Plasma Storage Facility", - 2561: "Storm Storage Facility", - 2562: "Temperate Storage Facility", - 2848: "Barren Extractor Control Unit", - 2867: "Broadcast Node", - 2868: "Integrity Response Drones", - 2869: "Nano-Factory", - 2870: "Organic Mortar Applicators", - 2871: "Recursive Computing Module", - 2872: "Self-Harmonizing Power Core", - 2875: "Sterile Conduits", - 2876: "Wetware Mainframe", - 3060: "Gas Extractor Control Unit", - 3061: "Ice Extractor Control Unit", - 3062: "Lava Extractor Control Unit", - 3063: "Oceanic Extractor Control Unit", - 3064: "Plasma Extractor Control Unit", - 3067: "Storm Extractor Control Unit", - 3068: "Temperate Extractor Control Unit", - 3645: "Water", - 3683: "Oxygen", - 3689: "Mechanical Parts", - 3691: "Synthetic Oil", - 3693: "Fertilizer", - 3695: "Polytextiles", - 3697: "Silicate Glass", - 3725: "Livestock", - 3775: "Viral Agent", - 3779: "Biomass", - 3828: "Construction Blocks", - 9828: "Silicon", - 9830: "Rocket Fuel", - 9832: "Coolant", - 9834: "Guidance Systems", - 9836: "Consumer Electronics", - 9838: "Superconductors", - 9840: "Transmitter", - 9842: "Miniature Electronics", - 9846: "Planetary Vehicles", - 9848: "Robotics", - 12836: "Transcranial Microcontrollers", - 15317: "Genetically Enhanced Livestock", - 17136: "Ukomi Superconductors", - 17392: "Data Chips", - 17898: "High-Tech Transmitters", - 28974: "Vaccines", - } +var PITypesMap = map[int64]string{ + 44: "Enriched Uranium", + 2073: "Microorganisms", + 2256: "Temperate Launchpad", + 2257: "Ice Storage Facility", + 2267: "Base Metals", + 2268: "Aqueous Liquids", + 2270: "Noble Metals", + 2272: "Heavy Metals", + 2286: "Planktic Colonies", + 2287: "Complex Organisms", + 2288: "Carbon Compounds", + 2305: "Autotrophs", + 2306: "Non-CS Crystals", + 2307: "Felsic Magma", + 2308: "Suspended Plasma", + 2309: "Ionic Solutions", + 2310: "Noble Gas", + 2311: "Reactive Gas", + 2312: "Supertensile Plastics", + 2317: "Oxides", + 2319: "Test Cultures", + 2321: "Polyaramids", + 2327: "Microfiber Shielding", + 2328: "Water-Cooled CPU", + 2329: "Biocells", + 2344: "Condensates", + 2345: "Camera Drones", + 2346: "Synthetic Synapses", + 2348: "Gel-Matrix Biopaste", + 2349: "Supercomputers", + 2351: "Smartfab Units", + 2352: "Nuclear Reactors", + 2354: "Neocoms", + 2358: "Biotech Research Reports", + 2360: "Industrial Explosives", + 2361: "Hermetic Membranes", + 2366: "Hazmat Detection Systems", + 2367: "Cryoprotectant Solution", + 2389: "Plasmoids", + 2390: "Electrolytes", + 2392: "Oxidizing Compound", + 2393: "Bacteria", + 2395: "Proteins", + 2396: "Biofuels", + 2397: "Industrial Fibers", + 2398: "Reactive Metals", + 2399: "Precious Metals", + 2400: "Toxic Metals", + 2401: "Chiral Structures", + 2463: "Nanites", + 2469: "Lava Basic Industry Facility", + 2470: "Lava Advanced Industry Facility", + 2471: "Plasma Basic Industry Facility", + 2472: "Plasma Advanced Industry Facility", + 2473: "Barren Basic Industry Facility", + 2474: "Barren Advanced Industry Facility", + 2475: "Barren High-Tech Production Plant", + 2480: "Temperate Advanced Industry Facility", + 2481: "Temperate Basic Industry Facility", + 2482: "Temperate High-Tech Production Plant", + 2483: "Storm Basic Industry Facility", + 2484: "Storm Advanced Industry Facility", + 2485: "Oceanic Advanced Industry Facility", + 2490: "Oceanic Basic Industry Facility", + 2491: "Ice Advanced Industry Facility", + 2492: "Gas Basic Industry Facility", + 2493: "Ice Basic Industry Facility", + 2494: "Gas Advanced Industry Facility", + 2535: "Oceanic Storage Facility", + 2536: "Gas Storage Facility", + 2541: "Barren Storage Facility", + 2542: "Oceanic Launchpad", + 2543: "Gas Launchpad", + 2544: "Barren Launchpad", + 2552: "Ice Launchpad", + 2555: "Lava Launchpad", + 2556: "Plasma Launchpad", + 2557: "Storm Launchpad", + 2558: "Lava Storage Facility", + 2560: "Plasma Storage Facility", + 2561: "Storm Storage Facility", + 2562: "Temperate Storage Facility", + 2848: "Barren Extractor Control Unit", + 2867: "Broadcast Node", + 2868: "Integrity Response Drones", + 2869: "Nano-Factory", + 2870: "Organic Mortar Applicators", + 2871: "Recursive Computing Module", + 2872: "Self-Harmonizing Power Core", + 2875: "Sterile Conduits", + 2876: "Wetware Mainframe", + 3060: "Gas Extractor Control Unit", + 3061: "Ice Extractor Control Unit", + 3062: "Lava Extractor Control Unit", + 3063: "Oceanic Extractor Control Unit", + 3064: "Plasma Extractor Control Unit", + 3067: "Storm Extractor Control Unit", + 3068: "Temperate Extractor Control Unit", + 3645: "Water", + 3683: "Oxygen", + 3689: "Mechanical Parts", + 3691: "Synthetic Oil", + 3693: "Fertilizer", + 3695: "Polytextiles", + 3697: "Silicate Glass", + 3725: "Livestock", + 3775: "Viral Agent", + 3779: "Biomass", + 3828: "Construction Blocks", + 9828: "Silicon", + 9830: "Rocket Fuel", + 9832: "Coolant", + 9834: "Guidance Systems", + 9836: "Consumer Electronics", + 9838: "Superconductors", + 9840: "Transmitter", + 9842: "Miniature Electronics", + 9846: "Planetary Vehicles", + 9848: "Robotics", + 12836: "Transcranial Microcontrollers", + 15317: "Genetically Enhanced Livestock", + 17136: "Ukomi Superconductors", + 17392: "Data Chips", + 17898: "High-Tech Transmitters", + 28974: "Vaccines", +} var PITypes = map[int]string{ 2469: "Lava Basic Industry Facility", @@ -275,135 +275,135 @@ var StorageIDs = []int{ 2557, // Storm Launchpad } -var PIProductVolumes = map[int]float64{ - 44: 0.75, // Enriched Uranium - 2073: 0.005, // Microorganisms - 2256: 0.0, // Temperate Launchpad - 2257: 0.0, // Ice Storage Facility - 2267: 0.005, // Base Metals - 2268: 0.005, // Aqueous Liquids - 2270: 0.005, // Noble Metals - 2272: 0.005, // Heavy Metals - 2286: 0.005, // Planktic Colonies - 2287: 0.005, // Complex Organisms - 2288: 0.005, // Carbon Compounds - 2305: 0.005, // Autotrophs - 2306: 0.005, // Non-CS Crystals - 2307: 0.005, // Felsic Magma - 2308: 0.005, // Suspended Plasma - 2309: 0.005, // Ionic Solutions - 2310: 0.005, // Noble Gas - 2311: 0.005, // Reactive Gas - 2312: 0.75, // Supertensile Plastics - 2317: 0.75, // Oxides - 2319: 0.75, // Test Cultures - 2321: 0.75, // Polyaramids - 2327: 0.75, // Microfiber Shielding - 2328: 0.75, // Water-Cooled CPU - 2329: 0.75, // Biocells - 2344: 3.0, // Condensates - 2345: 3.0, // Camera Drones - 2346: 3.0, // Synthetic Synapses - 2348: 3.0, // Gel-Matrix Biopaste - 2349: 3.0, // Supercomputers - 2351: 3.0, // Smartfab Units - 2352: 3.0, // Nuclear Reactors - 2354: 3.0, // Neocoms - 2358: 3.0, // Biotech Research Reports - 2360: 3.0, // Industrial Explosives - 2361: 3.0, // Hermetic Membranes - 2366: 3.0, // Hazmat Detection Systems - 2367: 3.0, // Cryoprotectant Solution - 2389: 0.19, // Plasmoids - 2390: 0.19, // Electrolytes - 2392: 0.19, // Oxidizing Compound - 2393: 0.19, // Bacteria - 2395: 0.19, // Proteins - 2396: 0.19, // Biofuels - 2397: 0.19, // Industrial Fibers - 2398: 0.19, // Reactive Metals - 2399: 0.19, // Precious Metals - 2400: 0.19, // Toxic Metals - 2401: 0.19, // Chiral Structures - 2463: 0.75, // Nanites - 2469: 0.0, // Lava Basic Industry Facility - 2470: 0.0, // Lava Advanced Industry Facility - 2471: 0.0, // Plasma Basic Industry Facility - 2472: 0.0, // Plasma Advanced Industry Facility - 2473: 0.0, // Barren Basic Industry Facility - 2474: 0.0, // Barren Advanced Industry Facility - 2475: 0.0, // Barren High-Tech Production Plant - 2480: 0.0, // Temperate Advanced Industry Facility - 2481: 0.0, // Temperate Basic Industry Facility - 2482: 0.0, // Temperate High-Tech Production Plant - 2483: 0.0, // Storm Basic Industry Facility - 2484: 0.0, // Storm Advanced Industry Facility - 2485: 0.0, // Oceanic Advanced Industry Facility - 2490: 0.0, // Oceanic Basic Industry Facility - 2491: 0.0, // Ice Advanced Industry Facility - 2492: 0.0, // Gas Basic Industry Facility - 2493: 0.0, // Ice Basic Industry Facility - 2494: 0.0, // Gas Advanced Industry Facility - 2535: 0.0, // Oceanic Storage Facility - 2536: 0.0, // Gas Storage Facility - 2541: 0.0, // Barren Storage Facility - 2542: 0.0, // Oceanic Launchpad - 2543: 0.0, // Gas Launchpad - 2544: 0.0, // Barren Launchpad - 2552: 0.0, // Ice Launchpad - 2555: 0.0, // Lava Launchpad - 2556: 0.0, // Plasma Launchpad - 2557: 0.0, // Storm Launchpad - 2558: 0.0, // Lava Storage Facility - 2560: 0.0, // Plasma Storage Facility - 2561: 0.0, // Storm Storage Facility - 2562: 0.0, // Temperate Storage Facility - 2848: 0.0, // Barren Extractor Control Unit - 2867: 50.0, // Broadcast Node - 2868: 50.0, // Integrity Response Drones - 2869: 50.0, // Nano-Factory - 2870: 50.0, // Organic Mortar Applicators - 2871: 50.0, // Recursive Computing Module - 2872: 50.0, // Self-Harmonizing Power Core - 2875: 50.0, // Sterile Conduits - 2876: 50.0, // Wetware Mainframe - 3060: 0.0, // Gas Extractor Control Unit - 3061: 0.0, // Ice Extractor Control Unit - 3062: 0.0, // Lava Extractor Control Unit - 3063: 0.0, // Oceanic Extractor Control Unit - 3064: 0.0, // Plasma Extractor Control Unit - 3067: 0.0, // Storm Extractor Control Unit - 3068: 0.0, // Temperate Extractor Control Unit - 3645: 0.19, // Water - 3683: 0.19, // Oxygen - 3689: 0.75, // Mechanical Parts - 3691: 0.75, // Synthetic Oil - 3693: 0.75, // Fertilizer - 3695: 0.75, // Polytextiles - 3697: 0.75, // Silicate Glass - 3725: 0.75, // Livestock - 3775: 0.75, // Viral Agent - 3779: 0.19, // Biomass - 3828: 0.75, // Construction Blocks - 9828: 0.19, // Silicon - 9830: 0.75, // Rocket Fuel - 9832: 0.75, // Coolant - 9834: 3.0, // Guidance Systems - 9836: 0.75, // Consumer Electronics - 9838: 0.75, // Superconductors - 9840: 0.75, // Transmitter - 9842: 0.75, // Miniature Electronics - 9846: 3.0, // Planetary Vehicles - 9848: 3.0, // Robotics - 12836: 3.0, // Transcranial Microcontrollers - 15317: 0.75, // Genetically Enhanced Livestock - 17136: 3.0, // Ukomi Superconductors - 17392: 3.0, // Data Chips - 17898: 3.0, // High-Tech Transmitters - 28974: 3.0, // Vaccines +var PIProductVolumes = map[int64]float64{ + 44: 0.75, // Enriched Uranium + 2073: 0.005, // Microorganisms + 2256: 0.0, // Temperate Launchpad + 2257: 0.0, // Ice Storage Facility + 2267: 0.005, // Base Metals + 2268: 0.005, // Aqueous Liquids + 2270: 0.005, // Noble Metals + 2272: 0.005, // Heavy Metals + 2286: 0.005, // Planktic Colonies + 2287: 0.005, // Complex Organisms + 2288: 0.005, // Carbon Compounds + 2305: 0.005, // Autotrophs + 2306: 0.005, // Non-CS Crystals + 2307: 0.005, // Felsic Magma + 2308: 0.005, // Suspended Plasma + 2309: 0.005, // Ionic Solutions + 2310: 0.005, // Noble Gas + 2311: 0.005, // Reactive Gas + 2312: 0.75, // Supertensile Plastics + 2317: 0.75, // Oxides + 2319: 0.75, // Test Cultures + 2321: 0.75, // Polyaramids + 2327: 0.75, // Microfiber Shielding + 2328: 0.75, // Water-Cooled CPU + 2329: 0.75, // Biocells + 2344: 3.0, // Condensates + 2345: 3.0, // Camera Drones + 2346: 3.0, // Synthetic Synapses + 2348: 3.0, // Gel-Matrix Biopaste + 2349: 3.0, // Supercomputers + 2351: 3.0, // Smartfab Units + 2352: 3.0, // Nuclear Reactors + 2354: 3.0, // Neocoms + 2358: 3.0, // Biotech Research Reports + 2360: 3.0, // Industrial Explosives + 2361: 3.0, // Hermetic Membranes + 2366: 3.0, // Hazmat Detection Systems + 2367: 3.0, // Cryoprotectant Solution + 2389: 0.19, // Plasmoids + 2390: 0.19, // Electrolytes + 2392: 0.19, // Oxidizing Compound + 2393: 0.19, // Bacteria + 2395: 0.19, // Proteins + 2396: 0.19, // Biofuels + 2397: 0.19, // Industrial Fibers + 2398: 0.19, // Reactive Metals + 2399: 0.19, // Precious Metals + 2400: 0.19, // Toxic Metals + 2401: 0.19, // Chiral Structures + 2463: 0.75, // Nanites + 2469: 0.0, // Lava Basic Industry Facility + 2470: 0.0, // Lava Advanced Industry Facility + 2471: 0.0, // Plasma Basic Industry Facility + 2472: 0.0, // Plasma Advanced Industry Facility + 2473: 0.0, // Barren Basic Industry Facility + 2474: 0.0, // Barren Advanced Industry Facility + 2475: 0.0, // Barren High-Tech Production Plant + 2480: 0.0, // Temperate Advanced Industry Facility + 2481: 0.0, // Temperate Basic Industry Facility + 2482: 0.0, // Temperate High-Tech Production Plant + 2483: 0.0, // Storm Basic Industry Facility + 2484: 0.0, // Storm Advanced Industry Facility + 2485: 0.0, // Oceanic Advanced Industry Facility + 2490: 0.0, // Oceanic Basic Industry Facility + 2491: 0.0, // Ice Advanced Industry Facility + 2492: 0.0, // Gas Basic Industry Facility + 2493: 0.0, // Ice Basic Industry Facility + 2494: 0.0, // Gas Advanced Industry Facility + 2535: 0.0, // Oceanic Storage Facility + 2536: 0.0, // Gas Storage Facility + 2541: 0.0, // Barren Storage Facility + 2542: 0.0, // Oceanic Launchpad + 2543: 0.0, // Gas Launchpad + 2544: 0.0, // Barren Launchpad + 2552: 0.0, // Ice Launchpad + 2555: 0.0, // Lava Launchpad + 2556: 0.0, // Plasma Launchpad + 2557: 0.0, // Storm Launchpad + 2558: 0.0, // Lava Storage Facility + 2560: 0.0, // Plasma Storage Facility + 2561: 0.0, // Storm Storage Facility + 2562: 0.0, // Temperate Storage Facility + 2848: 0.0, // Barren Extractor Control Unit + 2867: 50.0, // Broadcast Node + 2868: 50.0, // Integrity Response Drones + 2869: 50.0, // Nano-Factory + 2870: 50.0, // Organic Mortar Applicators + 2871: 50.0, // Recursive Computing Module + 2872: 50.0, // Self-Harmonizing Power Core + 2875: 50.0, // Sterile Conduits + 2876: 50.0, // Wetware Mainframe + 3060: 0.0, // Gas Extractor Control Unit + 3061: 0.0, // Ice Extractor Control Unit + 3062: 0.0, // Lava Extractor Control Unit + 3063: 0.0, // Oceanic Extractor Control Unit + 3064: 0.0, // Plasma Extractor Control Unit + 3067: 0.0, // Storm Extractor Control Unit + 3068: 0.0, // Temperate Extractor Control Unit + 3645: 0.19, // Water + 3683: 0.19, // Oxygen + 3689: 0.75, // Mechanical Parts + 3691: 0.75, // Synthetic Oil + 3693: 0.75, // Fertilizer + 3695: 0.75, // Polytextiles + 3697: 0.75, // Silicate Glass + 3725: 0.75, // Livestock + 3775: 0.75, // Viral Agent + 3779: 0.19, // Biomass + 3828: 0.75, // Construction Blocks + 9828: 0.19, // Silicon + 9830: 0.75, // Rocket Fuel + 9832: 0.75, // Coolant + 9834: 3.0, // Guidance Systems + 9836: 0.75, // Consumer Electronics + 9838: 0.75, // Superconductors + 9840: 0.75, // Transmitter + 9842: 0.75, // Miniature Electronics + 9846: 3.0, // Planetary Vehicles + 9848: 3.0, // Robotics + 12836: 3.0, // Transcranial Microcontrollers + 15317: 0.75, // Genetically Enhanced Livestock + 17136: 3.0, // Ukomi Superconductors + 17392: 3.0, // Data Chips + 17898: 3.0, // High-Tech Transmitters + 28974: 3.0, // Vaccines } -var StorageCapacities = map[int]int{ +var StorageCapacities = map[int64]int{ 2257: 12000, // Ice Storage Facility 2535: 12000, // Oceanic Storage Facility 2536: 12000, // Gas Storage Facility @@ -422,7 +422,7 @@ var StorageCapacities = map[int]int{ 2557: 10000, // Storm Launchpad } -var LaunchpadIDs = map[int]struct{}{ +var LaunchpadIDs = map[int64]struct{}{ 2256: {}, 2542: {}, 2543: {}, @@ -442,4 +442,4 @@ var ExtractorTypeIDs = map[int]struct{}{ 3064: {}, 3067: {}, 3068: {}, -} \ No newline at end of file +} diff --git a/esi/cached.go b/esi/cached.go index 5d5399d..c6187df 100644 --- a/esi/cached.go +++ b/esi/cached.go @@ -2,8 +2,6 @@ package esi import ( "context" - "crypto/sha256" - "encoding/hex" "encoding/json" "fmt" "os" @@ -16,14 +14,14 @@ import ( ) type CacheDB interface { - GetCacheEntry(urlHash string) (*types.CacheEntry, error) + GetCacheEntry(hash string) (*types.CacheEntry, error) SaveCacheEntry(entry *types.CacheEntry) error } // CachedESI implements ESIInterface with caching type CachedESI struct { - direct ESIInterface - db CacheDB + direct ESIInterface + db CacheDB cacheValidity time.Duration } @@ -47,135 +45,127 @@ func NewCachedESI(direct ESIInterface, db CacheDB) *CachedESI { // 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)) - - url := fmt.Sprintf("/v3/characters/%d/planets/%d/", characterID, planetID) funclog.Info("Starting") - fetchFunc := func() (*PlanetPI, error) { - funclog.Info("Calling direct ESI") - result, err := c.direct.GetPlanetPI(ctx, characterID, planetID, accessToken) - if err != nil { - funclog.Error("Direct ESI call failed: %v", err) + 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 } - if result != 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 + return &planetPI, nil } - - result, err := getCachedResponse(c, url, fetchFunc) + 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 details: %v", err) + funclog.Error("Failed to get planet PI: %v", err) return nil, err } - - 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() + apirespjson, err := json.Marshal(apiresp) if err != nil { - funclog.Error("API fetch failed for URL: %s: %v", url, err) - var zero T - return zero, err + funclog.Error("Failed to marshal planet PI: %v", err) + return nil, err } - funclog.Debug("API fetch successful for URL: %s", url) - - // Store in cache - 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), + cacheEntry := &types.CacheEntry{ + Hash: hash, + Data: string(apirespjson), CachedAt: time.Now(), } - - funclog.Debug("Saving cache entry for URL: %s", url) - if err := c.db.SaveCacheEntry(cacheEntry); err != nil { - 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)) + err = c.db.SaveCacheEntry(cacheEntry) + if err != nil { + funclog.Warning("Failed to save cache entry: %v", err) } - - return result, nil + 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)) - url := fmt.Sprintf("/v1/universe/planets/%d/", planetID) funclog.Info("Starting") - fetchFunc := func() (*PlanetName, error) { - funclog.Info("Calling direct ESI for planet %d name", planetID) - result, err := c.direct.GetPlanetName(ctx, planetID) - if err != nil { - funclog.Error("Direct ESI call failed for planet %d: %v", planetID, err) + 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 } - if result != 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 + return &planetPI, nil } - - result, err := getCachedResponse(c, url, fetchFunc) + 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 for planet %d: %v", planetID, err) + funclog.Error("Failed to get planet name: %v", err) return nil, err } - - if result != nil { - funclog.Info("Successfully retrieved planet name '%s' for planet %d", result.Name, planetID) - } else { - funclog.Info("Successfully retrieved nil planet name for planet %d", planetID) + apirespjson, err := json.Marshal(apiresp) + if err != nil { + funclog.Error("Failed to marshal planet name: %v", err) + return nil, err } - 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{} \ No newline at end of file diff --git a/esi/client.go b/esi/client.go index e3521a5..feb4e49 100644 --- a/esi/client.go +++ b/esi/client.go @@ -20,69 +20,6 @@ const ( 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 { Name string `json:"name"` PlanetID int `json:"planet_id"` @@ -99,20 +36,11 @@ type FactoryDetails struct { 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 type ESIInterface interface { GetCharacterPlanets(ctx context.Context, characterID int, accessToken string) ([]Planet, error) - GetPlanetDetails(ctx context.Context, characterID, planetID int, accessToken string) (*PlanetDetail, error) - GetPlanetName(ctx context.Context, planetID int) (*PlanetName, error) + GetPlanetPI(ctx context.Context, characterID int, planetID int64, accessToken string) (*PlanetPI, error) + GetPlanetName(ctx context.Context, planetID int64) (*PlanetName, error) } // DirectESI implements ESIInterface with direct API calls @@ -138,13 +66,14 @@ func NewDirectESI() *DirectESI { // GetCharacterPlanets retrieves a list of planets for a character 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) 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 } @@ -153,36 +82,37 @@ func (d *DirectESI) GetCharacterPlanets(ctx context.Context, characterID int, ac resp, err := d.httpClient.Do(req) if err != nil { - logger.Error("Failed to fetch character planets: %v", err) + funclog.Error("Failed to fetch character planets: %v", err) return nil, err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { 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)) } var planets []Planet 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 } - logger.Info("Successfully fetched %d planets for character ID %d", len(planets), characterID) + funclog.Info("Successfully fetched %d planets", len(planets)) return planets, nil } -// GetPlanetDetails retrieves detailed information about a specific planet -func (d *DirectESI) GetPlanetDetails(ctx context.Context, characterID, planetID int, accessToken string) (*PlanetDetail, error) { - logger.Debug("Fetching planet details for character ID %d, planet ID %d", characterID, planetID) +// GetPlanetPI retrieves detailed information about a specific planet +func (d *DirectESI) GetPlanetPI(ctx context.Context, characterID int, planetID int64, accessToken string) (*PlanetPI, error) { + 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) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, 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 } @@ -191,36 +121,37 @@ func (d *DirectESI) GetPlanetDetails(ctx context.Context, characterID, planetID resp, err := d.httpClient.Do(req) if err != nil { - logger.Error("Failed to fetch planet details: %v", err) + funclog.Error("Failed to fetch planet details: %v", err) return nil, err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { 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)) } - var planetDetail PlanetDetail - if err := json.NewDecoder(resp.Body).Decode(&planetDetail); err != nil { - logger.Error("Failed to decode planet details response: %v", err) + var pi PlanetPI + if err := json.NewDecoder(resp.Body).Decode(&pi); err != nil { + funclog.Error("Failed to decode planet details response: %v", err) return nil, err } - logger.Info("Successfully fetched planet details for character ID %d, planet ID %d", characterID, planetID) - return &planetDetail, nil + funclog.Info("Successfully fetched planet details") + return &pi, nil } // GetPlanetName retrieves planet name from universe endpoint -func (d *DirectESI) GetPlanetName(ctx context.Context, planetID int) (*PlanetName, error) { - logger.Debug("Fetching planet name for planet ID %d", planetID) +func (d *DirectESI) GetPlanetName(ctx context.Context, planetID int64) (*PlanetName, error) { + 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) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, 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 } @@ -228,28 +159,30 @@ func (d *DirectESI) GetPlanetName(ctx context.Context, planetID int) (*PlanetNam resp, err := d.httpClient.Do(req) if err != nil { - logger.Error("Failed to fetch planet name: %v", err) + funclog.Error("Failed to fetch planet name: %v", err) return nil, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) 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 } 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)) } var planetName PlanetName 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 } - 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 } + +var _ ESIInterface = &DirectESI{} \ No newline at end of file diff --git a/esi/types.go b/esi/types.go index 99dba82..d15e12b 100644 --- a/esi/types.go +++ b/esi/types.go @@ -32,7 +32,7 @@ type Content struct { type Route struct { ContentTypeID int64 `json:"content_type_id"` DestinationPinID int64 `json:"destination_pin_id"` - Quantity int64 `json:"quantity"` + Quantity float64 `json:"quantity"` RouteID int64 `json:"route_id"` SourcePinID int64 `json:"source_pin_id"` Waypoints []int64 `json:"waypoints"` diff --git a/repositories/cache.go b/repositories/cache.go index 970e77a..f5b5254 100644 --- a/repositories/cache.go +++ b/repositories/cache.go @@ -1,6 +1,7 @@ package repositories import ( + "fmt" "go-eve-pi/types" 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 -func (r *CacheRepository) GetCacheEntry(urlHash string) (*types.CacheEntry, error) { - logger.Debug("Fetching cache entry for hash: %s", urlHash) +func (r *CacheRepository) GetCacheEntry(hash string) (*types.CacheEntry, error) { + funclog := logger.Default.WithPrefix("CacheRepository.GetCacheEntry").WithPrefix(fmt.Sprintf("hash=%s", hash)) + funclog.Info("Starting") 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 { - logger.Debug("No cache entry found for hash %s: %v", urlHash, err) + funclog.Debug("No cache entry found: %v", err) return nil, err } - logger.Debug("Cache entry found for hash %s", urlHash) + funclog.Debug("Cache entry found") return &entry, nil } // SaveCacheEntry saves a cache entry to the database 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 if err != nil { return err } - logger.Debug("Cache entry saved successfully for hash %s", entry.URLHash) + funclog.Debug("Cache entry saved successfully") return nil } diff --git a/types/character.go b/types/types.go similarity index 78% rename from types/character.go rename to types/types.go index a87d6b9..c53a963 100644 --- a/types/character.go +++ b/types/types.go @@ -13,10 +13,9 @@ type Character struct { CreatedAt time.Time } -// CacheEntry represents a cached API response type CacheEntry struct { ID uint `gorm:"primaryKey"` - URLHash string `gorm:"uniqueIndex"` - Response string `gorm:"type:text"` + Hash string `gorm:"uniqueIndex"` + Data string `gorm:"type:text"` CachedAt time.Time `gorm:"index"` }