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

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

Issue 1259593005: Add 'user friendly' datastore API. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: Created 5 years, 4 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
(Empty)
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
3 // found in the LICENSE file.
4
5 package datastore
6
7 import (
8 "fmt"
9 "reflect"
10
11 "github.com/luci/luci-go/common/errors"
12 )
13
14 type datastoreImpl struct{ RawInterface }
15
16 var _ Interface = (*datastoreImpl)(nil)
17
18 func (d *datastoreImpl) NewKeyObj(src interface{}) Key {
19 ret, err := d.NewKeyObjErr(src)
20 if err != nil {
21 panic(err)
22 }
23 return ret
24 }
25
26 func (d *datastoreImpl) NewKeyObjErr(src interface{}) (Key, error) {
27 return newKeyObjErr(d.NewKey, src)
28 }
29
30 func (d *datastoreImpl) Run(q Query, proto interface{}, cb RunCB) error {
31 if _, ok := proto.(*Key); ok {
32 return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, gc func() (Cursor, error)) bool {
33 return cb(k, gc)
34 })
35 }
36
37 t := reflect.TypeOf(proto)
38 if t.Kind() != reflect.Ptr {
39 return fmt.Errorf("invalid Run proto type: %T", proto)
40 }
41 e := t.Elem()
42 var mkPLS func() (interface{}, PropertyLoadSaver)
43 if t.Implements(typeOfPropertyLoadSaver) {
44 mkPLS = func() (interface{}, PropertyLoadSaver) {
45 iface := reflect.New(e).Interface()
46 return iface, iface.(PropertyLoadSaver)
47 }
48 } else if e.Kind() == reflect.Struct {
49 cdc := getCodec(e)
50 mkPLS = func() (interface{}, PropertyLoadSaver) {
51 ptr := reflect.New(e)
52 return ptr.Interface(), &structPLS{ptr.Elem(), cdc}
53 }
54 }
55 if mkPLS == nil {
56 return fmt.Errorf("invalid Run proto type: %T", proto)
57 }
58
59 innerErr := error(nil)
60 err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc func() (Curs or, error)) bool {
61 iface, pls := mkPLS()
62 if innerErr = pls.Load(pm); innerErr != nil {
63 return false
64 }
65 setKey(pls, k)
66 return cb(iface, gc)
67 })
68 if err == nil {
69 err = innerErr
Vadim Sh. 2015/07/29 16:21:43 are you sure you want to return error(nil) instead
iannucci 2015/08/03 03:56:31 pretty sure it's the same thing. `innerErr := err
70 }
71 return err
72 }
73
74 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error {
75 v := reflect.ValueOf(dst)
76 if v.IsNil() {
77 return errors.New("invalid GetAll dst: <nil>")
78 }
79
80 t := v.Type()
81 if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Slice {
82 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice %T", dst)
83 }
84
85 if keys, ok := dst.(*[]Key); ok {
86 return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, _ func() (Cursor, error)) bool {
87 *keys = append(*keys, k)
88 return true
89 })
90 }
91
92 slice := v.Elem()
93 mat := parseArg(t.Elem())
94 if !mat.valid || mat.newElem == nil {
95 return fmt.Errorf("invalid GetAll input type: %T", dst)
96 }
97
98 lme := errors.LazyMultiError{Size: slice.Len()}
99 i := 0
100 err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ func() (Curso r, error)) bool {
101 itm := mat.newElem()
102 slice.Set(reflect.Append(slice, itm))
103 mat.setKey(itm, k)
104 lme.Assign(i, mat.setPM(itm, pm))
105 i++
106 return true
107 })
108 if err == nil {
109 err = lme.Get()
110 }
111 return err
112 }
113
114 func (d *datastoreImpl) Get(dst interface{}) (err error) {
115 return errors.SingleError(d.GetMulti([]interface{}{dst}))
116 }
117
118 func (d *datastoreImpl) Put(src interface{}) (err error) {
119 return errors.SingleError(d.PutMulti([]interface{}{src}))
120 }
121
122 func (d *datastoreImpl) Delete(key Key) (err error) {
123 return errors.SingleError(d.DeleteMulti([]Key{key}))
124 }
125
126 func (d *datastoreImpl) GetMulti(dst interface{}) error {
127 slice := reflect.ValueOf(dst)
128 mat := parseMultiArg(slice.Type())
129 if !mat.valid {
130 return fmt.Errorf("invalid GetMulti input type: %T", dst)
131 }
132
133 keys, err := mat.GetKeys(d.NewKey, slice)
134 if err != nil {
135 return err
136 }
137
138 lme := errors.LazyMultiError{Size: len(keys)}
139 i := 0
140 err = d.RawInterface.GetMulti(keys, func(pm PropertyMap, err error) {
141 if !lme.Assign(i, err) {
142 lme.Assign(i, mat.setPM(slice.Index(i), pm))
143 }
144 i++
145 })
146
147 if err == nil {
148 err = lme.Get()
149 }
150 return err
151 }
152
153 func (d *datastoreImpl) PutMulti(src interface{}) error {
154 slice := reflect.ValueOf(src)
155 mat := parseMultiArg(slice.Type())
156 if !mat.valid {
157 return fmt.Errorf("invalid PutMulti input type: %T", src)
158 }
159
160 keys, err := mat.GetKeys(d.NewKey, slice)
161 if err != nil {
162 return err
163 }
164
165 vals, err := mat.GetPMs(slice)
166 if err != nil {
167 return err
168 }
169
170 lme := errors.LazyMultiError{Size: len(keys)}
171 i := 0
172 err = d.RawInterface.PutMulti(keys, vals, func(key Key, err error) {
173 mat.setKey(slice.Index(i), key)
174 lme.Assign(i, err)
175 i++
176 })
177
178 if err == nil {
179 err = lme.Get()
180 }
181 return err
182 }
183
184 func (d *datastoreImpl) DeleteMulti(keys []Key) (err error) {
185 lme := errors.LazyMultiError{Size: len(keys)}
186 i := 0
187 extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) {
188 lme.Assign(i, internalErr)
189 i++
190 })
191 err = lme.Get()
192 if err == nil {
193 err = extErr
194 }
195 return
196 }
197
198 func (d *datastoreImpl) Raw() RawInterface {
199 return d.RawInterface
200 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698