1package libkb
2
3import (
4	"fmt"
5	"time"
6
7	"github.com/keybase/client/go/protocol/keybase1"
8
9	"stathat.com/c/ramcache"
10)
11
12// UserCardCache caches keybase1.UserCard objects in memory.
13type UserCardCache struct {
14	cache *ramcache.Ramcache
15}
16
17// NewUserCardCache creates a UserCardCache.  keybase1.UserCards will expire
18// after maxAge.
19func NewUserCardCache(maxAge time.Duration) *UserCardCache {
20	c := &UserCardCache{
21		cache: ramcache.New(),
22	}
23	c.cache.MaxAge = maxAge
24	c.cache.TTL = maxAge
25	return c
26}
27
28// Get looks for a keybase1.UserCard for uid.  It returns nil, nil if not found.
29// useSession is set if the card is being looked up with a session.
30func (c *UserCardCache) Get(uid keybase1.UID, useSession bool) (*keybase1.UserCard, error) {
31	v, err := c.cache.Get(c.key(uid, useSession))
32	if err != nil {
33		if err == ramcache.ErrNotFound {
34			return nil, nil
35		}
36		return nil, err
37	}
38	card, ok := v.(keybase1.UserCard)
39	if !ok {
40		return nil, fmt.Errorf("invalid type in cache: %T", v)
41	}
42	return &card, nil
43}
44
45// Set stores card in the UserCardCache.  usedSession is set based on
46// whether user/card was looked up with a session or not.
47func (c *UserCardCache) Set(card *keybase1.UserCard, usedSession bool) error {
48	return c.cache.Set(c.key(card.Uid, usedSession), *card)
49}
50
51// Shutdown stops any goroutines in the cache.
52func (c *UserCardCache) Shutdown() {
53	c.cache.Shutdown()
54}
55
56func (c *UserCardCache) key(uid keybase1.UID, session bool) string {
57	suffix := "0"
58	if session {
59		suffix = "1"
60	}
61	return uid.String() + ":" + suffix
62}
63
64func (c *UserCardCache) Delete(uid keybase1.UID) error {
65	return c.cache.Delete(c.key(uid, true))
66}
67