80 lines
1.7 KiB
Go
80 lines
1.7 KiB
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
"sync/atomic"
|
|
)
|
|
|
|
type CacheStats struct {
|
|
Hits int64
|
|
Misses int64
|
|
Size int
|
|
}
|
|
|
|
type CachedGeocoder struct {
|
|
underlying GeocodingService
|
|
cache map[string]string
|
|
mutex sync.RWMutex
|
|
hits int64
|
|
misses int64
|
|
}
|
|
|
|
func NewCachedGeocodingService(underlying GeocodingService) *CachedGeocoder {
|
|
return &CachedGeocoder{
|
|
underlying: underlying,
|
|
cache: make(map[string]string),
|
|
}
|
|
}
|
|
|
|
func (g *CachedGeocoder) GetAddressFromCoordinates(latitude, longitude float64) (string, error) {
|
|
cacheKey := fmt.Sprintf("%.6f,%.6f", latitude, longitude)
|
|
|
|
// Check cache first
|
|
g.mutex.RLock()
|
|
if address, ok := g.cache[cacheKey]; ok {
|
|
g.mutex.RUnlock()
|
|
atomic.AddInt64(&g.hits, 1)
|
|
log.Printf("CACHE HIT: Coordinates (%.6f,%.6f) found in cache", latitude, longitude)
|
|
return address, nil
|
|
}
|
|
g.mutex.RUnlock()
|
|
|
|
log.Printf("CACHE MISS: Coordinates (%.6f,%.6f) not in cache, fetching from service", latitude, longitude)
|
|
atomic.AddInt64(&g.misses, 1)
|
|
|
|
// Not in cache, call the underlying service
|
|
address, err := g.underlying.GetAddressFromCoordinates(latitude, longitude)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Cache the result
|
|
g.mutex.Lock()
|
|
g.cache[cacheKey] = address
|
|
g.mutex.Unlock()
|
|
log.Printf("CACHE UPDATE: Coordinates (%.6f,%.6f) added to cache", latitude, longitude)
|
|
|
|
return address, nil
|
|
}
|
|
|
|
// GetStats returns the current cache statistics
|
|
func (g *CachedGeocoder) GetStats() CacheStats {
|
|
g.mutex.RLock()
|
|
stats := CacheStats{
|
|
Hits: g.hits,
|
|
Misses: g.misses,
|
|
Size: len(g.cache),
|
|
}
|
|
g.mutex.RUnlock()
|
|
return stats
|
|
}
|
|
|
|
// ClearCache empties the cache
|
|
func (g *CachedGeocoder) ClearCache() {
|
|
g.mutex.Lock()
|
|
g.cache = make(map[string]string)
|
|
g.mutex.Unlock()
|
|
}
|