/
cache_index.go
executable file
·132 lines (116 loc) · 3.76 KB
/
cache_index.go
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package registry
import (
"github.com/go-chassis/go-chassis/v2/core/common"
"github.com/hashicorp/go-version"
"github.com/patrickmn/go-cache"
"k8s.io/apimachinery/pkg/util/sets"
"sync"
)
// IndexCache return instances by criteria
type IndexCache struct {
latestV map[string]string //save every service's latest version number
muxLatestV sync.RWMutex
simpleCache *cache.Cache //save service name and correspond instances
//key must contain service name, cache key includes label key values
indexedCache *cache.Cache
CriteriaStore []map[string]string //all criteria need to be saved in here so that we can update indexedCache, during Set process
}
// NewIndexCache create a cache which saves and manage instances
func NewIndexCache() *IndexCache {
return &IndexCache{
simpleCache: cache.New(DefaultExpireTime, 0),
latestV: map[string]string{},
indexedCache: cache.New(DefaultExpireTime, 0),
muxLatestV: sync.RWMutex{},
}
}
// FullCache return all instances
func (ic *IndexCache) FullCache() *cache.Cache { return ic.simpleCache }
// Delete remove one service's instances
func (ic *IndexCache) Delete(k string) {
ic.simpleCache.Delete(k)
ic.indexedCache.Delete(k)
}
// Set overwrite instances cache
func (ic *IndexCache) Set(k string, instances []*MicroServiceInstance) {
latestV, _ := version.NewVersion("0.0.0")
for _, instance := range instances {
//update latest version number
v, _ := version.NewVersion(instance.GetVersion())
if v != nil && latestV.LessThan(v) {
ic.muxLatestV.Lock()
ic.latestV[k] = instance.GetVersion()
ic.muxLatestV.Unlock()
latestV = v
}
}
////TODO update indexed cache
//ic.muxCriteria.RLock()
//for _, criteria := range ic.CriteriaStore {
// indexKey := ic.GetIndexedCacheKey(k, criteria)
// result := make([]*MicroServiceInstance, 0)
// for _, instance := range instances {
// if instance.Has(criteria) {
// result = append(result, instance)
// }
// }
// //forcely overwrite indexed cache, that is safe
// ic.indexedCache.Set(indexKey, result, 0)
//}
//ic.muxCriteria.RUnlock()
ic.simpleCache.Set(k, instances, 0)
}
// Get return instances cache by criteria
func (ic *IndexCache) Get(k string, tags map[string]string) ([]*MicroServiceInstance, bool) {
value, ok := ic.simpleCache.Get(k)
if !ok {
return nil, false
}
if len(tags) == 0 {
return value.([]*MicroServiceInstance), ok
}
//if version is latest, then set it to real version
ic.setTagsBeforeQuery(k, tags)
//find from indexed cache first
indexKey := GetIndexedCacheKey(k, tags)
savedResult, ok := ic.indexedCache.Get(indexKey)
if !ok {
//no result, then find it and save result
instances, _ := value.([]*MicroServiceInstance)
queryResult := make([]*MicroServiceInstance, 0, len(instances))
for _, instance := range instances {
if instance.Has(tags) {
queryResult = append(queryResult, instance)
}
}
if len(queryResult) == 0 {
return nil, false
}
//ic.indexedCache.Set(indexKey, queryResult, 0)
//ic.muxCriteria.Lock()
//ic.CriteriaStore = append(ic.CriteriaStore, tags)
//ic.muxCriteria.Unlock()
return queryResult, true
}
return savedResult.([]*MicroServiceInstance), ok
}
func (ic *IndexCache) setTagsBeforeQuery(k string, tags map[string]string) {
ic.muxLatestV.RLock()
//must set version before query
if v, ok := tags[common.BuildinTagVersion]; ok && v == common.LatestVersion && ic.latestV[k] != "" {
tags[common.BuildinTagVersion] = ic.latestV[k]
}
ic.muxLatestV.RUnlock()
}
// GetIndexedCacheKey combine keys in order, use sets to return sorted list
func GetIndexedCacheKey(service string, tags map[string]string) (ss string) {
ss = "service:" + service
keys := sets.NewString()
for k := range tags {
keys.Insert(k)
}
for _, k := range keys.List() {
ss += "|" + k + ":" + tags[k]
}
return
}