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

Side by Side Diff: service/memcache/interface.go

Issue 2302743002: Interface update, per-method Contexts. (Closed)
Patch Set: Created 4 years, 3 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
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 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 memcache 5 package memcache
6 6
7 // Interface is the full interface to the memcache service. 7 import (
8 » "github.com/luci/luci-go/common/errors"
9 » "golang.org/x/net/context"
10 )
11
12 func filterItems(lme errors.LazyMultiError, items []Item, nilErr error) ([]Item, []int) {
13 » idxMap := make([]int, 0, len(items))
14 » retItems := make([]Item, 0, len(items))
15 » for i, itm := range items {
16 » » if itm != nil {
17 » » » idxMap = append(idxMap, i)
18 » » » retItems = append(retItems, itm)
19 » » } else {
20 » » » lme.Assign(i, nilErr)
21 » » }
22 » }
23 » return retItems, idxMap
24 }
25
26 func multiCall(items []Item, nilErr error, inner func(items []Item, cb RawCB) er ror) error {
27 » lme := errors.NewLazyMultiError(len(items))
28 » realItems, idxMap := filterItems(lme, items, nilErr)
29 » j := 0
30 » err := inner(realItems, func(err error) {
31 » » lme.Assign(idxMap[j], err)
32 » » j++
33 » })
34 » if err == nil {
35 » » err = lme.Get()
36 » » if len(items) == 1 {
37 » » » err = errors.SingleError(err)
38 » » }
39 » }
40 » return err
41 }
42
43 // NewItem creates a new, mutable, memcache item.
44 func NewItem(c context.Context, key string) Item {
45 » return Raw(c).NewItem(key)
46 }
47
48 // Add writes items to memcache iff they don't already exist.
8 // 49 //
9 // The *Multi methods may return a "github.com/luci/luci-go/common/errors".Multi Error 50 // If only one item is provided its error will be returned directly. If more
10 // if the rpc to the server was successful, but, e.g. some of the items were 51 // than one item is provided, an errors.MultiError will be returned in the
11 // missing. They may also return a regular error, if, for example, the rpc 52 // event of an error, with a given error index corresponding to the error
12 // failed outright. 53 // encountered when processing the item at that index.
13 type Interface interface { 54 func Add(c context.Context, items ...Item) error {
dnj 2016/09/01 15:25:40 Big change here is that I axed this Interface and
14 » // NewItem creates a new, mutable, memcache item. 55 » return multiCall(items, ErrNotStored, Raw(c).AddMulti)
15 » NewItem(key string) Item 56 }
16 57
17 » // Add puts a single item into memcache, but only if it didn't exist in 58 // Set writes items into memcache unconditionally.
18 » // memcache before. 59 //
19 » Add(item Item) error 60 // If only one item is provided its error will be returned directly. If more
61 // than one item is provided, an errors.MultiError will be returned in the
62 // event of an error, with a given error index corresponding to the error
63 // encountered when processing the item at that index.
64 func Set(c context.Context, items ...Item) error {
65 » return multiCall(items, ErrNotStored, Raw(c).SetMulti)
66 }
20 67
21 » // Set the item in memcache, whether or not it exists. 68 func getMultiImpl(raw RawInterface, items []Item) error {
22 » Set(item Item) error 69 » lme := errors.NewLazyMultiError(len(items))
70 » realItems, idxMap := filterItems(lme, items, ErrCacheMiss)
71 » if len(realItems) == 0 {
72 » » return lme.Get()
73 » }
23 74
24 » // Get retrieves an item from memcache. 75 » keys := make([]string, len(realItems))
25 » // 76 » for i, itm := range realItems {
26 » // On a cache miss ErrCacheMiss will be returned. Item will always be 77 » » keys[i] = itm.Key()
27 » // returned, even on a miss, but it's value may be empty if it was a mis s. 78 » }
28 » Get(key string) (Item, error)
29 79
30 » // Delete removes an item from memcache. 80 » j := 0
31 » Delete(key string) error 81 » err := raw.GetMulti(keys, func(item Item, err error) {
82 » » i := idxMap[j]
83 » » if !lme.Assign(i, err) {
84 » » » items[i].SetAll(item)
85 » » }
86 » » j++
87 » })
88 » if err == nil {
89 » » err = lme.Get()
90 » » if len(items) == 1 {
dnj 2016/09/01 15:25:40 (This is the "single argument, single error" logic
91 » » » err = errors.SingleError(err)
92 » » }
93 » }
94 » return err
95 }
32 96
33 » // CompareAndSwap accepts an item which is the result of Get() or GetMul ti(). 97 // Get retrieves items from memcache.
34 » // The Get functions add a secret field to item ('CasID'), which is used as 98 func Get(c context.Context, items ...Item) error {
35 » // the "compare" value for the "CompareAndSwap". The actual "Value" fiel d of 99 » return getMultiImpl(Raw(c), items)
36 » // the object set by the Get functions is the "swap" value. 100 }
37 » //
38 » // Example:
39 » // mc := memcache.Get(context)
40 » // itm := mc.NewItem("aKey")
41 » // mc.Get(itm) // check error
42 » // itm.SetValue(append(itm.Value(), []byte("more bytes")))
43 » // mc.CompareAndSwap(itm) // check error
44 » CompareAndSwap(item Item) error
45 101
46 » // Batch operations; GetMulti takes a []Item instead of []string to impr ove 102 // GetKey is a convenience method for generating and retrieving an Item instance
47 » // ergonomics when streamlining these operations. 103 // for the specified from memcache key.
48 » AddMulti(items []Item) error 104 //
49 » SetMulti(items []Item) error 105 // On a cache miss ErrCacheMiss will be returned. Item will always be
50 » GetMulti(items []Item) error 106 // returned, even on a miss, but it's value may be empty if it was a miss.
51 » DeleteMulti(keys []string) error 107 func GetKey(c context.Context, key string) (Item, error) {
52 » CompareAndSwapMulti(items []Item) error 108 » raw := Raw(c)
109 » ret := raw.NewItem(key)
110 » err := getMultiImpl(raw, []Item{ret})
111 » return ret, err
112 }
53 113
54 » // Increment adds delta to the uint64 contained at key. If the memcache key 114 // Delete deletes items from memcache.
55 » // is missing, it's populated with initialValue before applying delta (i .e. 115 //
56 » // the final value would be initialValue+delta). 116 // If only one item is provided its error will be returned directly. If more
57 » // 117 // than one item is provided, an errors.MultiError will be returned in the
58 » // Underflow caps at 0, overflow wraps back to 0. 118 // event of an error, with a given error index corresponding to the error
59 » // 119 // encountered when processing the item at that index.
60 » // If key contains a value which is not exactly 8 bytes, it's assumed to 120 func Delete(c context.Context, keys ...string) error {
61 » // contain non-number data and this method will return an error. 121 » lme := errors.NewLazyMultiError(len(keys))
62 » Increment(key string, delta int64, initialValue uint64) (newValue uint64 , err error) 122 » i := 0
123 » err := Raw(c).DeleteMulti(keys, func(err error) {
124 » » lme.Assign(i, err)
125 » » i++
126 » })
127 » if err == nil {
128 » » err = lme.Get()
129 » » if len(keys) == 1 {
130 » » » err = errors.SingleError(err)
131 » » }
132 » }
133 » return err
134 }
63 135
64 » // IncrementExisting is like Increment, except that the valu must exist 136 // CompareAndSwap writes the given item that was previously returned by Get, if
65 » // already. 137 // the value was neither modified or evicted between the Get and the
66 » IncrementExisting(key string, delta int64) (newValue uint64, err error) 138 // CompareAndSwap calls.
139 //
140 // Example:
141 // itm := memcache.NewItem(context, "aKey")
142 // memcache.Get(context, itm) // check error
143 // itm.SetValue(append(itm.Value(), []byte("more bytes")))
144 // memcache.CompareAndSwap(context, itm) // check error
145 //
146 // If only one item is provided its error will be returned directly. If more
147 // than one item is provided, an errors.MultiError will be returned in the
148 // event of an error, with a given error index corresponding to the error
149 // encountered when processing the item at that index.
150 func CompareAndSwap(c context.Context, items ...Item) error {
151 » return multiCall(items, ErrNotStored, Raw(c).CompareAndSwapMulti)
152 }
67 153
68 » // Flush dumps the entire memcache state. 154 // Increment adds delta to the uint64 contained at key. If the memcache key
69 » Flush() error 155 // is missing, it's populated with initialValue before applying delta (i.e.
156 // the final value would be initialValue+delta).
157 //
158 // Underflow caps at 0, overflow wraps back to 0.
159 //
160 // If key contains a value which is not exactly 8 bytes, it's assumed to
161 // contain non-number data and this method will return an error.
162 func Increment(c context.Context, key string, delta int64, initialValue uint64) (uint64, error) {
163 » return Raw(c).Increment(key, delta, &initialValue)
164 }
70 165
71 » // Stats gets some best-effort statistics about the current state of mem cache. 166 // IncrementExisting is like Increment, except that the valu must exist
72 » Stats() (*Statistics, error) 167 // already.
168 func IncrementExisting(c context.Context, key string, delta int64) (uint64, erro r) {
169 » return Raw(c).Increment(key, delta, nil)
170 }
73 171
74 » Raw() RawInterface 172 // Flush dumps the entire memcache state.
173 func Flush(c context.Context) error {
174 » return Raw(c).Flush()
75 } 175 }
176
177 // Stats gets some best-effort statistics about the current state of memcache.
178 func Stats(c context.Context) (*Statistics, error) {
179 return Raw(c).Stats()
180 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698