summaryrefslogtreecommitdiff
path: root/client/object/object.go
blob: a3404ccd9bc0f0ae7d5c70dfe05766977cb5203f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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.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
	}
}