| Index: go/src/infra/gae/libs/gae/doc.go
|
| diff --git a/go/src/infra/gae/libs/gae/doc.go b/go/src/infra/gae/libs/gae/doc.go
|
| index a42695bac5e402f1eeecd60667eb74c1051b4423..2704e4c15b83786e22c7f224e9696500b9e5f8b4 100644
|
| --- a/go/src/infra/gae/libs/gae/doc.go
|
| +++ b/go/src/infra/gae/libs/gae/doc.go
|
| @@ -7,56 +7,81 @@
|
| // APIs for testing (or potentially implement a different backend for them).
|
| //
|
| // gae currently provides interfaces for:
|
| -// * Datastore
|
| +// * RawDatastore (a less reflection-magic version of Datastore)
|
| // * Memcache
|
| // * TaskQueue
|
| // * GlobalInfo (e.g. Namespace, AppID, etc.)
|
| //
|
| // A package which implements the gae is expected to provide the following:
|
| -// * A package function `Enable(c context.Context, ...) context.Context`
|
| +// * A package function `Use(c context.Context, ...) context.Context`
|
| // This function is expected to add any information to c which is necessary
|
| // for the rest of its implementations to work. This may be something like
|
| // an `appengine.Context` or some connection information for an external
|
| // server. The `...` in the function signature may be any additional data
|
| -// needed.
|
| -// * Any of the package functions:
|
| -//
|
| -// UseDS(context.Context) context.Context
|
| -// UseMC(context.Context) context.Context
|
| -// UseTQ(context.Context) context.Context
|
| -// UseGI(context.Context) context.Context
|
| -//
|
| -// each of which would call gae.Set<service>Factory with the factory
|
| -// function for that interface type.
|
| -// * A `Use(context.Context) context.Context` function which calls all of the
|
| -// `Use*` package functions implemented by the package.
|
| -// * Partially-implemented interfaces should embed one of the Dummy* structs
|
| -// which will panic with an appropriate error for unimplemented
|
| -// methods.
|
| -//
|
| -// see "infra/gae/libs/gae/oldsdk" for an appengine-backed implementation.
|
| -//
|
| -// Datastore struct serialization uses the tag name 'gae' instead of 'datastore',
|
| -// and uses gae.DSKey but otherwise behaves identically. You must use the
|
| -// new-SDK primitive types (like GeoPoint, ByteString, etc.), even when using
|
| -// the old-SDK implementation of the factories. This was done to ensure that all
|
| -// code written against gae is go-gettable, and was deemed as less-annoying than
|
| -// re-defining all of the types identically.
|
| -//
|
| -// Kinds/Keys work similarly to how they work in goon (except you no longer use
|
| -// the goon + datastore tags and key/control-related tags start with $):
|
| -//
|
| -// type FooModel struct {
|
| -// _kind string `gae:"$kind,Foo"`
|
| -// Id string `gae:"$id"`
|
| -// Parent DSKey `gae:"$parent"`
|
| -//
|
| -// privateSkipped bool
|
| -// AutoSave int
|
| -// NoSaveField string `gae:"-"`
|
| -// NoIndexField float `gae:",noindex"`
|
| -// DiffName string `gae:"coolName"`
|
| +// needed (or it may be empty).
|
| +//
|
| +// * Partially-implemented interfaces should embed one of the dummy
|
| +// implementations in the `dummy` subpackage which will panic with
|
| +// an appropriate error for unimplemented methods.
|
| +//
|
| +// see "infra/gae/libs/gae/prod" for an appengine-backed implementation.
|
| +// see "infra/gae/libs/gae/memory" for an in-memory implementation.
|
| +//
|
| +// You will typically access one of the service interfaces in your code like:
|
| +// // This is the 'production' code
|
| +// func HTTPHandler(r *http.Request) {
|
| +// c := prod.Use(appengine.NewContext(r))
|
| +// CoolFunc(c)
|
| +// }
|
| +//
|
| +// // This is the 'testing' code
|
| +// func TestCoolFunc(t *testing.T) {
|
| +// c := memory.Use(context.Background())
|
| +// CoolFunc(c)
|
| +// }
|
| +//
|
| +// func CoolFunc(c context.Context, ...) {
|
| +// rds := gae.GetRDS(c) // returns a RawDatastore object
|
| +// mc := gae.GetMC(c) // returns a Memcache object
|
| +// // use them here
|
| +//
|
| +// // don't pass rds/mc/etc. directly, pass the context instead.
|
| +// SomeOtherFunction(c, ...)
|
| +//
|
| +// // because you might need to:
|
| +// rds.RunInTransaction(func (c context.Context) error {
|
| +// SomeOtherFunction(c, ...) // c contains transaction versions of everything
|
| +// }, nil)
|
| +// }
|
| +//
|
| +// RawDatastore struct serialization is provided by the `helper` subpackage. All
|
| +// supported struct types and interfaces are provided in this package, however.
|
| +// You can operate without any struct serizialization/reflection by exclusively
|
| +// using DSPropertyMap. A goon-style Datastore interface is also provided in the
|
| +// `helper` subpackage.
|
| +//
|
| +// Each service also supports "filters". Filters are proxy objects which have
|
| +// the same interface as the service they're filtering, and pass data through to
|
| +// the previous filter in the stack. Conceptually, a filtered version of, for
|
| +// example, the RawDatastore, could look like:
|
| +// User
|
| +// <mcache filter (attempts to use memcache as a cache for datastore)>
|
| +// <count filter (keeps a conter for how many times each API is used)>
|
| +// Memory RawDatastore (contains actual data)
|
| +//
|
| +// So GetRDS would return the full stack, and GetRDSUnfiltered would only
|
| +// return the bottom layer. In code, this would look like:
|
| +// func HTTPHandler(r *http.Request) {
|
| +// c := prod.Use(appengine.NewContext(r)) // production datastore
|
| +// c, rawCount := count.FilterRDS() // add count filter
|
| +// c = mcache.FilterRDS(c) // add mcache filter
|
| +// c, userCount := count.FilterRDS() // add another count filter
|
| // }
|
| //
|
| -// func (FooModel) GetCachePolicy() DSCacheFlags { return DSCache }
|
| +// Filters may or may not have state, it's up to the filter itself. In the case
|
| +// of the count filter, it returns its state from the Filter<Service> method,
|
| +// and the state can be observed to see how many times each API was invoked.
|
| +// Since filters stack, we can compare counts from rawCount versus userCount to
|
| +// see how many calls to the actual real datastore went through, v. how many
|
| +// went to memcache, for example.
|
| package gae
|
|
|