From 8cbf2b063d39440856d803715366db30359d5b23 Mon Sep 17 00:00:00 2001 From: Alexander Rolek Date: Tue, 16 Jan 2018 17:09:52 -0800 Subject: [PATCH] fixed issue where cache was not being leveraged if 200 status was not being set correctly on map and layer tile requests. added tests to catch the issue in the future. closes #263 --- server/handle_map_layer_zxy.go | 2 +- server/handle_map_zxy.go | 2 +- server/middleware_tile_cache.go | 12 ++++---- server/server_test.go | 49 +++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/server/handle_map_layer_zxy.go b/server/handle_map_layer_zxy.go index 4287936a3..651e44e56 100644 --- a/server/handle_map_layer_zxy.go +++ b/server/handle_map_layer_zxy.go @@ -137,7 +137,7 @@ func (req HandleMapLayerZXY) ServeHTTP(w http.ResponseWriter, r *http.Request) { // mimetype for protocol buffers w.Header().Add("Content-Type", "application/x-protobuf") - + w.WriteHeader(http.StatusOK) w.Write(pbyte) // check for tile size warnings diff --git a/server/handle_map_zxy.go b/server/handle_map_zxy.go index fddc98e91..f057b2538 100644 --- a/server/handle_map_zxy.go +++ b/server/handle_map_zxy.go @@ -133,7 +133,7 @@ func (req HandleMapZXY) ServeHTTP(w http.ResponseWriter, r *http.Request) { // mimetype for protocol buffers w.Header().Add("Content-Type", "application/x-protobuf") - + w.WriteHeader(http.StatusOK) w.Write(pbyte) // check for tile size warnings diff --git a/server/middleware_tile_cache.go b/server/middleware_tile_cache.go index 98ea66c23..6c25ca424 100644 --- a/server/middleware_tile_cache.go +++ b/server/middleware_tile_cache.go @@ -3,10 +3,10 @@ package server import ( "bytes" "io" - "log" "net/http" "github.com/terranodo/tegola/cache" + "github.com/terranodo/tegola/internal/log" ) // TileCacheHandler implements a request cache for tiles on requests when the URLs @@ -27,7 +27,7 @@ func TileCacheHandler(next http.Handler) http.Handler { // 5 is the value of len("maps/") key, err := cache.ParseKey(r.URL.Path[5:]) if err != nil { - log.Println("cache middleware: ParseKey err: %v", err) + log.Errorf("cache middleware: ParseKey err: %v", err) next.ServeHTTP(w, r) return } @@ -35,10 +35,11 @@ func TileCacheHandler(next http.Handler) http.Handler { // use the URL path as the key cachedTile, hit, err := cacher.Get(key) if err != nil { - log.Printf("cache middleware: error reading from cache: %v", err) + log.Errorf("cache middleware: error reading from cache: %v", err) next.ServeHTTP(w, r) return } + // cache miss if !hit { // buffer which will hold a copy of the response for writing to the cache @@ -60,7 +61,7 @@ func TileCacheHandler(next http.Handler) http.Handler { } if err := cacher.Set(key, buff.Bytes()); err != nil { - log.Printf("cache response writer err: %v", err) + log.Warnf("cache response writer err: %v", err) } return } @@ -93,7 +94,7 @@ type tileCacheResponseWriter struct { } func (w *tileCacheResponseWriter) Header() http.Header { - // communicate the tegola cache is being used + // communicate the cache is being used w.resp.Header().Set("Tegola-Cache", "MISS") return w.resp.Header() @@ -102,6 +103,7 @@ func (w *tileCacheResponseWriter) Header() http.Header { func (w *tileCacheResponseWriter) Write(b []byte) (int, error) { // only write to the multi writer when http response == StatusOK if w.status == http.StatusOK { + // write to our multi writer return w.multi.Write(b) } diff --git a/server/server_test.go b/server/server_test.go index 9ae41d087..b5a901742 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -2,10 +2,12 @@ package server_test import ( "context" + "sync" "github.com/terranodo/tegola" "github.com/terranodo/tegola/atlas" "github.com/terranodo/tegola/basic" + "github.com/terranodo/tegola/cache" "github.com/terranodo/tegola/mvt" "github.com/terranodo/tegola/server" ) @@ -93,6 +95,49 @@ func (l layer) SRID() int { return l.srid } +func NewMemoryCache() *MemoryCache { + return &MemoryCache{ + keyVals: map[string][]byte{}, + } +} + +// test cacher, implements the cache.Interface +type MemoryCache struct { + keyVals map[string][]byte + sync.RWMutex +} + +func (mc *MemoryCache) Get(key *cache.Key) ([]byte, bool, error) { + mc.RLock() + defer mc.RUnlock() + + val, ok := mc.keyVals[key.String()] + if !ok { + return nil, false, nil + } + + return val, true, nil +} + +func (mc *MemoryCache) Set(key *cache.Key, val []byte) error { + mc.Lock() + defer mc.Unlock() + + mc.keyVals[key.String()] = val + + return nil +} + +func (mc *MemoryCache) Purge(key *cache.Key) error { + mc.Lock() + defer mc.Unlock() + + delete(mc.keyVals, key.String()) + + return nil +} + +// pre test setup phase func init() { server.Version = serverVersion server.HostName = serverHostName @@ -106,6 +151,10 @@ func init() { testLayer3, }...) + atlas.SetCache(NewMemoryCache()) + // register a map with atlas atlas.AddMap(testMap) + + server.Atlas = atlas.DefaultAtlas }