Chromium Code Reviews| Index: go/src/infra/gae/libs/wrapper/memory/datastore.go |
| diff --git a/go/src/infra/gae/libs/wrapper/memory/datastore.go b/go/src/infra/gae/libs/wrapper/memory/datastore.go |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9923774fae6b9b1c1059f76d6b7f2b52473e165e |
| --- /dev/null |
| +++ b/go/src/infra/gae/libs/wrapper/memory/datastore.go |
| @@ -0,0 +1,211 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package memory |
| + |
| +import ( |
| + "errors" |
| + "fmt" |
| + "golang.org/x/net/context" |
| + "strings" |
| + |
| + "infra/gae/libs/wrapper" |
| + |
| + "appengine/datastore" |
| + "appengine_internal" |
|
Vadim Sh.
2015/05/24 19:43:26
noooooo!
|
| + pb "appengine_internal/datastore" |
|
Vadim Sh.
2015/05/24 19:43:26
noooooo! x2
iannucci
2015/05/24 20:33:54
Yeah I know... it's all for error types though...
|
| + |
| + "github.com/mjibson/goon" |
| +) |
| + |
| +//////////////////////////////////// public //////////////////////////////////// |
| + |
| +// UseDS adds a wrapper.Datastore implementation to context, accessible |
| +// by wrapper.GetDS(c) |
| +func UseDS(c context.Context) context.Context { |
| + return wrapper.SetDSFactory(c, func(ic context.Context) wrapper.Datastore { |
| + dsd := cur(ic).Get("DS") |
| + var ret interface { |
| + wrapper.Testable |
| + wrapper.Datastore |
| + } |
| + |
| + switch x := dsd.(type) { |
| + case *dataStoreData: |
| + ret = &dsImpl{wrapper.DummyDS(), x, curGID(ic).namespace, ic} |
| + case *txnDataStoreData: |
| + ret = &txnDsImpl{wrapper.DummyDS(), x, curGID(ic).namespace} |
| + default: |
| + panic(fmt.Errorf("DS: bad type: %v", dsd)) |
| + } |
| + |
| + return ret |
| + }) |
| +} |
| + |
| +//////////////////////////////////// dsImpl //////////////////////////////////// |
| + |
| +// dsImpl exists solely to bind the current c to the datastore data. |
| +type dsImpl struct { |
| + wrapper.Datastore |
| + |
| + data *dataStoreData |
| + ns string |
| + c context.Context |
| +} |
| + |
| +/////////////////////////////// Testable(dsImpl) /////////////////////////////// |
| + |
| +func (d *dsImpl) IsBroken() error { |
| + return d.data.IsBroken() |
| +} |
| +func (d *dsImpl) SetBrokenFeatures(features ...string) { |
| + d.data.SetBrokenFeatures(features...) |
| +} |
| +func (d *dsImpl) UnsetBrokenFeatures(features ...string) { |
| + d.data.UnsetBrokenFeatures(features...) |
| +} |
| + |
| +/////////////////////////////// DSKinder(dsImpl) /////////////////////////////// |
| + |
| +func (d *dsImpl) Kind(src interface{}) string { |
| + return kind(d.ns, d.KindNameResolver(), src) |
| +} |
| + |
| +///////////////////////////// DSKindSetter(dsImpl) ///////////////////////////// |
| + |
| +func (d *dsImpl) KindNameResolver() goon.KindNameResolver { |
| + return d.data.KindNameResolver() |
| +} |
| +func (d *dsImpl) SetKindNameResolver(knr goon.KindNameResolver) { |
| + d.data.SetKindNameResolver(knr) |
| +} |
| + |
| +////////////////////////////// DSNewKeyer(dsImpl) ////////////////////////////// |
| + |
| +func (d *dsImpl) NewKey(kind, stringID string, intID int64, parent *datastore.Key) *datastore.Key { |
| + return newKey(d.ns, kind, stringID, intID, parent) |
| +} |
| +func (d *dsImpl) NewKeyObj(src interface{}) *datastore.Key { |
| + return newKeyObj(d.ns, d.KindNameResolver(), src) |
| +} |
| +func (d *dsImpl) NewKeyObjError(src interface{}) (*datastore.Key, error) { |
| + return newKeyObjError(d.ns, d.KindNameResolver(), src) |
| +} |
| + |
| +////////////////////// DSSingleReadWriter(*dataStoreData) ////////////////////// |
| + |
| +func (d *dsImpl) Put(src interface{}) (*datastore.Key, error) { |
| + err := d.data.IsBroken() |
| + if err != nil { |
| + return nil, err |
| + } |
| + return d.data.put(d.ns, src) |
| +} |
| + |
| +func (d *dsImpl) Get(dst interface{}) error { |
| + err := d.data.IsBroken() |
| + if err != nil { |
| + return err |
| + } |
| + return d.data.get(d.ns, dst) |
| +} |
| + |
| +func (d *dsImpl) Delete(key *datastore.Key) error { |
| + err := d.data.IsBroken() |
| + if err != nil { |
| + return err |
| + } |
| + return d.data.del(d.ns, key) |
| +} |
| + |
| +////////////////////////////////// txnDsImpl /////////////////////////////////// |
| + |
| +type txnDsImpl struct { |
| + wrapper.Datastore |
| + |
| + data *txnDataStoreData |
| + ns string |
| +} |
| + |
| +///////////////////////////// Testable(txnDsImpl) ////////////////////////////// |
| + |
| +func (d *txnDsImpl) IsBroken() error { |
| + return d.data.IsBroken() |
| +} |
| +func (d *txnDsImpl) SetBrokenFeatures(features ...string) { |
| + d.data.SetBrokenFeatures(features...) |
| +} |
| +func (d *txnDsImpl) UnsetBrokenFeatures(features ...string) { |
| + d.data.UnsetBrokenFeatures(features...) |
| +} |
| + |
| +///////////////////////////// DSKinder(txnDsImpl) ////////////////////////////// |
| + |
| +func (d *txnDsImpl) Kind(src interface{}) string { |
| + return kind(d.ns, d.KindNameResolver(), src) |
| +} |
| + |
| +/////////////////////////// DSKindSetter(txnDsImpl) //////////////////////////// |
| + |
| +func (d *txnDsImpl) KindNameResolver() goon.KindNameResolver { |
| + return d.data.KindNameResolver() |
| +} |
| +func (d *txnDsImpl) SetKindNameResolver(knr goon.KindNameResolver) { |
| + d.data.SetKindNameResolver(knr) |
| +} |
| + |
| +//////////////////////////// DSNewKeyer(txnDsImpl) ///////////////////////////// |
| + |
| +func (d *txnDsImpl) NewKey(kind, stringID string, intID int64, parent *datastore.Key) *datastore.Key { |
| + return newKey(d.ns, kind, stringID, intID, parent) |
| +} |
| +func (d *txnDsImpl) NewKeyObj(src interface{}) *datastore.Key { |
| + return newKeyObj(d.ns, d.KindNameResolver(), src) |
| +} |
| +func (d *txnDsImpl) NewKeyObjError(src interface{}) (*datastore.Key, error) { |
| + return newKeyObjError(d.ns, d.KindNameResolver(), src) |
| +} |
| + |
| +//////////////////////// DSSingleReadWriter(*txnDsImpl) //////////////////////// |
| + |
| +func (d *txnDsImpl) Put(src interface{}) (*datastore.Key, error) { |
| + err := d.data.IsBroken() |
| + if err != nil { |
| + return nil, err |
| + } |
| + return d.data.put(d.ns, src) |
| +} |
| + |
| +func (d *txnDsImpl) Get(dst interface{}) error { |
| + err := d.data.IsBroken() |
| + if err != nil { |
| + return err |
| + } |
| + return d.data.get(d.ns, dst) |
| +} |
| + |
| +func (d *txnDsImpl) Delete(key *datastore.Key) error { |
| + err := d.data.IsBroken() |
| + if err != nil { |
| + return err |
| + } |
| + return d.data.del(d.ns, key) |
| +} |
| + |
| +///////////////////////// DSTransactioner(*txnDsImpl) ////////////////////////// |
| + |
| +func (*txnDsImpl) RunInTransaction(func(c context.Context) error, *datastore.TransactionOptions) error { |
| + return errors.New("datastore: nested transactions are not supported") |
| +} |
| + |
| +////////////////////////////// private functions /////////////////////////////// |
| + |
| +func newDSError(code pb.Error_ErrorCode, message ...string) *appengine_internal.APIError { |
| + return &appengine_internal.APIError{ |
| + Detail: strings.Join(message, ""), |
| + Service: "datastore_v3", |
| + Code: int32(code), |
| + } |
| +} |