package object import ( "citrons.xyz/talk/proto" ) type ObjCache struct { stream ObjStream objects map[string]cacheEntry } type cacheEntry struct { o proto.Object refCount int cached bool } type ObjStream interface { Sub(id string) GetInfo(id string, callback func(*proto.Object)) Unsub(id string) } func NewCache(stream ObjStream) ObjCache { return ObjCache {stream, make(map[string]cacheEntry)} } func (oc *ObjCache) Get(id string) *proto.Object { entry := oc.objects[id] if !entry.cached { return nil } return &entry.o } func (oc *ObjCache) Fetch(id string, callback func(*proto.Object)) { entry := oc.objects[id] if !entry.cached { oc.stream.GetInfo(id, callback) } else { callback(&entry.o) } } func (oc *ObjCache) Watch(id string) { entry, ok := oc.objects[id] if !ok { oc.stream.Sub(id) } entry.refCount++ oc.objects[id] = entry } func (oc *ObjCache) Unwatch(id string) { entry, ok := oc.objects[id] if ok { entry.refCount-- if entry.refCount <= 0 { oc.stream.Unsub(id) delete(oc.objects, id) } else { oc.objects[id] = entry } } } func (oc *ObjCache) IsWatched(id string) bool { return oc.objects[id].refCount > 0 } func (oc *ObjCache) Update(id string, new proto.Object) { entry := oc.objects[id] if entry.cached && new.Kind == entry.o.Kind { for k, v := range new.Fields { entry.o.Fields[k] = v } } else { entry.o = new } entry.cached = true oc.objects[id] = entry } func (oc *ObjCache) Gone(id string) { entry := oc.objects[id] if entry.cached { obj := entry.o obj.Fields["kind"] = obj.Kind obj.Kind = "gone" entry.o = obj oc.objects[id] = entry } }