-
Notifications
You must be signed in to change notification settings - Fork 5
/
cache.go
88 lines (70 loc) · 1.85 KB
/
cache.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
package cachecluster
import (
"fmt"
"net"
"sort"
"strings"
"time"
"runtime/debug"
"github.com/golang/groupcache"
)
type (
cache struct {
*groupcache.HTTPPool
me net.IP
prev string
config *CacheConfig
}
)
// New creates a new auto-clusered cache instance
func New(config *Config) (*cache, error) {
cluster, err := newCluster(config)
if err != nil {
logger.Debugf("error creating cluster %v", err)
return nil, err
}
self := fmt.Sprintf("http://%s:%d", cluster.me, config.Cache.Port)
logger.Debugf("groupcache on %s", self)
pool := groupcache.NewHTTPPoolOpts(self, nil)
cache := &cache{
HTTPPool: pool,
me: cluster.me,
config: &config.Cache,
}
if config.Cache.GCPercent > 0 {
debug.SetGCPercent(config.Cache.GCPercent)
}
if config.Cache.PeriodicRelease > 0 {
go periodMemoryRelease(config.Cache.PeriodicRelease)
}
// start a separate goroutine because a) this blocks and b) we want
// to return as soon as possible so whatever service is running on
// this instance can actually start without needing to wait for the
// clustering to happen
go cluster.listenForUpdates(self, cache.updatePeers)
return cache, nil
}
// Periodic release of unused memory back to the OS.
func periodMemoryRelease(interval int) {
ticker := time.Tick(time.Duration(interval) * time.Second)
for range ticker {
debug.FreeOSMemory()
}
}
func (c *cache) updatePeers(addresses []net.IP) {
peers := make([]string, len(addresses))
for i, addr := range addresses {
peers[i] = fmt.Sprintf("http://%s:%d", addr, c.config.Port)
}
sort.Slice(peers, func(i, j int) bool { return peers[i] < peers[j] })
list := strings.Join(peers, ", ")
if list == c.prev {
return
}
logger.Debugf("%s set peers %s", c.me, list)
c.Set(peers...)
c.prev = list
}
func (c *cache) ListenOn() string {
return fmt.Sprintf("0.0.0.0:%d", c.config.Port)
}