| 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 | 
|  |