diff --git a/bird/bird.go b/bird/bird.go index cd58014..9d9797b 100644 --- a/bird/bird.go +++ b/bird/bird.go @@ -66,6 +66,10 @@ func toCache(key string, val Parsed) bool { /* Convenience method to retrieve entries from the cache. * Abstracts over the specific caching implementations. + * If err returned by cache.Get(key) is set, the value from the cache is not + * used. There is either a fault e.g. missing entry or the ttl is expired. + * Handling of specific error conditions e.g. ttl expired but entry present is + * possible but currently not implemented. */ func fromCache(key string) (Parsed, bool) { val, err := cache.Get(key) diff --git a/bird/redis_cache.go b/bird/redis_cache.go index 6335b8b..f20f7e8 100644 --- a/bird/redis_cache.go +++ b/bird/redis_cache.go @@ -2,12 +2,15 @@ package bird import ( "encoding/json" - "github.com/go-redis/redis" + "errors" "time" + + "github.com/go-redis/redis" ) type RedisCache struct { - client *redis.Client + client *redis.Client + keyPrefix string } func NewRedisCache(config CacheConfig) (*RedisCache, error) { @@ -31,6 +34,7 @@ func NewRedisCache(config CacheConfig) (*RedisCache, error) { } func (self *RedisCache) Get(key string) (Parsed, error) { + key = self.keyPrefix + key //"B" + IPVersion + "_" + key data, err := self.client.Get(key).Result() if err != nil { return NilParse, err @@ -39,15 +43,34 @@ func (self *RedisCache) Get(key string) (Parsed, error) { parsed := Parsed{} err = json.Unmarshal([]byte(data), &parsed) - return parsed, err -} - -func (self *RedisCache) Set(key string, parsed Parsed) error { - payload, err := json.Marshal(parsed) - if err != nil { - return err + ttl, correct := parsed["ttl"].(time.Time) + if !correct { + return NilParse, errors.New("Invalid TTL value for key" + key) } - _, err = self.client.Set(key, payload, time.Minute*5).Result() - return err + if ttl.Before(time.Now()) { + return NilParse, err // TTL expired + } else { + return parsed, err // cache hit + } +} + +func (self *RedisCache) Set(key string, parsed Parsed, ttl int) error { + switch { + case ttl == 0: + return nil // do not cache + + case ttl > 0: + key = self.keyPrefix + key //TODO "B" + IPVersion + "_" + key + payload, err := json.Marshal(parsed) + if err != nil { + return err + } + + _, err = self.client.Set(key, payload, time.Duration(ttl)*time.Minute).Result() + return err + + default: // ttl negative - invalid + return errors.New("Negative TTL value for key" + key) + } } diff --git a/bird/redis_cache_test.go b/bird/redis_cache_test.go index a8b6103..d84492c 100644 --- a/bird/redis_cache_test.go +++ b/bird/redis_cache_test.go @@ -23,7 +23,7 @@ func Test_RedisCacheAccess(t *testing.T) { } t.Log("Setting redis cache...") - err = cache.Set("testkey", parsed) + err = cache.Set("testkey", parsed, 5) if err != nil { t.Error(err) } @@ -80,7 +80,7 @@ func Test_RedisCacheRoutes(t *testing.T) { return } - err = cache.Set("routes_protocol_test", parsed) + err = cache.Set("routes_protocol_test", parsed, 5) if err != nil { t.Error(err) } diff --git a/birdwatcher.go b/birdwatcher.go index 3c6df3d..a186f52 100644 --- a/birdwatcher.go +++ b/birdwatcher.go @@ -173,7 +173,7 @@ func main() { var cache bird.Cache if conf.Cache.UseRedis { - bird.CacheRedis, err = bird.NewRedisCache(conf.Cache) + cache, err = bird.NewRedisCache(conf.Cache) if err != nil { log.Fatal("Could not initialize redis cache, falling back to MemoryCache:", err) }