diff options
Diffstat (limited to 'client/object')
| -rw-r--r-- | client/object/object.go | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/client/object/object.go b/client/object/object.go new file mode 100644 index 0000000..f42eaf8 --- /dev/null +++ b/client/object/object.go @@ -0,0 +1,95 @@ +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.Command)) + 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, func(cmd proto.Command) { + if cmd.Kind == "i" && len(cmd.Args) > 0 { + callback(&cmd.Args[0]) + } else { + callback(nil) + } + }) + } + callback(&entry.o) +} + +func (oc *ObjCache) Watch(id string) { + entry, ok := oc.objects[id] + if !ok { + oc.stream.Sub(id) + } + 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) 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 + } +} + + |
