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

Side by Side Diff: service/datastore/datastore.go

Issue 1355783002: Refactor keys and queries in datastore service and implementation. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: appease errcheck Created 5 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
« no previous file with comments | « service/datastore/context_test.go ('k') | service/datastore/datastore_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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package datastore 5 package datastore
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "reflect" 9 "reflect"
10 10
11 "github.com/luci/luci-go/common/errors" 11 "github.com/luci/luci-go/common/errors"
12 ) 12 )
13 13
14 type datastoreImpl struct{ RawInterface } 14 type datastoreImpl struct {
15 » RawInterface
16
17 » aid string
18 » ns string
19 }
15 20
16 var _ Interface = (*datastoreImpl)(nil) 21 var _ Interface = (*datastoreImpl)(nil)
17 22
18 func (d *datastoreImpl) KeyForObj(src interface{}) Key { 23 func (d *datastoreImpl) KeyForObj(src interface{}) *Key {
19 ret, err := d.KeyForObjErr(src) 24 ret, err := d.KeyForObjErr(src)
20 if err != nil { 25 if err != nil {
21 panic(err) 26 panic(err)
22 } 27 }
23 return ret 28 return ret
24 } 29 }
25 30
26 func (d *datastoreImpl) KeyForObjErr(src interface{}) (Key, error) { 31 func (d *datastoreImpl) KeyForObjErr(src interface{}) (*Key, error) {
27 » return newKeyObjErr(d.NewKey, src) 32 » return newKeyObjErr(d.aid, d.ns, src)
28 } 33 }
29 34
30 func (d *datastoreImpl) DecodeCursor(s string) (Cursor, error) { 35 func (d *datastoreImpl) MakeKey(elems ...interface{}) *Key {
31 » return d.RawInterface.DecodeCursor(s) 36 » return MakeKey(d.aid, d.ns, elems...)
32 } 37 }
33 38
34 func (d *datastoreImpl) Run(q Query, cbIface interface{}) error { 39 func (d *datastoreImpl) NewKey(kind, stringID string, intID int64, parent *Key) *Key {
40 » return NewKey(d.aid, d.ns, kind, stringID, intID, parent)
41 }
42
43 func (d *datastoreImpl) NewKeyToks(toks []KeyTok) *Key {
44 » return NewKeyToks(d.aid, d.ns, toks)
45 }
46
47 func (d *datastoreImpl) Run(q *Query, cbIface interface{}) error {
35 if cbIface == nil { 48 if cbIface == nil {
36 return fmt.Errorf("cannot use nil callback when Running query") 49 return fmt.Errorf("cannot use nil callback when Running query")
37 } 50 }
38 51
39 // TODO(riannucci): Profile and determine if any of this is causing a re al 52 // TODO(riannucci): Profile and determine if any of this is causing a re al
40 » // slowdown. Could potentially cache reflection stuff by cbType? 53 » // slowdown. Could potentially cache reflection stuff by cbTyp?
41 cbTyp := reflect.TypeOf(cbIface) 54 cbTyp := reflect.TypeOf(cbIface)
42 55
43 badSig := false 56 badSig := false
44 mat := multiArgType{} 57 mat := multiArgType{}
45 isKey := false 58 isKey := false
46 59
47 if cbTyp.Kind() == reflect.Func && cbTyp.NumIn() == 2 && cbTyp.NumOut() == 1 { 60 if cbTyp.Kind() == reflect.Func && cbTyp.NumIn() == 2 && cbTyp.NumOut() == 1 {
48 firstArg := cbTyp.In(0) 61 firstArg := cbTyp.In(0)
49 if firstArg == typeOfKey { 62 if firstArg == typeOfKey {
50 isKey = true 63 isKey = true
51 } else { 64 } else {
52 mat = parseArg(firstArg) 65 mat = parseArg(firstArg)
53 badSig = !mat.valid || mat.newElem == nil 66 badSig = !mat.valid || mat.newElem == nil
54 } 67 }
55 } else { 68 } else {
56 badSig = true 69 badSig = true
57 } 70 }
58 71
59 if badSig || cbTyp.Out(0) != typeOfBool || cbTyp.In(1) != typeOfCursorCB { 72 if badSig || cbTyp.Out(0) != typeOfBool || cbTyp.In(1) != typeOfCursorCB {
60 panic(fmt.Errorf( 73 panic(fmt.Errorf(
61 "cb does not match the required callback signature: `%T` != `func(TYPE, CursorCB) bool`", 74 "cb does not match the required callback signature: `%T` != `func(TYPE, CursorCB) bool`",
62 cbIface)) 75 cbIface))
63 } 76 }
64 77
65 if isKey { 78 if isKey {
66 » » cb := cbIface.(func(Key, CursorCB) bool) 79 » » cb := cbIface.(func(*Key, CursorCB) bool)
67 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, gc CursorCB) bool { 80 » » fq, err := q.KeysOnly(true).Finalize()
81 » » if err != nil {
82 » » » return err
83 » » }
84 » » return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, gc Cur sorCB) bool {
68 return cb(k, gc) 85 return cb(k, gc)
69 }) 86 })
70 } 87 }
71 88
89 fq, err := q.Finalize()
90 if err != nil {
91 return err
92 }
93
72 cbVal := reflect.ValueOf(cbIface) 94 cbVal := reflect.ValueOf(cbIface)
73 95
74 innerErr := error(nil) 96 innerErr := error(nil)
75 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc CursorCB) bo ol { 97 » err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, gc CursorCB) b ool {
76 itm := mat.newElem() 98 itm := mat.newElem()
77 if innerErr = mat.setPM(itm, pm); innerErr != nil { 99 if innerErr = mat.setPM(itm, pm); innerErr != nil {
78 return false 100 return false
79 } 101 }
80 mat.setKey(itm, k) 102 mat.setKey(itm, k)
81 return cbVal.Call([]reflect.Value{itm, reflect.ValueOf(gc)})[0]. Bool() 103 return cbVal.Call([]reflect.Value{itm, reflect.ValueOf(gc)})[0]. Bool()
82 }) 104 })
83 if err == nil { 105 if err == nil {
84 err = innerErr 106 err = innerErr
85 } 107 }
86 return err 108 return err
87 } 109 }
88 110
89 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { 111 func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error {
90 v := reflect.ValueOf(dst) 112 v := reflect.ValueOf(dst)
91 if v.Kind() != reflect.Ptr { 113 if v.Kind() != reflect.Ptr {
92 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst) 114 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst)
93 } 115 }
94 if !v.IsValid() || v.IsNil() { 116 if !v.IsValid() || v.IsNil() {
95 return errors.New("invalid GetAll dst: <nil>") 117 return errors.New("invalid GetAll dst: <nil>")
96 } 118 }
97 119
98 » if keys, ok := dst.(*[]Key); ok { 120 » if keys, ok := dst.(*[]*Key); ok {
99 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, _ CursorCB) bool { 121 » » fq, err := q.KeysOnly(true).Finalize()
122 » » if err != nil {
123 » » » return err
124 » » }
125
126 » » return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, _ Curs orCB) bool {
100 *keys = append(*keys, k) 127 *keys = append(*keys, k)
101 return true 128 return true
102 }) 129 })
103 } 130 }
131 fq, err := q.Finalize()
132 if err != nil {
133 return err
134 }
104 135
105 slice := v.Elem() 136 slice := v.Elem()
106 mat := parseMultiArg(slice.Type()) 137 mat := parseMultiArg(slice.Type())
107 if !mat.valid || mat.newElem == nil { 138 if !mat.valid || mat.newElem == nil {
108 return fmt.Errorf("invalid GetAll input type: %T", dst) 139 return fmt.Errorf("invalid GetAll input type: %T", dst)
109 } 140 }
110 141
111 » lme := errors.NewLazyMultiError(slice.Len()) 142 » errs := map[int]error{}
112 i := 0 143 i := 0
113 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ CursorCB) boo l { 144 » err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ CursorCB) bo ol {
114 slice.Set(reflect.Append(slice, mat.newElem())) 145 slice.Set(reflect.Append(slice, mat.newElem()))
115 itm := slice.Index(i) 146 itm := slice.Index(i)
116 mat.setKey(itm, k) 147 mat.setKey(itm, k)
117 » » lme.Assign(i, mat.setPM(itm, pm)) 148 » » err := mat.setPM(itm, pm)
149 » » if err != nil {
150 » » » errs[i] = err
151 » » }
118 i++ 152 i++
119 return true 153 return true
120 }) 154 })
121 if err == nil { 155 if err == nil {
122 » » err = lme.Get() 156 » » if len(errs) > 0 {
157 » » » me := make(errors.MultiError, slice.Len())
158 » » » for i, e := range errs {
159 » » » » me[i] = e
160 » » » }
161 » » » err = me
162 » » }
123 } 163 }
124 return err 164 return err
125 } 165 }
126 166
127 func isOkType(v reflect.Type) bool { 167 func isOkType(v reflect.Type) bool {
128 if v.Implements(typeOfPropertyLoadSaver) { 168 if v.Implements(typeOfPropertyLoadSaver) {
129 return true 169 return true
130 } 170 }
131 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { 171 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
132 return true 172 return true
133 } 173 }
134 return false 174 return false
135 } 175 }
136 176
137 func (d *datastoreImpl) Get(dst interface{}) (err error) { 177 func (d *datastoreImpl) Get(dst interface{}) (err error) {
138 if !isOkType(reflect.TypeOf(dst)) { 178 if !isOkType(reflect.TypeOf(dst)) {
139 return fmt.Errorf("invalid Get input type: %T", dst) 179 return fmt.Errorf("invalid Get input type: %T", dst)
140 } 180 }
141 return errors.SingleError(d.GetMulti([]interface{}{dst})) 181 return errors.SingleError(d.GetMulti([]interface{}{dst}))
142 } 182 }
143 183
144 func (d *datastoreImpl) Put(src interface{}) (err error) { 184 func (d *datastoreImpl) Put(src interface{}) (err error) {
145 if !isOkType(reflect.TypeOf(src)) { 185 if !isOkType(reflect.TypeOf(src)) {
146 return fmt.Errorf("invalid Put input type: %T", src) 186 return fmt.Errorf("invalid Put input type: %T", src)
147 } 187 }
148 return errors.SingleError(d.PutMulti([]interface{}{src})) 188 return errors.SingleError(d.PutMulti([]interface{}{src}))
149 } 189 }
150 190
151 func (d *datastoreImpl) Delete(key Key) (err error) { 191 func (d *datastoreImpl) Delete(key *Key) (err error) {
152 » return errors.SingleError(d.DeleteMulti([]Key{key})) 192 » return errors.SingleError(d.DeleteMulti([]*Key{key}))
153 } 193 }
154 194
155 func (d *datastoreImpl) GetMulti(dst interface{}) error { 195 func (d *datastoreImpl) GetMulti(dst interface{}) error {
156 slice := reflect.ValueOf(dst) 196 slice := reflect.ValueOf(dst)
157 mat := parseMultiArg(slice.Type()) 197 mat := parseMultiArg(slice.Type())
158 if !mat.valid { 198 if !mat.valid {
159 return fmt.Errorf("invalid GetMulti input type: %T", dst) 199 return fmt.Errorf("invalid GetMulti input type: %T", dst)
160 } 200 }
161 201
162 » keys, pms, err := mat.GetKeysPMs(d.NewKey, slice) 202 » keys, pms, err := mat.GetKeysPMs(d.aid, d.ns, slice)
163 if err != nil { 203 if err != nil {
164 return err 204 return err
165 } 205 }
166 206
167 lme := errors.NewLazyMultiError(len(keys)) 207 lme := errors.NewLazyMultiError(len(keys))
168 i := 0 208 i := 0
169 meta := NewMultiMetaGetter(pms) 209 meta := NewMultiMetaGetter(pms)
170 err = d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap, err error ) { 210 err = d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap, err error ) {
171 if !lme.Assign(i, err) { 211 if !lme.Assign(i, err) {
172 lme.Assign(i, mat.setPM(slice.Index(i), pm)) 212 lme.Assign(i, mat.setPM(slice.Index(i), pm))
173 } 213 }
174 i++ 214 i++
175 }) 215 })
176 216
177 if err == nil { 217 if err == nil {
178 err = lme.Get() 218 err = lme.Get()
179 } 219 }
180 return err 220 return err
181 } 221 }
182 222
183 func (d *datastoreImpl) PutMulti(src interface{}) error { 223 func (d *datastoreImpl) PutMulti(src interface{}) error {
184 slice := reflect.ValueOf(src) 224 slice := reflect.ValueOf(src)
185 mat := parseMultiArg(slice.Type()) 225 mat := parseMultiArg(slice.Type())
186 if !mat.valid { 226 if !mat.valid {
187 return fmt.Errorf("invalid PutMulti input type: %T", src) 227 return fmt.Errorf("invalid PutMulti input type: %T", src)
188 } 228 }
189 229
190 » keys, vals, err := mat.GetKeysPMs(d.NewKey, slice) 230 » keys, vals, err := mat.GetKeysPMs(d.aid, d.ns, slice)
191 if err != nil { 231 if err != nil {
192 return err 232 return err
193 } 233 }
194 234
195 lme := errors.NewLazyMultiError(len(keys)) 235 lme := errors.NewLazyMultiError(len(keys))
196 i := 0 236 i := 0
197 » err = d.RawInterface.PutMulti(keys, vals, func(key Key, err error) { 237 » err = d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) {
198 if key != keys[i] { 238 if key != keys[i] {
199 mat.setKey(slice.Index(i), key) 239 mat.setKey(slice.Index(i), key)
200 } 240 }
201 lme.Assign(i, err) 241 lme.Assign(i, err)
202 i++ 242 i++
203 }) 243 })
204 244
205 if err == nil { 245 if err == nil {
206 err = lme.Get() 246 err = lme.Get()
207 } 247 }
208 return err 248 return err
209 } 249 }
210 250
211 func (d *datastoreImpl) DeleteMulti(keys []Key) (err error) { 251 func (d *datastoreImpl) DeleteMulti(keys []*Key) (err error) {
212 lme := errors.NewLazyMultiError(len(keys)) 252 lme := errors.NewLazyMultiError(len(keys))
213 i := 0 253 i := 0
214 extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) { 254 extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) {
215 lme.Assign(i, internalErr) 255 lme.Assign(i, internalErr)
216 i++ 256 i++
217 }) 257 })
218 err = lme.Get() 258 err = lme.Get()
219 if err == nil { 259 if err == nil {
220 err = extErr 260 err = extErr
221 } 261 }
222 return 262 return
223 } 263 }
224 264
225 func (d *datastoreImpl) Raw() RawInterface { 265 func (d *datastoreImpl) Raw() RawInterface {
226 return d.RawInterface 266 return d.RawInterface
227 } 267 }
OLDNEW
« no previous file with comments | « service/datastore/context_test.go ('k') | service/datastore/datastore_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698