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
package binding
import (
"maps"
"slices"
"strings"
"sync"
)
type Target struct {
Cluster string
Workspace string
Name string
}
type Table[B any] struct {
mu sync.RWMutex
items map[string]B
users map[string]map[string]Target
}
func New[B any]() *Table[B] {
return &Table[B]{items: map[string]B{}, users: map[string]map[string]Target{}}
}
func Key(workspace string, parts ...string) string {
out := strings.TrimSpace(workspace)
for _, part := range parts {
out += "/" + strings.ToLower(strings.TrimSpace(part))
}
return out
}
func (t *Table[B]) Set(target Target, value *B, refs ...string) {
t.mu.Lock()
defer t.mu.Unlock()
k := Key(target.Workspace, target.Name)
if value == nil {
delete(t.items, k)
} else {
t.items[k] = *value
}
for ref, set := range t.users {
if !slices.Contains(refs, ref) {
delete(set, k)
if len(set) == 0 {
delete(t.users, ref)
}
}
}
for _, ref := range refs {
if ref == "" {
continue
}
set := t.users[ref]
if set == nil {
set = map[string]Target{}
t.users[ref] = set
}
set[k] = target
}
}
func (t *Table[B]) Get(workspace, name string) (B, bool) {
t.mu.RLock()
defer t.mu.RUnlock()
value, ok := t.items[Key(workspace, name)]
return value, ok
}
func (t *Table[B]) Users(ref string) []Target {
t.mu.RLock()
defer t.mu.RUnlock()
return slices.Collect(maps.Values(t.users[ref]))
}