12 gob.RegisterName("*github.com/Kovensky/go-anidb.Episode", &Episode{})
15 func (e *Episode) Touch() {
19 func (e *Episode) IsStale() bool {
23 return time.Now().Sub(e.Cached) > EpisodeCacheDuration
26 var eidAidMap = map[EID]AID{}
27 var eidAidLock = sync.RWMutex{}
29 // Unique Episode IDentifier.
32 // Retrieves the Episode corresponding to this EID from the cache.
33 func (eid EID) Episode() *Episode {
34 e, _ := caches.Get(episodeCache).Get(int(eid)).(*Episode)
38 func cacheEpisode(ep *Episode) {
40 defer eidAidLock.Unlock()
42 eidAidMap[ep.EID] = ep.AID
43 caches.Get(episodeCache).Set(int(ep.EID), ep)
46 // Retrieves the Episode from the cache if possible.
48 // If the result is stale, then queries the UDP API to
49 // know which AID owns this EID, then gets the episodes
51 func (adb *AniDB) EpisodeByID(eid EID) <-chan *Episode {
52 ch := make(chan *Episode, 1)
54 if e := eid.Episode(); e != nil && !e.IsStale() {
60 ec := caches.Get(episodeCache)
61 ic := make(chan Cacheable, 1)
62 go func() { ch <- (<-ic).(*Episode); close(ch) }()
63 if ec.Intent(int(eid), ic) {
68 // The UDP API data is worse than the HTTP API anime data,
69 // try and get from the corresponding Anime
72 aid, ok := eidAidMap[eid]
78 for i := 0; i < 2; i++ {
80 // couldn't get anime and we already ran the EPISODE query
85 // We don't know what the AID is yet.
86 reply := <-adb.udp.SendRecv("EPISODE", paramMap{"eid": eid})
88 if reply.Error() == nil {
89 parts := strings.Split(reply.Lines()[1], "|")
91 if id, err := strconv.ParseInt(parts[1], 10, 32); err == nil {
100 <-adb.AnimeByID(AID(aid)) // this caches episodes...
101 e = eid.Episode() // ...so this is now a cache hit
106 // if this is somehow still a miss, then the EID<->AID map broke
108 delete(eidAidMap, eid)
114 // Caching (and channel broadcasting) done by AnimeByID