X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=episodecache.go;h=727a2a8691af3f27cf1769dea6e4495e3f4e7c44;hb=59d77e55f0aaa0643c71a5066399f3d7ce740de6;hp=4d8fa7e87aca36ea2a3ec6c37f9525cc46fcfe90;hpb=198d18d4efdc831b043cd894cf88139a5381096a;p=go-anidb.git diff --git a/episodecache.go b/episodecache.go index 4d8fa7e..727a2a8 100644 --- a/episodecache.go +++ b/episodecache.go @@ -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,15 +26,15 @@ 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. @@ -45,32 +43,41 @@ func cacheEpisode(ep *Episode) { // 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 @@ -90,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 }