go.mercari.io/datastore@v1.8.2/clouddatastore/client.go (about) 1 package clouddatastore 2 3 import ( 4 "context" 5 "errors" 6 7 "cloud.google.com/go/datastore" 8 w "go.mercari.io/datastore" 9 "go.mercari.io/datastore/internal/shared" 10 ) 11 12 var _ w.Client = (*datastoreImpl)(nil) 13 14 type datastoreImpl struct { 15 ctx context.Context 16 client *datastore.Client 17 middlewares []w.Middleware 18 } 19 20 func (d *datastoreImpl) Get(ctx context.Context, key w.Key, dst interface{}) error { 21 err := d.GetMulti(ctx, []w.Key{key}, []interface{}{dst}) 22 if merr, ok := err.(w.MultiError); ok { 23 return merr[0] 24 } else if err != nil { 25 return err 26 } 27 28 return nil 29 } 30 31 func (d *datastoreImpl) GetMulti(ctx context.Context, keys []w.Key, dst interface{}) error { 32 cacheInfo := &w.MiddlewareInfo{ 33 Context: ctx, 34 Client: d, 35 } 36 cb := shared.NewCacheBridge(cacheInfo, &originalClientBridgeImpl{d}, nil, nil, d.middlewares) 37 38 return shared.GetMultiOps(ctx, keys, dst, func(keys []w.Key, dst []w.PropertyList) error { 39 return cb.GetMultiWithoutTx(cacheInfo, keys, dst) 40 }) 41 } 42 43 func (d *datastoreImpl) Put(ctx context.Context, key w.Key, src interface{}) (w.Key, error) { 44 keys, err := d.PutMulti(ctx, []w.Key{key}, []interface{}{src}) 45 if merr, ok := err.(w.MultiError); ok { 46 return nil, merr[0] 47 } else if err != nil { 48 return nil, err 49 } 50 51 return keys[0], nil 52 } 53 54 func (d *datastoreImpl) PutMulti(ctx context.Context, keys []w.Key, src interface{}) ([]w.Key, error) { 55 cacheInfo := &w.MiddlewareInfo{ 56 Context: ctx, 57 Client: d, 58 } 59 cb := shared.NewCacheBridge(cacheInfo, &originalClientBridgeImpl{d}, nil, nil, d.middlewares) 60 61 keys, _, err := shared.PutMultiOps(ctx, keys, src, func(keys []w.Key, src []w.PropertyList) ([]w.Key, []w.PendingKey, error) { 62 keys, err := cb.PutMultiWithoutTx(cacheInfo, keys, src) 63 return keys, nil, err 64 }) 65 if err != nil { 66 return nil, err 67 } 68 69 return keys, nil 70 } 71 72 func (d *datastoreImpl) Delete(ctx context.Context, key w.Key) error { 73 err := d.DeleteMulti(ctx, []w.Key{key}) 74 if merr, ok := err.(w.MultiError); ok { 75 return merr[0] 76 } else if err != nil { 77 return err 78 } 79 80 return nil 81 } 82 83 func (d *datastoreImpl) DeleteMulti(ctx context.Context, keys []w.Key) error { 84 cacheInfo := &w.MiddlewareInfo{ 85 Context: ctx, 86 Client: d, 87 } 88 cb := shared.NewCacheBridge(cacheInfo, &originalClientBridgeImpl{d}, nil, nil, d.middlewares) 89 90 return shared.DeleteMultiOps(ctx, keys, func(keys []w.Key) error { 91 return cb.DeleteMultiWithoutTx(cacheInfo, keys) 92 }) 93 } 94 95 func (d *datastoreImpl) NewTransaction(ctx context.Context) (w.Transaction, error) { 96 tx, err := d.client.NewTransaction(ctx) 97 if err != nil { 98 return nil, toWrapperError(err) 99 } 100 101 txCtx := context.WithValue(ctx, contextTransaction{}, tx) 102 txImpl := &transactionImpl{ 103 client: &datastoreImpl{ 104 ctx: txCtx, 105 client: d.client, 106 middlewares: d.middlewares, 107 }, 108 } 109 txImpl.cacheInfo = &w.MiddlewareInfo{ 110 Context: txCtx, 111 Client: d, 112 Transaction: txImpl, 113 } 114 115 return txImpl, nil 116 } 117 118 func (d *datastoreImpl) RunInTransaction(ctx context.Context, f func(tx w.Transaction) error) (w.Commit, error) { 119 var txImpl *transactionImpl 120 commit, err := d.client.RunInTransaction(ctx, func(baseTx *datastore.Transaction) error { 121 txCtx := context.WithValue(ctx, contextTransaction{}, baseTx) 122 txImpl = &transactionImpl{ 123 client: &datastoreImpl{ 124 ctx: txCtx, 125 client: d.client, 126 middlewares: d.middlewares, 127 }, 128 } 129 txImpl.cacheInfo = &w.MiddlewareInfo{ 130 Context: txCtx, 131 Client: d, 132 Transaction: txImpl, 133 } 134 return f(txImpl) 135 }, datastore.MaxAttempts(1)) 136 if err != nil { 137 return nil, toWrapperError(err) 138 } 139 140 cb := shared.NewCacheBridge(txImpl.cacheInfo, &originalClientBridgeImpl{txImpl.client}, &originalTransactionBridgeImpl{tx: txImpl}, nil, txImpl.client.middlewares) 141 commitImpl := &commitImpl{commit} 142 err = cb.PostCommit(txImpl.cacheInfo, txImpl, commitImpl) 143 144 if err != nil { 145 return nil, err 146 } 147 148 return commitImpl, nil 149 } 150 151 func (d *datastoreImpl) Run(ctx context.Context, q w.Query) w.Iterator { 152 cacheInfo := &w.MiddlewareInfo{ 153 Context: ctx, 154 Client: d, 155 } 156 cb := shared.NewCacheBridge(cacheInfo, &originalClientBridgeImpl{d}, nil, nil, d.middlewares) 157 158 return cb.Run(cb.Info, q, q.Dump()) 159 } 160 161 func (d *datastoreImpl) AllocateIDs(ctx context.Context, keys []w.Key) ([]w.Key, error) { 162 cacheInfo := &w.MiddlewareInfo{ 163 Context: ctx, 164 Client: d, 165 } 166 cb := shared.NewCacheBridge(cacheInfo, &originalClientBridgeImpl{d}, nil, nil, d.middlewares) 167 168 return cb.AllocateIDs(cb.Info, keys) 169 } 170 171 func (d *datastoreImpl) Count(ctx context.Context, q w.Query) (int, error) { 172 cacheInfo := &w.MiddlewareInfo{ 173 Context: ctx, 174 Client: d, 175 } 176 cb := shared.NewCacheBridge(cacheInfo, &originalClientBridgeImpl{d}, nil, nil, d.middlewares) 177 178 return cb.Count(cb.Info, q, q.Dump()) 179 } 180 181 func (d *datastoreImpl) GetAll(ctx context.Context, q w.Query, dst interface{}) ([]w.Key, error) { 182 qImpl, ok := q.(*queryImpl) 183 if !ok { 184 return nil, errors.New("invalid query type") 185 } 186 187 if qImpl.firstError != nil { 188 return nil, qImpl.firstError 189 } 190 191 qDump := q.Dump() 192 cacheInfo := &w.MiddlewareInfo{ 193 Context: ctx, 194 Client: d, 195 Transaction: qDump.Transaction, 196 } 197 cb := shared.NewCacheBridge(cacheInfo, &originalClientBridgeImpl{d}, nil, nil, d.middlewares) 198 return shared.GetAllOps(ctx, qDump, dst, func(dst *[]w.PropertyList) ([]w.Key, error) { 199 return cb.GetAll(cacheInfo, q, qDump, dst) 200 }) 201 } 202 203 func (d *datastoreImpl) IncompleteKey(kind string, parent w.Key) w.Key { 204 key := &keyImpl{ 205 kind: kind, 206 id: 0, 207 name: "", 208 } 209 if parent != nil { 210 parentImpl := parent.(*keyImpl) 211 key.parent = parentImpl 212 } 213 214 return key 215 } 216 217 func (d *datastoreImpl) NameKey(kind, name string, parent w.Key) w.Key { 218 key := &keyImpl{ 219 kind: kind, 220 id: 0, 221 name: name, 222 } 223 if parent != nil { 224 parentImpl := parent.(*keyImpl) 225 key.parent = parentImpl 226 } 227 228 return key 229 } 230 231 func (d *datastoreImpl) IDKey(kind string, id int64, parent w.Key) w.Key { 232 key := &keyImpl{ 233 kind: kind, 234 id: id, 235 name: "", 236 } 237 if parent != nil { 238 parentImpl := parent.(*keyImpl) 239 key.parent = parentImpl 240 } 241 242 return key 243 } 244 245 func (d *datastoreImpl) NewQuery(kind string) w.Query { 246 q := datastore.NewQuery(kind) 247 return &queryImpl{ctx: d.ctx, q: q, dump: &w.QueryDump{Kind: kind}} 248 } 249 250 func (d *datastoreImpl) Close() error { 251 return d.client.Close() 252 } 253 254 func (d *datastoreImpl) DecodeKey(encoded string) (w.Key, error) { 255 key, err := datastore.DecodeKey(encoded) 256 if err != nil { 257 return nil, toWrapperError(err) 258 } 259 260 return toWrapperKey(key), nil 261 } 262 263 func (d *datastoreImpl) DecodeCursor(s string) (w.Cursor, error) { 264 cur, err := datastore.DecodeCursor(s) 265 if err != nil { 266 return nil, toWrapperError(err) 267 } 268 269 return &cursorImpl{cursor: cur}, nil 270 } 271 272 func (d *datastoreImpl) Batch() *w.Batch { 273 return &w.Batch{Client: d} 274 } 275 276 func (d *datastoreImpl) AppendMiddleware(mw w.Middleware) { 277 d.middlewares = append(d.middlewares, mw) 278 } 279 280 func (d *datastoreImpl) RemoveMiddleware(mw w.Middleware) bool { 281 list := make([]w.Middleware, 0, len(d.middlewares)) 282 found := false 283 for _, old := range d.middlewares { 284 if old == mw { 285 found = true 286 continue 287 } 288 list = append(list, old) 289 } 290 d.middlewares = list 291 292 return found 293 } 294 295 func (d *datastoreImpl) Context() context.Context { 296 return d.ctx 297 } 298 299 func (d *datastoreImpl) SetContext(ctx context.Context) { 300 if ctx == nil { 301 panic("ctx can't be nil") 302 } 303 d.ctx = ctx 304 }