package anidb
import (
- "encoding/gob"
"github.com/Kovensky/go-anidb/http"
"github.com/Kovensky/go-anidb/udp"
+ "github.com/Kovensky/go-fscache"
"strconv"
"strings"
"time"
)
-func init() {
- gob.RegisterName("*github.com/Kovensky/go-anidb.Group", &Group{})
- gob.RegisterName("github.com/Kovensky/go-anidb.GID", GID(0))
- gob.RegisterName("*github.com/Kovensky/go-anidb.gidCache", &gidCache{})
-}
+var _ cacheable = &Group{}
-func (g *Group) Touch() {
- g.Cached = time.Now()
+func (g *Group) setCachedTS(ts time.Time) {
+ g.Cached = ts
}
func (g *Group) IsStale() bool {
// Unique Group IDentifier
type GID int
-// make GID cacheable
-
-func (e GID) Touch() {}
-func (e GID) IsStale() bool { return false }
+func cacheGroup(g *Group) {
+ CacheSet(g.GID, "gid", "by-name", g.Name)
+ CacheSet(g.GID, "gid", "by-shortname", g.ShortName)
+ CacheSet(g, "gid", g.GID)
+}
// Retrieves the Group from the cache.
func (gid GID) Group() *Group {
var g Group
- if cache.Get(&g, "gid", gid) == nil {
+ if CacheGet(&g, "gid", gid) == nil {
return &g
}
return nil
}
-type gidCache struct {
- GID
- Time time.Time
-}
-
-func (c *gidCache) Touch() { c.Time = time.Now() }
-func (c *gidCache) IsStale() bool {
- if c != nil && time.Now().Sub(c.Time) < GroupCacheDuration {
- return false
- }
- return true
-}
-
-// Retrieves a Group by its GID.
+// Retrieves a Group by its GID. Uses the UDP API.
func (adb *AniDB) GroupByID(gid GID) <-chan *Group {
- keys := []cacheKey{"gid", gid}
+ key := []fscache.CacheKey{"gid", gid}
ch := make(chan *Group, 1)
- ic := make(chan Cacheable, 1)
+ if gid < 1 {
+ ch <- nil
+ close(ch)
+ return ch
+ }
+
+ ic := make(chan notification, 1)
go func() { ch <- (<-ic).(*Group); close(ch) }()
- if intentMap.Intent(ic, keys...) {
+ if intentMap.Intent(ic, key...) {
return ch
}
- if !cache.CheckValid(keys...) {
- intentMap.Notify((*Group)(nil), keys...)
+ if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
+ intentMap.NotifyClose((*Group)(nil), key...)
return ch
}
g := gid.Group()
if !g.IsStale() {
- intentMap.Notify(g, keys...)
+ intentMap.NotifyClose(g, key...)
return ch
}
if reply.Error() == nil {
g = parseGroupReply(reply)
- cache.Set(&gidCache{GID: g.GID}, "gid", "by-name", g.Name)
- cache.Set(&gidCache{GID: g.GID}, "gid", "by-shortname", g.ShortName)
- cache.Set(g, keys...)
+ cacheGroup(g)
} else if reply.Code() == 350 {
- cache.MarkInvalid(keys...)
- cache.Delete(keys...) // deleted group?
+ Cache.SetInvalid(key...)
}
- intentMap.Notify(g, keys...)
+ intentMap.NotifyClose(g, key...)
}()
return ch
}
// Retrieves a Group by its name. Either full or short names are matched.
+// Uses the UDP API.
func (adb *AniDB) GroupByName(gname string) <-chan *Group {
- keys := []cacheKey{"gid", "by-name", gname}
- altKeys := []cacheKey{"gid", "by-shortname", gname}
+ key := []fscache.CacheKey{"gid", "by-name", gname}
+ altKey := []fscache.CacheKey{"gid", "by-shortname", gname}
ch := make(chan *Group, 1)
- ic := make(chan Cacheable, 1)
+ if gname == "" {
+ ch <- nil
+ close(ch)
+ return ch
+ }
+
+ ic := make(chan notification, 1)
go func() {
gid := (<-ic).(GID)
if gid > 0 {
}
close(ch)
}()
- if intentMap.Intent(ic, keys...) {
+ if intentMap.Intent(ic, key...) {
return ch
}
- if !cache.CheckValid(keys...) {
- intentMap.Notify(GID(0), keys...)
+ if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
+ intentMap.NotifyClose(GID(0), key...)
return ch
}
gid := GID(0)
- var gc gidCache
- if cache.Get(&gc, keys...) == nil && !gc.IsStale() {
- intentMap.Notify(gc.GID, keys...)
+ switch ts, err := Cache.Get(&gid, key...); {
+ case err == nil && time.Now().Sub(ts) < GroupCacheDuration:
+ intentMap.NotifyClose(gid, key...)
return ch
- }
- gid = gc.GID
-
- if gid == 0 {
- if cache.Get(&gc, altKeys...) == nil && !gc.IsStale() {
- intentMap.Notify(gc.GID, keys...)
+ default:
+ switch ts, err = Cache.Get(&gid, altKey...); {
+ case err == nil && time.Now().Sub(ts) < GroupCacheDuration:
+ intentMap.NotifyClose(gid, key...)
return ch
}
- gid = gc.GID
}
go func() {
gid = g.GID
- cache.Set(&gidCache{GID: gid}, keys...)
- cache.Set(&gidCache{GID: gid}, altKeys...)
- cache.Set(g, "gid", gid)
+ cacheGroup(g)
} else if reply.Code() == 350 {
- cache.MarkInvalid(keys...)
- cache.Delete(keys...) // renamed group?
- cache.Delete(altKeys...)
+ Cache.SetInvalid(key...)
+ Cache.SetInvalid(altKey...)
}
- intentMap.Notify(gid, keys...)
+ intentMap.NotifyClose(gid, key...)
}()
return ch
}