forked from juju/juju
/
cache.go
97 lines (85 loc) · 2.97 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
89
90
91
92
93
94
95
96
97
// Copyright 2012-2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package context
import (
"sort"
"github.com/juju/juju/apiserver/params"
)
// SettingsFunc returns the relation settings for a unit.
type SettingsFunc func(unitName string) (params.Settings, error)
// SettingsMap is a map from unit name to relation settings.
type SettingsMap map[string]params.Settings
// RelationCache stores a relation's remote unit membership and settings.
// Member settings are stored until invalidated or removed by name; settings
// of non-member units are stored only until the cache is pruned.
type RelationCache struct {
// readSettings is used to get settings data if when not already present.
readSettings SettingsFunc
// members' keys define the relation's membership; non-nil values hold
// cached settings.
members SettingsMap
// others is a short-term cache for non-member settings.
others SettingsMap
}
// NewRelationCache creates a new RelationCache that will use the supplied
// SettingsFunc to populate itself on demand. Initial membership is determined
// by memberNames.
func NewRelationCache(readSettings SettingsFunc, memberNames []string) *RelationCache {
cache := &RelationCache{
readSettings: readSettings,
}
cache.Prune(memberNames)
return cache
}
// Prune resets the membership to the supplied list, and discards the settings
// of all non-member units.
func (cache *RelationCache) Prune(memberNames []string) {
newMembers := SettingsMap{}
for _, memberName := range memberNames {
newMembers[memberName] = cache.members[memberName]
}
cache.members = newMembers
cache.others = SettingsMap{}
}
// MemberNames returns the names of the remote units present in the relation.
func (cache *RelationCache) MemberNames() (memberNames []string) {
for memberName := range cache.members {
memberNames = append(memberNames, memberName)
}
sort.Strings(memberNames)
return memberNames
}
// Settings returns the settings of the named remote unit. It's valid to get
// the settings of any unit that has ever been in the relation.
func (cache *RelationCache) Settings(unitName string) (params.Settings, error) {
settings, isMember := cache.members[unitName]
if settings == nil {
if !isMember {
settings = cache.others[unitName]
}
if settings == nil {
var err error
settings, err = cache.readSettings(unitName)
if err != nil {
return nil, err
}
}
}
if isMember {
cache.members[unitName] = settings
} else {
cache.others[unitName] = settings
}
return settings, nil
}
// InvalidateMember ensures that the named remote unit will be considered a
// member of the relation, and that the next attempt to read its settings will
// use fresh data.
func (cache *RelationCache) InvalidateMember(memberName string) {
cache.members[memberName] = nil
}
// RemoveMember ensures that the named remote unit will not be considered a
// member of the relation,
func (cache *RelationCache) RemoveMember(memberName string) {
delete(cache.members, memberName)
}