Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: appengine/gaeconfig/cache.go

Issue 2575383002: Add server/cache support to gaeconfig. (Closed)
Patch Set: Un-collapse. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | appengine/gaeconfig/cache_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package gaeconfig
6
7 import (
8 "bytes"
9 "encoding/binary"
10 "fmt"
11 "time"
12
13 ds "github.com/luci/gae/service/datastore"
14 mc "github.com/luci/gae/service/memcache"
15 "github.com/luci/luci-go/common/clock"
16 "github.com/luci/luci-go/common/config"
17 "github.com/luci/luci-go/common/config/filters/caching"
18 "github.com/luci/luci-go/common/data/caching/proccache"
19 log "github.com/luci/luci-go/common/logging"
20
21 "golang.org/x/net/context"
22 )
23
24 // WrapWithCache wraps config client with proccache-and-memcache-caching layer.
25 func WrapWithCache(cfg config.Interface, expire time.Duration) config.Interface {
26 return caching.Wrap(cfg, caching.Options{
27 Cache: &cache{},
28 Expiration: expire,
29 })
30 }
31
32 type cache struct{}
33
34 type proccacheKey string
35
36 func (c *cache) Store(ctx context.Context, baseKey string, expire time.Duration, value []byte) {
37 k := cacheKey(baseKey)
38
39 proccache.Put(ctx, k, value, expire)
40
41 // value in memcache is [varint(expiration_ts.Millis) ++ value]
42 // value in proccache is [value]
43 //
44 // This is because memcache doesn't populate the .Expiration field of th e
45 // memcache Item on Get operations :(
46 stamp := ds.TimeToInt(clock.Now(ctx).UTC().Add(expire))
47 buf := make([]byte, binary.MaxVarintLen64)
48 value = append(buf[:binary.PutVarint(buf, stamp)], value...)
49
50 itm := mc.NewItem(ctx, string(k)).SetExpiration(expire).SetValue(value)
51 if err := mc.Set(ctx, itm); err != nil {
52 log.Fields{
53 log.ErrorKey: err,
54 "key": baseKey,
55 "expire": expire,
56 }.Warningf(ctx, "Failed to store cache value.")
57 }
58 }
59
60 func (c *cache) Retrieve(ctx context.Context, baseKey string) []byte {
61 k := cacheKey(baseKey)
62 ret, err := proccache.GetOrMake(ctx, k, func() (value interface{}, exp t ime.Duration, err error) {
63 item, err := mc.GetKey(ctx, string(k))
64 if err != nil {
65 if err != mc.ErrCacheMiss {
66 log.Fields{
67 log.ErrorKey: err,
68 "key": baseKey,
69 }.Warningf(ctx, "Failed to retrieve memcache val ue.")
70 }
71 return
72 }
73
74 buf := bytes.NewBuffer(item.Value())
75 expStamp, err := binary.ReadVarint(buf)
76 if err != nil {
77 log.Fields{
78 log.ErrorKey: err,
79 "key": baseKey,
80 }.Warningf(ctx, "Failed to decode stamp in memcache valu e.")
81 return
82 }
83
84 // proccache will ignore this value if exp is in the past
85 exp = ds.IntToTime(expStamp).Sub(clock.Now(ctx))
86 value = buf.Bytes()
87 return
88 })
89 if err != nil {
90 return nil
91 }
92 return ret.([]byte)
93 }
94
95 func cacheKey(baseKey string) proccacheKey {
96 return proccacheKey(fmt.Sprintf("luci-config:v2:%s", baseKey))
97 }
OLDNEW
« no previous file with comments | « no previous file | appengine/gaeconfig/cache_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698