diff --git a/Makefile b/Makefile index ff276b3f1..44515b3a5 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: go install --tags=with_sqlite ./pkg/... ./server/... ./cmd/... ./third_party/... presubmit: - SKIP_DEP_TESTS=1 go test -short ./pkg/... ./server/camlistored ./cmd/... && echo PASS + SKIP_DEP_TESTS=1 go test --tags=with_sqlite -short ./pkg/... ./server/camlistored ./cmd/... && echo PASS embeds: go install ./pkg/fileembed/genfileembed/ && genfileembed ./server/camlistored/ui diff --git a/pkg/blobserver/registry.go b/pkg/blobserver/registry.go index b5531d1f9..8c1b1d3fc 100644 --- a/pkg/blobserver/registry.go +++ b/pkg/blobserver/registry.go @@ -32,8 +32,15 @@ type FindHandlerByTyper interface { // returns its prefix and handler if it's loaded. If it's not // loaded, the error will be ErrHandlerTypeNotFound. // - // This is used by handler constructors to find siblings (such as the "ui" type handler) + // This is used by handlers to find siblings (such as the "ui" type handler) // which might have more knowledge about the configuration for discovery, etc. + // + // Note that if this is called during handler construction + // time, only the prefix may be returned with a nil handler + // and nil err. Unlike GetHandler and GetStorage, this does + // not cause the prefix to load immediately. At runtime (after + // construction of all handlers), then prefix and handler will + // both be non-nil when err is nil. FindHandlerByType(handlerType string) (prefix string, handler interface{}, err error) } @@ -43,12 +50,19 @@ type Loader interface { // MyPrefix returns the prefix of the handler currently being constructed. MyPrefix() string - GetStorage(prefix string) (Storage, error) + // GetHandlerType returns the handler's configured type, but does + // not force it to start being loaded yet. GetHandlerType(prefix string) string // returns "" if unknown - // Returns either a Storage or an http.Handler + // GetHandler returns either a Storage or an http.Handler. + // It forces the handler to be loaded and returns an error if + // a cycle is created. GetHandler(prefix string) (interface{}, error) + // GetStorage is like GetHandler but requires that the Handler be + // a storage Handler. + GetStorage(prefix string) (Storage, error) + // If we're loading configuration in response to a web request // (as we do with App Engine), then this returns a request and // true. diff --git a/pkg/serverconfig/serverconfig.go b/pkg/serverconfig/serverconfig.go index d3be37aa8..199a04676 100644 --- a/pkg/serverconfig/serverconfig.go +++ b/pkg/serverconfig/serverconfig.go @@ -26,6 +26,7 @@ import ( "log" "net/http" "os" + "runtime" "strconv" "strings" @@ -225,7 +226,6 @@ func (hl *handlerLoader) GetHandler(prefix string) (interface{}, error) { } func (hl *handlerLoader) GetHandlerType(prefix string) string { - hl.setupHandler(prefix) return hl.configType(prefix) } @@ -247,7 +247,9 @@ func (hl *handlerLoader) setupHandler(prefix string) { return } if h.settingUp { - exitFailure("loop in configuration graph; %q tried to load itself indirectly", prefix) + buf := make([]byte, 1024) + buf = buf[:runtime.Stack(buf, false)] + exitFailure("loop in configuration graph; %q tried to load itself indirectly. Stack:\n%s", prefix, buf) } h.settingUp = true defer func() {