4 "github.com/Kovensky/go-fscache"
10 var _ cacheable = &Episode{}
12 func (e *Episode) setCachedTS(ts time.Time) {
16 func (e *Episode) IsStale() bool {
20 return time.Now().Sub(e.Cached) > EpisodeCacheDuration
23 // Unique Episode IDentifier.
26 // Retrieves the Episode corresponding to this EID from the cache.
27 func (eid EID) Episode() *Episode {
29 if CacheGet(&e, "eid", eid) == nil {
35 func cacheEpisode(ep *Episode) {
36 CacheSet(ep.AID, "aid", "by-eid", ep.EID)
37 CacheSet(ep, "eid", ep.EID)
40 // Retrieves an Episode by its EID.
42 // If we know which AID owns this EID, then it's equivalent
43 // to an Anime query. Otherwise, uses both the HTTP and UDP
44 // APIs to retrieve it.
45 func (adb *AniDB) EpisodeByID(eid EID) <-chan *Episode {
46 key := []fscache.CacheKey{"eid", eid}
47 ch := make(chan *Episode, 1)
55 ic := make(chan notification, 1)
56 go func() { ch <- (<-ic).(*Episode); close(ch) }()
57 if intentMap.Intent(ic, key...) {
61 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
62 intentMap.NotifyClose((*Episode)(nil), key...)
68 intentMap.NotifyClose(e, key...)
73 // The UDP API data is worse than the HTTP API anime data and
74 // might even get truncated on some pathological cases;
75 // try and get from the corresponding Anime, which uses the HTTP
79 _, err := Cache.Get(&aid, "aid", "by-eid", eid)
84 for i := 0; i < 2; i++ {
86 // couldn't get anime and we already ran the EPISODE query
91 // We don't know what the AID is yet.
92 reply := <-adb.udp.SendRecv("EPISODE", paramMap{"eid": eid})
94 if reply.Error() == nil {
95 parts := strings.Split(reply.Lines()[1], "|")
97 if id, err := strconv.ParseInt(parts[1], 10, 32); err == nil {
103 } else if reply.Code() == 340 {
104 Cache.SetInvalid(key...)
111 a := <-adb.AnimeByID(AID(aid)) // updates the episode cache as well
112 ep := a.EpisodeByEID(eid)
118 // the EID<->AID map broke
120 Cache.Delete("aid", "by-eid", eid)
123 intentMap.NotifyClose(e, key...)