| Index: impl/prod/context.go
|
| diff --git a/impl/prod/context.go b/impl/prod/context.go
|
| index fc4a5e8fd9afc7036620e605b4f60fb2f3b85878..10ba7d1d36433213957863ea0fa3b309f8020563 100644
|
| --- a/impl/prod/context.go
|
| +++ b/impl/prod/context.go
|
| @@ -11,7 +11,6 @@ import (
|
| "net/url"
|
| "strings"
|
|
|
| - "github.com/luci/gae/service/info"
|
| "github.com/luci/gae/service/urlfetch"
|
| "golang.org/x/net/context"
|
| gOAuth "golang.org/x/oauth2/google"
|
| @@ -29,9 +28,8 @@ var RemoteAPIScopes = []string{
|
| type key int
|
|
|
| var (
|
| - prodContextKey key
|
| - prodContextNoTxnKey key = 1
|
| - probeCacheKey key = 2
|
| + prodStateKey = "contains the current *prodState"
|
| + probeCacheKey = "contains the current *infoProbeCache"
|
| )
|
|
|
| // AEContext retrieves the raw "google.golang.org/appengine" compatible Context.
|
| @@ -40,40 +38,15 @@ var (
|
| // RPCs. Doesn't transfer cancelation ability though (since it's ignored by GAE
|
| // anyway).
|
| func AEContext(c context.Context) context.Context {
|
| - aeCtx, _ := c.Value(prodContextKey).(context.Context)
|
| - if aeCtx == nil {
|
| - return nil
|
| - }
|
| - if deadline, ok := c.Deadline(); ok {
|
| - aeCtx, _ = context.WithDeadline(aeCtx, deadline)
|
| - }
|
| - return aeCtx
|
| -}
|
| -
|
| -// AEContextNoTxn retrieves the raw "google.golang.org/appengine" compatible
|
| -// Context that's not part of a transaction.
|
| -func AEContextNoTxn(c context.Context) context.Context {
|
| - aeCtx, _ := c.Value(prodContextNoTxnKey).(context.Context)
|
| - if aeCtx == nil {
|
| - return nil
|
| - }
|
| -
|
| - if ns, has := info.Get(c).GetNamespace(); has {
|
| - var err error
|
| - aeCtx, err = appengine.Namespace(aeCtx, ns)
|
| - if err != nil {
|
| - panic(err)
|
| - }
|
| - }
|
| - if deadline, ok := c.Deadline(); ok {
|
| - aeCtx, _ = context.WithDeadline(aeCtx, deadline)
|
| - }
|
| - return aeCtx
|
| + ps := getProdState(c)
|
| + return ps.context(c)
|
| }
|
|
|
| func setupAECtx(c, aeCtx context.Context) context.Context {
|
| - c = context.WithValue(c, prodContextKey, aeCtx)
|
| - c = context.WithValue(c, prodContextNoTxnKey, aeCtx)
|
| + c = withProdState(c, prodState{
|
| + ctx: aeCtx,
|
| + noTxnCtx: aeCtx,
|
| + })
|
| return useModule(useMail(useUser(useURLFetch(useRDS(useMC(useTQ(useGI(useLogging(c)))))))))
|
| }
|
|
|
| @@ -123,9 +96,11 @@ func Use(c context.Context, r *http.Request) context.Context {
|
| // - "https://www.googleapis.com/auth/cloud.platform"
|
| func UseRemote(inOutCtx *context.Context, host string, client *http.Client) (err error) {
|
| if client == nil {
|
| + aeCtx := AEContext(*inOutCtx)
|
| +
|
| if strings.HasPrefix(host, "localhost") {
|
| transp := http.DefaultTransport
|
| - if aeCtx := AEContextNoTxn(*inOutCtx); aeCtx != nil {
|
| + if aeCtx != nil {
|
| transp = urlfetch.Get(*inOutCtx)
|
| }
|
|
|
| @@ -147,7 +122,6 @@ func UseRemote(inOutCtx *context.Context, host string, client *http.Client) (err
|
| }
|
| defer rsp.Body.Close()
|
| } else {
|
| - aeCtx := AEContextNoTxn(*inOutCtx)
|
| if aeCtx == nil {
|
| aeCtx = context.Background()
|
| }
|
| @@ -165,3 +139,48 @@ func UseRemote(inOutCtx *context.Context, host string, client *http.Client) (err
|
| *inOutCtx = setupAECtx(*inOutCtx, aeCtx)
|
| return nil
|
| }
|
| +
|
| +// prodState is the current production state.
|
| +type prodState struct {
|
| + // ctx is the current derived GAE context.
|
| + ctx context.Context
|
| +
|
| + // noTxnCtx is a Context maintained alongside ctx. When a transaction is
|
| + // entered, ctx will be updated, but noTxnCtx will not, allowing extra-
|
| + // transactional Context access.
|
| + noTxnCtx context.Context
|
| +
|
| + // inTxn if true if this is in a transaction, false otherwise.
|
| + inTxn bool
|
| +}
|
| +
|
| +func getProdState(c context.Context) prodState {
|
| + if v := c.Value(&prodStateKey).(*prodState); v != nil {
|
| + return *v
|
| + }
|
| + return prodState{}
|
| +}
|
| +
|
| +func withProdState(c context.Context, ps prodState) context.Context {
|
| + return context.WithValue(c, &prodStateKey, &ps)
|
| +}
|
| +
|
| +// context returns the current AppEngine-bound Context. Prior to returning,
|
| +// the deadline from "c" (if any) is applied.
|
| +//
|
| +// Note that this does not (currently) apply any other Done state or propagate
|
| +// cancellation from "c".
|
| +//
|
| +// Tracking at:
|
| +// https://github.com/luci/gae/issues/59
|
| +func (ps *prodState) context(c context.Context) context.Context {
|
| + aeCtx := ps.ctx
|
| + if aeCtx == nil {
|
| + return nil
|
| + }
|
| +
|
| + if deadline, ok := c.Deadline(); ok {
|
| + aeCtx, _ = context.WithDeadline(aeCtx, deadline)
|
| + }
|
| + return aeCtx
|
| +}
|
|
|