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

Side by Side Diff: doc.go

Issue 1247283003: Improve docs (Closed) Base URL: https://github.com/luci/gae.git@reduce_size
Patch Set: fix comments Created 5 years, 5 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
« no previous file with comments | « no previous file | filter/count/count.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Package gae provides a fakable wrapped interface for the appengine SDK's 5 // Package gae provides a fakable wrapped interface for the appengine SDK's
6 // APIs. This means that it's possible to mock all of the supported appengine 6 // APIs. This means that it's possible to mock all of the supported appengine
7 // APIs for testing (or potentially implement a different backend for them). 7 // APIs for testing (or potentially implement a different backend for them).
8 // 8 //
9 // Features
10 //
9 // gae currently provides interfaces for: 11 // gae currently provides interfaces for:
10 // * RawDatastore (a less reflection-magic version of Datastore) 12 // - RawDatastore (a less reflection-magic version of Datastore)
11 // * Memcache 13 // - Memcache
12 // * TaskQueue 14 // - TaskQueue
13 // * GlobalInfo (e.g. Namespace, AppID, etc.) 15 // - GlobalInfo (e.g. Namespace, AppID, etc.)
14 // 16 //
15 // A package which implements the gae is expected to provide the following: 17 // In addition, it provides a 'Datastore' service which adds all the reflection
16 // * A package function `Use(c context.Context, ...) context.Context` 18 // magic of the original SDK's datastore package on top of RawDatastore.
17 // This function is expected to add any information to c which is necessary
18 // for the rest of its implementations to work. This may be something like
19 // an `appengine.Context` or some connection information for an external
20 // server. The `...` in the function signature may be any additional data
21 // needed (or it may be empty).
22 // 19 //
23 // * Partially-implemented interfaces should embed one of the dummy 20 // Additional features include:
24 // implementations in the `dummy` subpackage which will panic with 21 // - true service interfaces (not package-level functions)
25 // an appropriate error for unimplemented methods. 22 // - methods don't need explicit context passed to them, increasing readabilit y.
23 // - service filters allow for composition of functionality. For example:
24 // - transparent memcaching of datastore access
25 // - transparent transaction buffering
26 // - statistics-gathering shims
27 // - deterministic and probabalistic API failure simulation
28 // - transparent retries
29 // - truly parallel in-memory testing implementation. No more need for
30 // dev_appserver.py subprocesses :).
26 // 31 //
27 // see "infra/gae/libs/gae/prod" for an appengine-backed implementation. 32 // Package Organization
28 // see "infra/gae/libs/gae/memory" for an in-memory implementation. 33 //
34 // The gae library is organized into several subpackages:
35 // - service/* supported service definitions
36 // - impl/* implementations of the services
37 // - filter/* extra filter functionality for the services, agnostic to the
38 // underlying implementation.
39 //
40 // TLDR
41 //
42 // In production, do:
43 //
44 // import (
45 // "fmt"
46 // "net/http"
47 //
48 // "github.com/luci/gae/impl/prod"
49 // "github.com/luci/gae/service/rawdatastore"
50 // "golang.org/x/net/context"
51 // )
52 //
53 // func handler(w http.ResponseWriter, r *http.Request) {
54 // c := prod.UseRequest(r)
55 // // add production filters, etc. here
56 // innerHandler(c, w)
57 // }
58 //
59 // func innerHandler(c context.Context, w http.ResponseWriter) {
60 // rds := rawdatastore.Get(c)
61 // data := rawdatastore.PropertyMap{
62 // "Value": {rawdatastore.MkProperty("hello")},
63 // }
64 // newKey, err := rds.Put(rds.NewKey("Kind", "", 0, nil), data)
65 // if err != nil {
66 // http.Error(w, err.String(), http.StatusInternalServerError)
67 // }
68 // fmt.Fprintf(w, "I wrote: %s", newKey)
69 // }
70 //
71 // And in your test do:
72 //
73 // import (
74 // "testing"
75 // "fmt"
76 // "net/http"
77 //
78 // "github.com/luci/gae/impl/memory"
79 // "github.com/luci/gae/service/rawdatastore"
80 // "golang.org/x/net/context"
81 // )
82 //
83 // func TestHandler(t *testing.T) {
84 // t.Parallel()
85 // c := memory.Use(context.Background())
86 // // use rawdatastore here to monkey with the database, install
87 // // testing filters like featureBreaker to test error conditions in
88 // // innerHandler, etc.
89 // innerHandler(c, ...)
90 // }
91 //
92 // Service Definitions
93 //
94 // A service defintion lives under the `service` subfolder, and defines the
95 // user-facing interface for a service. Each service has a few common types and
96 // functions. Common types are:
97 //
98 // service.Interface - the main service interface
99 // service.Testable - any additional methods that a 'testing' implementation
100 // should provide. It's expected that tests will cast
101 // the Interface from Get() to Testable in order to
102 // access these methods.
103 // service.Factory - a function returning an Interface
104 // service.Filter - a function returning a new Interface based on the
105 // previous filtered interface.
106 //
107 // And common functions are:
108 // service.Get - Retrieve the current, filtered Interface
109 // implementation from the context. This is the most
110 // frequently used service function by far.
111 // service.AddFilters - adds one or more Filters to the context.
112 // service.SetFactory - adds a Factory to the context
113 // service.Set - adds an implementation of Interface to the context
114 // (shorthand for SetFactory, useful for testing)
115 //
116 // Implementations
117 //
118 // The impl subdirectory contains a couple different service implementations,
119 // depending on your needs.
120 //
121 // 'prod' is the production (e.g. real appengine-backed) implementation. It
122 // calls through to the original appengine SDK.
123 //
124 // 'memory' is a truly parallel in-memory testing implementation. It should
125 // be functionally the same as the production appengine services, implementing
126 // many of the real-world quirks of the actual services. It also implements
127 // the services' Testable interface, for those services which define those
128 // interfaces.
129 //
130 // Usage
29 // 131 //
30 // You will typically access one of the service interfaces in your code like: 132 // You will typically access one of the service interfaces in your code like:
31 // // This is the 'production' code 133 // // This is the 'production' code
32 // func HTTPHandler(r *http.Request) { 134 // func HTTPHandler(r *http.Request) {
33 // c := prod.Use(appengine.NewContext(r)) 135 // c := prod.Use(appengine.NewContext(r))
34 // CoolFunc(c) 136 // CoolFunc(c)
35 // } 137 // }
36 // 138 //
37 // // This is the 'testing' code 139 // // This is the 'testing' code
38 // func TestCoolFunc(t *testing.T) { 140 // func TestCoolFunc(t *testing.T) {
39 // c := memory.Use(context.Background()) 141 // c := memory.Use(context.Background())
40 // CoolFunc(c) 142 // CoolFunc(c)
41 // } 143 // }
42 // 144 //
43 // func CoolFunc(c context.Context, ...) { 145 // func CoolFunc(c context.Context, ...) {
44 // rds := gae.GetRDS(c) // returns a RawDatastore object 146 // rds := gae.GetRDS(c) // returns a RawDatastore object
45 // mc := gae.GetMC(c) // returns a Memcache object 147 // mc := gae.GetMC(c) // returns a Memcache object
46 // // use them here 148 // // use them here
47 // 149 //
48 // // don't pass rds/mc/etc. directly, pass the context instead. 150 // // don't pass rds/mc/etc. directly, pass the context instead.
49 // SomeOtherFunction(c, ...) 151 // SomeOtherFunction(c, ...)
50 // 152 //
51 // // because you might need to: 153 // // because you might need to:
52 // rds.RunInTransaction(func (c context.Context) error { 154 // rds.RunInTransaction(func (c context.Context) error {
53 // SomeOtherFunction(c, ...) // c contains transaction versions of everyt hing 155 // SomeOtherFunction(c, ...) // c contains transaction versions of everyt hing
54 // }, nil) 156 // }, nil)
55 // } 157 // }
56 // 158 //
57 // RawDatastore struct serialization is provided by the `helper` subpackage. All 159 // RawDatastore struct serialization is provided by the `rawdatastore`
58 // supported struct types and interfaces are provided in this package, however. 160 // subpackage. All supported struct types and interfaces are provided in this
59 // You can operate without any struct serizialization/reflection by exclusively 161 // package, however. You can operate without any struct
60 // using DSPropertyMap. A goon-style Datastore interface is also provided in the 162 // serizialization/reflection by exclusively using PropertyMap. A goon-style
61 // `helper` subpackage. 163 // Datastore interface is also provided in the `datastore` service package.
164 //
165 // Filters
62 // 166 //
63 // Each service also supports "filters". Filters are proxy objects which have 167 // Each service also supports "filters". Filters are proxy objects which have
64 // the same interface as the service they're filtering, and pass data through to 168 // the same interface as the service they're filtering, and pass data through to
65 // the previous filter in the stack. Conceptually, a filtered version of, for 169 // the previous filter in the stack. Conceptually, a filtered version of, for
66 // example, the RawDatastore, could look like: 170 // example, the RawDatastore, could look like:
67 // User 171 // User code
68 // <mcache filter (attempts to use memcache as a cache for datastore)> 172 // <count filter (counts how many times each API is called by the user)>
69 // <count filter (keeps a conter for how many times each API is used)> 173 // <mcache filter (attempts to use memcache as a cache for rawdatastore)>
70 // Memory RawDatastore (contains actual data) 174 // <count filter (counts how many times each API is actually hit)>
175 // memory RawDatastore implementation
71 // 176 //
72 // So GetRDS would return the full stack, and GetRDSUnfiltered would only 177 // So rawdatastore.Get would return the full stack. In code, this would look
73 // return the bottom layer. In code, this would look like: 178 // like:
74 // func HTTPHandler(r *http.Request) { 179 // func HTTPHandler(r *http.Request) {
75 // c := prod.Use(appengine.NewContext(r)) // production datastore 180 // c := prod.Use(appengine.NewContext(r)) // production datastore
76 // c, rawCount := count.FilterRDS() // add count filter 181 // c, rawCount := count.FilterRDS() // add count filter
77 // c = mcache.FilterRDS(c) // add mcache filter 182 // c = mcache.FilterRDS(c) // add mcache filter
78 // c, userCount := count.FilterRDS() // add another count filter 183 // c, userCount := count.FilterRDS() // add another count filter
79 // } 184 // }
80 // 185 //
81 // Filters may or may not have state, it's up to the filter itself. In the case 186 // Filters may or may not have state, it's up to the filter itself. In the case
82 // of the count filter, it returns its state from the Filter<Service> method, 187 // of the count filter, it returns its state from the Filter<Service> method,
83 // and the state can be observed to see how many times each API was invoked. 188 // and the state can be observed to see how many times each API was invoked.
84 // Since filters stack, we can compare counts from rawCount versus userCount to 189 // Since filters stack, we can compare counts from rawCount versus userCount to
85 // see how many calls to the actual real datastore went through, v. how many 190 // see how many calls to the actual real datastore went through, vs. how many
86 // went to memcache, for example. 191 // went to memcache, for example.
87 package gae 192 package gae
OLDNEW
« no previous file with comments | « no previous file | filter/count/count.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698