From ff4149ecbd0e7cc2b6a7b91a549403617356e989 Mon Sep 17 00:00:00 2001 From: ashisgreat22 Date: Tue, 24 Mar 2026 01:08:09 +0100 Subject: [PATCH] cache: add tier definitions and EngineTier function Co-Authored-By: Claude Opus 4.6 --- internal/cache/tiers.go | 56 ++++++++++++++++++++++++++++++++++++ internal/cache/tiers_test.go | 33 +++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 internal/cache/tiers.go create mode 100644 internal/cache/tiers_test.go diff --git a/internal/cache/tiers.go b/internal/cache/tiers.go new file mode 100644 index 0000000..6df07ab --- /dev/null +++ b/internal/cache/tiers.go @@ -0,0 +1,56 @@ +package cache + +import "time" + +// TTLTier represents a cache TTL tier with a name and duration. +type TTLTier struct { + Name string + Duration time.Duration +} + +// defaultTiers maps engine names to their default TTL tiers. +var defaultTiers = map[string]TTLTier{ + // Static knowledge engines — rarely change + "wikipedia": {Name: "static", Duration: 24 * time.Hour}, + "wikidata": {Name: "static", Duration: 24 * time.Hour}, + "arxiv": {Name: "static", Duration: 24 * time.Hour}, + "crossref": {Name: "static", Duration: 24 * time.Hour}, + "stackoverflow": {Name: "static", Duration: 24 * time.Hour}, + "github": {Name: "static", Duration: 24 * time.Hour}, + + // API-based general search — fresher data + "braveapi": {Name: "api_general", Duration: 1 * time.Hour}, + "youtube": {Name: "api_general", Duration: 1 * time.Hour}, + + // Scraped general search — moderately stable + "google": {Name: "scraped_general", Duration: 2 * time.Hour}, + "bing": {Name: "scraped_general", Duration: 2 * time.Hour}, + "duckduckgo": {Name: "scraped_general", Duration: 2 * time.Hour}, + "qwant": {Name: "scraped_general", Duration: 2 * time.Hour}, + "brave": {Name: "scraped_general", Duration: 2 * time.Hour}, + + // News/social — changes frequently + "reddit": {Name: "news_social", Duration: 30 * time.Minute}, + + // Image search + "bing_images": {Name: "images", Duration: 1 * time.Hour}, + "ddg_images": {Name: "images", Duration: 1 * time.Hour}, + "qwant_images": {Name: "images", Duration: 1 * time.Hour}, +} + +// EngineTier returns the TTL tier for an engine, applying overrides if provided. +// If the engine has no defined tier, returns a default of 1 hour. +func EngineTier(engineName string, overrides map[string]time.Duration) TTLTier { + // Check override first — override tier name is just the engine name + if override, ok := overrides[engineName]; ok && override > 0 { + return TTLTier{Name: engineName, Duration: override} + } + + // Fall back to default tier + if tier, ok := defaultTiers[engineName]; ok { + return tier + } + + // Unknown engines get a sensible default + return TTLTier{Name: "unknown", Duration: 1 * time.Hour} +} \ No newline at end of file diff --git a/internal/cache/tiers_test.go b/internal/cache/tiers_test.go new file mode 100644 index 0000000..b9419a9 --- /dev/null +++ b/internal/cache/tiers_test.go @@ -0,0 +1,33 @@ +package cache + +import ( + "testing" + "time" +) + +func TestEngineTier(t *testing.T) { + // Test default static tier + tier := EngineTier("wikipedia", nil) + if tier.Name != "static" || tier.Duration != 24*time.Hour { + t.Errorf("wikipedia: expected static/24h, got %s/%v", tier.Name, tier.Duration) + } + + // Test default api_general tier + tier = EngineTier("braveapi", nil) + if tier.Name != "api_general" || tier.Duration != 1*time.Hour { + t.Errorf("braveapi: expected api_general/1h, got %s/%v", tier.Name, tier.Duration) + } + + // Test override takes precedence — override tier name is just the engine name + override := 48 * time.Hour + tier = EngineTier("wikipedia", map[string]time.Duration{"wikipedia": override}) + if tier.Name != "wikipedia" || tier.Duration != 48*time.Hour { + t.Errorf("wikipedia override: expected wikipedia/48h, got %s/%v", tier.Name, tier.Duration) + } + + // Test unknown engine gets default + tier = EngineTier("unknown_engine", nil) + if tier.Name != "unknown" || tier.Duration != 1*time.Hour { + t.Errorf("unknown engine: expected unknown/1h, got %s/%v", tier.Name, tier.Duration) + } +} \ No newline at end of file