-
Notifications
You must be signed in to change notification settings - Fork 17
/
cached_directory.go
54 lines (45 loc) · 1.44 KB
/
cached_directory.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
package directoryrolebinding
import (
"context"
"fmt"
"time"
"github.com/go-logr/logr"
)
// NewCachedDirectory wraps the given directory so that we cache member lists for the
// given TTL. This is useful when we want to reason about the maximum number of calls to a
// directory API our controllers might make, which helps us avoid API rate limits.
func NewCachedDirectory(logger logr.Logger, directory Directory, ttl time.Duration) *cachedDirectory {
return &cachedDirectory{
logger: logger,
directory: directory,
ttl: ttl,
cache: map[string]cacheEntry{},
now: time.Now,
}
}
type cachedDirectory struct {
logger logr.Logger
directory Directory
ttl time.Duration
cache map[string]cacheEntry
now func() time.Time
}
type cacheEntry struct {
members []string
cachedAt time.Time
}
func (d *cachedDirectory) MembersOf(ctx context.Context, group string) (members []string, err error) {
if entry, ok := d.cache[group]; ok {
if d.now().Sub(entry.cachedAt) < d.ttl { // within ttl
return entry.members, nil
}
d.logger.Info(fmt.Sprintf("Cache expired for group %s", group), "event", "cache.expire", "group", group)
delete(d.cache, group) // expired
}
members, err = d.directory.MembersOf(ctx, group)
if err == nil {
d.logger.Info(fmt.Sprintf("Cache added for group %s", group), "event", "cache.add", "group", group)
d.cache[group] = cacheEntry{members: members, cachedAt: d.now()}
}
return
}