]> git.lizzy.rs Git - go-anidb.git/blobdiff - episodecache.go
misc: Support partial episodes
[go-anidb.git] / episodecache.go
index cfc44d98ffebbb41bbcd6491d95f00f3574ea552..cd2e4aa0c6d4a17e6d48677cb9249e2c6155e68b 100644 (file)
@@ -40,10 +40,20 @@ func cacheEpisode(ep *Episode) {
 }
 
 // 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}
        ch := make(chan *Episode, 1)
 
+       if eid < 1 {
+               ch <- nil
+               close(ch)
+               return ch
+       }
+
        ic := make(chan Cacheable, 1)
        go func() { ch <- (<-ic).(*Episode); close(ch) }()
        if intentMap.Intent(ic, keys...) {
@@ -51,12 +61,13 @@ func (adb *AniDB) EpisodeByID(eid EID) <-chan *Episode {
        }
 
        if !cache.CheckValid(keys...) {
-               intentMap.Notify((*Episode)(nil), keys...)
+               intentMap.NotifyClose((*Episode)(nil), keys...)
                return ch
        }
 
-       if e := eid.Episode(); !e.IsStale() {
-               intentMap.Notify(e, keys...)
+       e := eid.Episode()
+       if !e.IsStale() {
+               intentMap.NotifyClose(e, keys...)
                return ch
        }
 
@@ -69,7 +80,6 @@ func (adb *AniDB) EpisodeByID(eid EID) <-chan *Episode {
 
                udpDone := false
 
-               var e *Episode
                for i := 0; i < 2; i++ {
                        if !ok && udpDone {
                                // couldn't get anime and we already ran the EPISODE query
@@ -86,26 +96,31 @@ 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?
+                                       break
                                } else {
                                        break
                                }
                                udpDone = true
                        }
-                       <-adb.AnimeByID(AID(aid)) // this caches episodes...
-                       e = 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 e != nil {
+                       if ep != nil {
+                               e = ep
                                break
                        } else {
-                               // if this is somehow still a miss, then the EID<->AID map broke
-                               cache.Delete("aid", "by-eid", eid)
+                               // the EID<->AID map broke
                                ok = false
+                               cache.Delete("aid", "by-eid", eid)
                        }
                }
-               intentMap.Notify(e, keys...)
+               intentMap.NotifyClose(e, keys...)
        }()
        return ch
 }