Fixed a race condition and improved cache interface.
This commit is contained in:
@@ -2,6 +2,7 @@ package types
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -18,6 +19,7 @@ type CacheEntity[T cacheType] struct {
|
||||
|
||||
// Cache, representing a mapping between a key(str) and a CacheEntity
|
||||
type Cache[T cacheType] struct {
|
||||
mu sync.RWMutex
|
||||
Data map[string]CacheEntity[T]
|
||||
}
|
||||
|
||||
@@ -28,7 +30,7 @@ type Caches struct {
|
||||
WindCache Cache[Wind]
|
||||
DailyForecastCache Cache[DailyForecast]
|
||||
HourlyForecastCache Cache[HourlyForecast]
|
||||
MoonCache CacheEntity[Moon]
|
||||
MoonCache Cache[Moon]
|
||||
}
|
||||
|
||||
func InitCache() *Caches {
|
||||
@@ -38,11 +40,14 @@ func InitCache() *Caches {
|
||||
WindCache: Cache[Wind]{Data: make(map[string]CacheEntity[Wind])},
|
||||
DailyForecastCache: Cache[DailyForecast]{Data: make(map[string]CacheEntity[DailyForecast])},
|
||||
HourlyForecastCache: Cache[HourlyForecast]{Data: make(map[string]CacheEntity[HourlyForecast])},
|
||||
MoonCache: CacheEntity[Moon]{element: Moon{}, timestamp: time.Time{}},
|
||||
MoonCache: Cache[Moon]{Data: make(map[string]CacheEntity[Moon])},
|
||||
}
|
||||
}
|
||||
|
||||
func (cache *Cache[T]) GetEntry(cityName string, ttl int8) (T, bool) {
|
||||
cache.mu.RLock()
|
||||
defer cache.mu.RUnlock()
|
||||
|
||||
val, isPresent := cache.Data[strings.ToUpper(cityName)]
|
||||
|
||||
// If key is not present, return a zero value
|
||||
@@ -61,6 +66,9 @@ func (cache *Cache[T]) GetEntry(cityName string, ttl int8) (T, bool) {
|
||||
}
|
||||
|
||||
func (cache *Cache[T]) AddEntry(entry T, cityName string) {
|
||||
cache.mu.Lock()
|
||||
defer cache.mu.Unlock()
|
||||
|
||||
currentTime := time.Now()
|
||||
|
||||
cache.Data[strings.ToUpper(cityName)] = CacheEntity[T]{
|
||||
@@ -68,26 +76,3 @@ func (cache *Cache[T]) AddEntry(entry T, cityName string) {
|
||||
timestamp: currentTime,
|
||||
}
|
||||
}
|
||||
|
||||
func (moon *CacheEntity[Moon]) GetEntry(ttl int8) (Moon, bool) {
|
||||
var zeroMoon Moon
|
||||
|
||||
// If moon data is not present, return a zero value
|
||||
if moon == nil {
|
||||
return zeroMoon, false
|
||||
}
|
||||
|
||||
// Otherwise check whether the element is expired
|
||||
currentTime := time.Now()
|
||||
expired := currentTime.Sub(moon.timestamp) > (time.Duration(ttl) * time.Hour)
|
||||
if expired {
|
||||
return zeroMoon, false
|
||||
}
|
||||
|
||||
return moon.element, true
|
||||
}
|
||||
|
||||
func (cache *CacheEntity[Moon]) AddEntry(entry Moon) {
|
||||
cache.element = entry
|
||||
cache.timestamp = time.Now()
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@ package types
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// StatDB data type, representing a mapping between a location and its weather
|
||||
type StatDB struct {
|
||||
mu sync.RWMutex
|
||||
db map[string]Weather
|
||||
}
|
||||
|
||||
@@ -18,6 +20,9 @@ func InitDB() *StatDB {
|
||||
}
|
||||
|
||||
func (statDB *StatDB) AddStatistic(cityName string, weather Weather) {
|
||||
statDB.mu.Lock()
|
||||
defer statDB.mu.Unlock()
|
||||
|
||||
key := fmt.Sprintf("%s@%s", weather.Date.Date.Format("2006-01-02"), cityName)
|
||||
|
||||
// Insert weather statistic into the database only if it isn't present
|
||||
@@ -29,6 +34,9 @@ func (statDB *StatDB) AddStatistic(cityName string, weather Weather) {
|
||||
}
|
||||
|
||||
func (statDB *StatDB) IsKeyInvalid(key string) bool {
|
||||
statDB.mu.RLock()
|
||||
defer statDB.mu.RUnlock()
|
||||
|
||||
// A key is invalid if it has less than 2 entries within the last 2 days
|
||||
threshold := time.Now().AddDate(0, 0, -2)
|
||||
|
||||
@@ -52,6 +60,9 @@ func (statDB *StatDB) IsKeyInvalid(key string) bool {
|
||||
}
|
||||
|
||||
func (statDB *StatDB) GetCityStatistics(cityName string) []Weather {
|
||||
statDB.mu.RLock()
|
||||
defer statDB.mu.RUnlock()
|
||||
|
||||
result := make([]Weather, 0)
|
||||
|
||||
for key, record := range statDB.db {
|
||||
|
||||
Reference in New Issue
Block a user