]> git.lizzy.rs Git - go-anidb.git/blobdiff - episodecache.go
anidb: Correct cache key for LID.MyListEntry
[go-anidb.git] / episodecache.go
index 00b2a405ec22243287504dd4a1bfa195bb79384d..727a2a8691af3f27cf1769dea6e4495e3f4e7c44 100644 (file)
@@ -1,18 +1,16 @@
 package anidb
 
 import (
-       "encoding/gob"
+       "github.com/Kovensky/go-fscache"
        "strconv"
        "strings"
        "time"
 )
 
-func init() {
-       gob.RegisterName("*github.com/Kovensky/go-anidb.Episode", &Episode{})
-}
+var _ cacheable = &Episode{}
 
-func (e *Episode) Touch() {
-       e.Cached = time.Now()
+func (e *Episode) setCachedTS(ts time.Time) {
+       e.Cached = ts
 }
 
 func (e *Episode) IsStale() bool {
@@ -28,45 +26,58 @@ type EID int
 // Retrieves the Episode corresponding to this EID from the cache.
 func (eid EID) Episode() *Episode {
        var e Episode
-       if cache.Get(&e, "eid", eid) == nil {
+       if CacheGet(&e, "eid", eid) == nil {
                return &e
        }
        return nil
 }
 
 func cacheEpisode(ep *Episode) {
-       cache.Set(ep.AID, "aid", "by-eid", ep.EID)
-       cache.Set(ep, "eid", ep.EID)
+       CacheSet(ep.AID, "aid", "by-eid", ep.EID)
+       CacheSet(ep, "eid", ep.EID)
 }
 
 // Retrieves an Episode by its EID.
+//
+// If we know which AID owns this EID, then it's equivalent
+// to an Anime query. Otherwise, uses both the HTTP and UDP
+// APIs to retrieve it.
 func (adb *AniDB) EpisodeByID(eid EID) <-chan *Episode {
-       keys := []cacheKey{"eid", eid}
+       key := []fscache.CacheKey{"eid", eid}
        ch := make(chan *Episode, 1)
 
-       ic := make(chan Cacheable, 1)
+       if eid < 1 {
+               ch <- nil
+               close(ch)
+               return ch
+       }
+
+       ic := make(chan notification, 1)
        go func() { ch <- (<-ic).(*Episode); close(ch) }()
-       if intentMap.Intent(ic, keys...) {
+       if intentMap.Intent(ic, key...) {
                return ch
        }
 
-       if !cache.CheckValid(keys...) {
-               intentMap.Notify((*Episode)(nil), keys...)
+       if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
+               intentMap.NotifyClose((*Episode)(nil), key...)
                return ch
        }
 
        e := eid.Episode()
        if !e.IsStale() {
-               intentMap.Notify(e, keys...)
+               intentMap.NotifyClose(e, key...)
                return ch
        }
 
        go func() {
-               // The UDP API data is worse than the HTTP API anime data,
-               // try and get from the corresponding Anime
+               // The UDP API data is worse than the HTTP API anime data and
+               // might even get truncated on some pathological cases;
+               // try and get from the corresponding Anime, which uses the HTTP
+               // API episode list.
 
                aid := AID(0)
-               ok := cache.Get(&aid, "aid", "by-eid", eid) == nil
+               _, err := Cache.Get(&aid, "aid", "by-eid", eid)
+               ok := err == nil
 
                udpDone := false
 
@@ -86,45 +97,30 @@ func (adb *AniDB) EpisodeByID(eid EID) <-chan *Episode {
                                        if id, err := strconv.ParseInt(parts[1], 10, 32); err == nil {
                                                ok = true
                                                aid = AID(id)
+                                       } else {
+                                               break
                                        }
                                } else if reply.Code() == 340 {
-                                       cache.MarkInvalid(keys...)
-                                       cache.Delete(keys...) // deleted EID?
+                                       Cache.SetInvalid(key...)
+                                       break
                                } else {
                                        break
                                }
                                udpDone = true
                        }
-                       a := <-adb.AnimeByID(AID(aid)) // this caches episodes...
-                       ep := eid.Episode()            // ...so this is now a cache hit
+                       a := <-adb.AnimeByID(AID(aid)) // updates the episode cache as well
+                       ep := a.EpisodeByEID(eid)
 
-                       if !ep.IsStale() {
+                       if ep != nil {
                                e = ep
                                break
                        } else {
+                               // the EID<->AID map broke
                                ok = false
-
-                               // check to see if we looked in the right AID
-                               found := false
-                               if a != nil {
-                                       for _, ep := range a.Episodes {
-                                               if eid == ep.EID {
-                                                       found = true
-                                                       break
-                                               }
-                                       }
-                               }
-
-                               // if found, then it's just that the anime is also stale (offline?)
-                               if found {
-                                       break
-                               } else {
-                                       // otherwise, the EID<->AID map broke
-                                       cache.Delete("aid", "by-eid", eid)
-                               }
+                               Cache.Delete("aid", "by-eid", eid)
                        }
                }
-               intentMap.Notify(e, keys...)
+               intentMap.NotifyClose(e, key...)
        }()
        return ch
 }