push app/route cache down to datastore (#303)

cache now implements models.Datastore by just embedding one and then changing
GetApp and GetRoute to have the cache inside. this makes it really flexible
for things like testing, so now the agent doesn't automagically do caching,
now it must be passed a datastore that was wrapped with a cache datastore.
the datastore in the server can remain separate and not use the cache still,
and then now the agent when running fn 'for real' is configured with the cache
baked in. this seems a lot cleaner than what we had and gets the cache out of
the way and it's easier to swap in / out / extend.
This commit is contained in:
Reed Allman
2017-09-08 09:18:36 -07:00
committed by Travis Reeder
parent 3d8ca450bb
commit 59d95d660a
4 changed files with 75 additions and 58 deletions

View File

@@ -13,7 +13,6 @@ import (
"github.com/fnproject/fn/api/models"
"github.com/go-openapi/strfmt"
"github.com/opentracing/opentracing-go"
"github.com/patrickmn/go-cache"
"github.com/sirupsen/logrus"
)
@@ -43,13 +42,12 @@ type CallOpt func(a *agent, c *call) error
func FromRequest(appName, path string, req *http.Request) CallOpt {
return func(a *agent, c *call) error {
// TODO we need to add a little timeout to these 2 things
app, err := a.app(req.Context(), appName)
app, err := a.ds.GetApp(req.Context(), appName)
if err != nil {
return err
}
route, err := a.route(req.Context(), appName, path)
route, err := a.ds.GetRoute(req.Context(), appName, path)
if err != nil {
return err
}
@@ -295,50 +293,6 @@ func (c *call) End(ctx context.Context, err error) {
}
}
func (a *agent) route(ctx context.Context, appName, path string) (*models.Route, error) {
key := routeCacheKey(appName, path)
route, ok := a.cache.Get(key)
if ok {
return route.(*models.Route), nil
}
resp, err := a.singleflight.Do(key,
func() (interface{}, error) { return a.ds.GetRoute(ctx, appName, path) },
)
if err != nil {
return nil, err
}
route = resp.(*models.Route)
a.cache.Set(key, route, cache.DefaultExpiration)
return route.(*models.Route), nil
}
func (a *agent) app(ctx context.Context, appName string) (*models.App, error) {
key := appCacheKey(appName)
app, ok := a.cache.Get(key)
if ok {
return app.(*models.App), nil
}
resp, err := a.singleflight.Do(key,
func() (interface{}, error) { return a.ds.GetApp(ctx, appName) },
)
if err != nil {
return nil, err
}
app = resp.(*models.App)
a.cache.Set(key, app, cache.DefaultExpiration)
return app.(*models.App), nil
}
func routeCacheKey(appname, path string) string {
return "r:" + appname + "\x00" + path
}
func appCacheKey(appname string) string {
return "a:" + appname
}
func fakeHandler(http.ResponseWriter, *http.Request, Params) {}
// TODO what is this stuff anyway?