From f8cffc6a6bb6da80dfda6fa4c67a9af348dd4d6a Mon Sep 17 00:00:00 2001 From: Aaron Schlesinger Date: Fri, 20 Jul 2018 14:46:06 -0700 Subject: [PATCH] Doing synchronous cache filling for the .info endpoint This patch shows how we could synchronously fill in storage when the proxy or registry receive a request to '.../version.info' and the package isn't in storage. Requires https://github.com/gomods/athens/pull/291 Part of https://github.com/gomods/athens/issues/290 --- pkg/download/version_info.go | 35 +++++++++++++++++++++++++++++------ pkg/storage/getter_saver.go | 7 +++++++ 2 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 pkg/storage/getter_saver.go diff --git a/pkg/download/version_info.go b/pkg/download/version_info.go index b3592cdaa..bcae3e50d 100644 --- a/pkg/download/version_info.go +++ b/pkg/download/version_info.go @@ -8,6 +8,7 @@ import ( "github.com/bketelsen/buffet" "github.com/gobuffalo/buffalo" "github.com/gobuffalo/buffalo/render" + "github.com/gomods/athens/pkg/module" "github.com/gomods/athens/pkg/paths" "github.com/gomods/athens/pkg/storage" ) @@ -16,7 +17,11 @@ import ( const PathVersionInfo = "/{module:.+}/@v/{version}.info" // VersionInfoHandler implements GET baseURL/module/@v/version.info -func VersionInfoHandler(getter storage.Getter, eng *render.Engine) func(c buffalo.Context) error { +func VersionInfoHandler( + getterSaver storage.GetterSaver, + fetcher module.Fetcher, + eng *render.Engine, +) func(c buffalo.Context) error { return func(c buffalo.Context) error { sp := buffet.SpanFromContext(c) sp.SetOperationName("versionInfoHandler") @@ -24,18 +29,36 @@ func VersionInfoHandler(getter storage.Getter, eng *render.Engine) func(c buffal if err != nil { return err } - version, err := getter.Get(params.Module, params.Version) + version, err := getterSaver.Get(params.Module, params.Version) if storage.IsNotFoundError(err) { - msg := fmt.Sprintf("%s@%s not found", params.Module, params.Version) - return c.Render(http.StatusNotFound, eng.JSON(msg)) + // TODO: serialize cache fills (https://github.com/gomods/athens/issues/308) + ref, err := fetcher.Fetch(params.Module, params.Version) + if err != nil { + // TODO: some way to figure out whether the package actually doesn't exist + return err + } + defer ref.Clear() + ver, err := ref.Read() + if err != nil { + return err + } + getterSaver.Save(c, params.Module, params.Version, ver.Mod, ver.Zip, ver.Info) + version = ver } else if err != nil { return err } - var revInfo storage.RevInfo - err = json.Unmarshal(version.Info, &revInfo) + revInfo, err := parseRevInfo(version.Info) if err != nil { return err } return c.Render(http.StatusOK, eng.JSON(revInfo)) } } + +func parseRevInfo(b []byte) (*storage.RevInfo, error) { + revInfo := &storage.RevInfo{} + if err := json.Unmarshal(b, revInfo); err != nil { + return nil, err + } + return revInfo, nil +} diff --git a/pkg/storage/getter_saver.go b/pkg/storage/getter_saver.go new file mode 100644 index 000000000..5988dd996 --- /dev/null +++ b/pkg/storage/getter_saver.go @@ -0,0 +1,7 @@ +package storage + +// GetterSaver is a Getter and a Saver in one +type GetterSaver interface { + Getter + Saver +}