OLD | NEW |
1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package server | 5 package server |
6 | 6 |
7 import ( | 7 import ( |
8 "time" | 8 "time" |
9 | 9 |
10 "golang.org/x/net/context" | 10 "golang.org/x/net/context" |
11 | 11 |
12 "github.com/luci/gae/service/info" | 12 "github.com/luci/gae/service/info" |
13 mc "github.com/luci/gae/service/memcache" | 13 mc "github.com/luci/gae/service/memcache" |
14 | 14 |
15 "github.com/luci/luci-go/common/clock" | 15 "github.com/luci/luci-go/common/clock" |
16 "github.com/luci/luci-go/common/data/caching/proccache" | 16 "github.com/luci/luci-go/common/data/caching/proccache" |
17 » "github.com/luci/luci-go/common/errors" | 17 » "github.com/luci/luci-go/common/retry" |
18 "github.com/luci/luci-go/common/sync/mutexpool" | 18 "github.com/luci/luci-go/common/sync/mutexpool" |
19 "github.com/luci/luci-go/server/auth" | 19 "github.com/luci/luci-go/server/auth" |
20 ) | 20 ) |
21 | 21 |
22 // Memcache implements auth.Cache on top of GAE memcache and per-request state. | 22 // Memcache implements auth.Cache on top of GAE memcache and per-request state. |
23 type Memcache struct { | 23 type Memcache struct { |
24 Namespace string | 24 Namespace string |
25 | 25 |
26 locks mutexpool.P | 26 locks mutexpool.P |
27 } | 27 } |
28 | 28 |
29 var _ auth.Cache = (*Memcache)(nil) | 29 var _ auth.Cache = (*Memcache)(nil) |
30 | 30 |
31 // Get returns a cached item or (nil, nil) if it's not in the cache. | 31 // Get returns a cached item or (nil, nil) if it's not in the cache. |
32 // | 32 // |
33 // Assumes callers do not modify the returned array in-place. Any returned error | 33 // Assumes callers do not modify the returned array in-place. Any returned error |
34 // is transient error. | 34 // is transient error. |
35 func (m *Memcache) Get(c context.Context, key string) ([]byte, error) { | 35 func (m *Memcache) Get(c context.Context, key string) ([]byte, error) { |
36 if val := m.getLocal(c, key); val != nil { | 36 if val := m.getLocal(c, key); val != nil { |
37 return val, nil | 37 return val, nil |
38 } | 38 } |
39 switch itm, err := mc.GetKey(m.cacheContext(c), key); { | 39 switch itm, err := mc.GetKey(m.cacheContext(c), key); { |
40 case err == mc.ErrCacheMiss: | 40 case err == mc.ErrCacheMiss: |
41 return nil, nil | 41 return nil, nil |
42 case err != nil: | 42 case err != nil: |
43 » » return nil, errors.WrapTransient(err) | 43 » » return nil, retry.Tag.Apply(err) |
44 default: | 44 default: |
45 m.setLocal(c, key, itm.Value(), itm.Expiration()) | 45 m.setLocal(c, key, itm.Value(), itm.Expiration()) |
46 return itm.Value(), nil | 46 return itm.Value(), nil |
47 } | 47 } |
48 } | 48 } |
49 | 49 |
50 // Set unconditionally overwrites an item in the cache. | 50 // Set unconditionally overwrites an item in the cache. |
51 // | 51 // |
52 // If 'exp' is zero, the item will have no expiration time. | 52 // If 'exp' is zero, the item will have no expiration time. |
53 // | 53 // |
54 // Any returned error is transient error. | 54 // Any returned error is transient error. |
55 func (m *Memcache) Set(c context.Context, key string, value []byte, exp time.Dur
ation) error { | 55 func (m *Memcache) Set(c context.Context, key string, value []byte, exp time.Dur
ation) error { |
56 m.setLocal(c, key, value, exp) | 56 m.setLocal(c, key, value, exp) |
57 cc := m.cacheContext(c) | 57 cc := m.cacheContext(c) |
58 item := mc.NewItem(cc, key).SetValue(value).SetExpiration(exp) | 58 item := mc.NewItem(cc, key).SetValue(value).SetExpiration(exp) |
59 if err := mc.Set(cc, item); err != nil { | 59 if err := mc.Set(cc, item); err != nil { |
60 » » return errors.WrapTransient(err) | 60 » » return retry.Tag.Apply(err) |
61 } | 61 } |
62 return nil | 62 return nil |
63 } | 63 } |
64 | 64 |
65 // WithLocalMutex calls 'f' under local mutex. | 65 // WithLocalMutex calls 'f' under local mutex. |
66 func (mc *Memcache) WithLocalMutex(c context.Context, key string, f func()) { | 66 func (m *Memcache) WithLocalMutex(c context.Context, key string, f func()) { |
67 » mc.locks.WithMutex(key, f) | 67 » m.locks.WithMutex(key, f) |
68 } | 68 } |
69 | 69 |
70 // cacheContext returns properly namespaced luci/gae context. | 70 // cacheContext returns properly namespaced luci/gae context. |
71 func (m *Memcache) cacheContext(c context.Context) context.Context { | 71 func (m *Memcache) cacheContext(c context.Context) context.Context { |
72 return info.MustNamespace(c, m.Namespace) | 72 return info.MustNamespace(c, m.Namespace) |
73 } | 73 } |
74 | 74 |
75 type requestCacheCtxKey *Memcache | 75 type requestCacheCtxKey *Memcache |
76 | 76 |
77 // UseRequestCache initializes context-bound local cache. | 77 // UseRequestCache initializes context-bound local cache. |
(...skipping 27 matching lines...) Expand all Loading... |
105 // setLocal puts a copy of 'val' in the context-bound cache. | 105 // setLocal puts a copy of 'val' in the context-bound cache. |
106 func (m *Memcache) setLocal(c context.Context, key string, val []byte, exp time.
Duration) { | 106 func (m *Memcache) setLocal(c context.Context, key string, val []byte, exp time.
Duration) { |
107 if pc := m.requestCache(c); pc != nil { | 107 if pc := m.requestCache(c); pc != nil { |
108 expTs := time.Time{} | 108 expTs := time.Time{} |
109 if exp != 0 { | 109 if exp != 0 { |
110 expTs = clock.Now(c).Add(exp) | 110 expTs = clock.Now(c).Add(exp) |
111 } | 111 } |
112 pc.Put(key, append([]byte(nil), val...), expTs) | 112 pc.Put(key, append([]byte(nil), val...), expTs) |
113 } | 113 } |
114 } | 114 } |
OLD | NEW |