From 7498f4128afc97b112bd9fe8474a85e981d88db3 Mon Sep 17 00:00:00 2001 From: partisan Date: Thu, 5 Dec 2024 19:47:53 +0100 Subject: [PATCH] added caching to map results --- cache.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ init.go | 1 + map.go | 22 +++++++++++++++++---- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/cache.go b/cache.go index c116cc9..b5ad880 100644 --- a/cache.go +++ b/cache.go @@ -62,6 +62,23 @@ type ForumSearchResult struct { ThumbnailSrc string `json:"thumbnailSrc,omitempty"` } +// GeocodeCachedItem represents a geocoding result stored in the cache. +type GeocodeCachedItem struct { + Latitude string + Longitude string + Found bool + StoredTime time.Time +} + +// GeocodeCache is a thread-safe map for caching geocoding results. +type GeocodeCache struct { + mu sync.Mutex + results map[string]GeocodeCachedItem + expiration time.Duration +} + +var geocodeCache *GeocodeCache + // CacheKey represents the key used to store search results in the cache. type CacheKey struct { Query string @@ -95,6 +112,15 @@ func NewResultsCache() *ResultsCache { } } +// NewGeocodeCache creates a new GeocodeCache with a specified expiration duration. +func NewGeocodeCache() *GeocodeCache { + printDebug("Initializing geocode cache with expiration: %s", config.RamCache.Duration) + return &GeocodeCache{ + results: make(map[string]GeocodeCachedItem), + expiration: config.RamCache.Duration, + } +} + // Get retrieves the results for a given key from the cache. func (rc *ResultsCache) Get(key CacheKey) ([]SearchResult, bool) { rc.mu.Lock() @@ -151,6 +177,38 @@ func (rc *ResultsCache) currentMemoryUsage() uint64 { return v.Used // Used memory in bytes } +// Get retrieves the geocoding result for a given query from the cache. +func (gc *GeocodeCache) Get(query string) (latitude, longitude string, found bool, exists bool) { + gc.mu.Lock() + defer gc.mu.Unlock() + + item, exists := gc.results[query] + if !exists { + return "", "", false, false + } + + // Check if the item has expired + if time.Since(item.StoredTime) > gc.expiration { + delete(gc.results, query) + printDebug("Geocode cache expired for query: %s", query) + return "", "", false, false + } + + return item.Latitude, item.Longitude, item.Found, true +} + +func (gc *GeocodeCache) Set(query, latitude, longitude string, found bool) { + gc.mu.Lock() + defer gc.mu.Unlock() + + gc.results[query] = GeocodeCachedItem{ + Latitude: latitude, + Longitude: longitude, + Found: found, + StoredTime: time.Now(), + } +} + func (rc *ResultsCache) cleanOldestItems() { rc.mu.Lock() defer rc.mu.Unlock() diff --git a/init.go b/init.go index 0e86684..e7d4ed1 100644 --- a/init.go +++ b/init.go @@ -89,6 +89,7 @@ func main() { // Start periodic cleanup of expired cache files if config.RamCacheEnabled { resultsCache = NewResultsCache() + geocodeCache = NewGeocodeCache() printInfo("RAM cache started.") } else { printInfo("RAM cache is disabled.") diff --git a/map.go b/map.go index 9bc3e32..4927fc0 100755 --- a/map.go +++ b/map.go @@ -14,11 +14,20 @@ type NominatimResponse struct { } func geocodeQuery(query string) (latitude, longitude string, found bool, err error) { + // First, check if the result is in the cache + cachedLat, cachedLon, cachedFound, exists := geocodeCache.Get(query) + if exists { + printDebug("Geocode cache hit for query: %s", query) + return cachedLat, cachedLon, cachedFound, nil + } + + printDebug("Geocode cache miss for query: %s", query) + // URL encode the query - query = url.QueryEscape(query) + queryEscaped := url.QueryEscape(query) // Construct the request URL - urlString := fmt.Sprintf("https://nominatim.openstreetmap.org/search?format=json&q=%s", query) + urlString := fmt.Sprintf("https://nominatim.openstreetmap.org/search?format=json&q=%s", queryEscaped) // Make the HTTP GET request resp, err := http.Get(urlString) @@ -37,10 +46,15 @@ func geocodeQuery(query string) (latitude, longitude string, found bool, err err if len(result) > 0 { latitude = result[0].Lat longitude = result[0].Lon - return latitude, longitude, true, nil + found = true + } else { + found = false } - return "", "", false, nil + // Store the result in the cache + geocodeCache.Set(query, latitude, longitude, found) + + return latitude, longitude, found, nil } func handleMapSearch(w http.ResponseWriter, settings UserSettings, query string) {