maptilecache

package module
v1.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2022 License: MIT Imports: 18 Imported by: 0

README

This project is a simple, open source map tile cache written go and licensed under the MIT license.

Upon receiving a map tile request the cache checks for cached map tiles and evaluates its age against a previously configured "Time to Live".

  • If the tile exists and is still current it will be served directly from the cache.
  • Otherwise it will be fetched from the remote server of the map tile provider, served to the client while the cache will be updated accordingly.

Benefits

Caching map tiles locally instead of fetching them remotely reduces

  • network traffic
  • server load
  • potential costs when using metered APIs

Plus, it allows you to hide your API-Keys on the server side instead of distributing them to the client in your JavaScript.

Usage

Instead of configuring your mapping library (like leaflet, for example) to fetch tiles directly from the map tile provider, route it to the server that is running the go-maptilecache instance.

For example, if you had previously configured a leaflet tile layer in your JavaScript like this

const osm = new L.TileLayer("https://api.tiles.openaip.net/api/data/airports/{z}/{x}/{y}.png?apiKey=<...>", {
    format: "image/png",
    subdomains: ["a", "b", "c"]
});

you would now point it at your go-maptilecache instance by configuring it like this

const osm = new L.TileLayer("http://localhost:9001/maptilecache/oaip-airports/{s}/{z}/{y}/{x}/", {
    format: "image/png",
    subdomains: ["a", "b", "c"]
});

to send all leaflet tile requests to the cache instead of the server where the tiles are hosted initially.

Then configure and spin up the cache with

package main

import (
    "net/http"
    "time"

    "github.com/Christian1984/go-maptilecache"
)

func main() {
    // create an in-memory cache that can be shared across multiple maptile caches
	sharedMemoryCacheConfig := maptilecache.SharedMemoryCacheConfig{
		MaxSizeBytes:          256 * 1024 * 1024,
		EnsureMaxSizeInterval: 10 * time.Second,
		DebugLogger:           maptilecache.PrintlnDebugLogger,
		InfoLogger:            maptilecache.PrintlnInfoLogger,
		WarnLogger:            maptilecache.PrintlnWarnLogger,
		ErrorLogger:           maptilecache.PrintlnErrorLogger,
	}
	sharedMemoryCache := maptilecache.NewSharedMemoryCache(sharedMemoryCacheConfig)

    // create one or more maptile caches
	oaipAirportsCacheConfig := maptilecache.CacheConfig{
		Port:              "9001"
		Route:             []string{"maptilecache", "oaip-airports"},
		UrlScheme:         "https://api.tiles.openaip.net/api/data/airports/{z}/{x}/{y}.png?apiKey={apiKey}",
		TimeToLive:        10 * 24 * time.Hour,
		ForwardHeaders:    false, // required for openAIP, default treu works for most APIs
		SharedMemoryCache: sharedMemoryCache,
		ApiKey:            secrets.OAPI_API_KEY,
		DebugLogger:       maptilecache.PrintlnDebugLogger,
		InfoLogger:        maptilecache.PrintlnInfoLogger,
		WarnLogger:        maptilecache.PrintlnWarnLogger,
		ErrorLogger:       maptilecache.PrintlnErrorLogger,
		StatsLogDelay:     1 * time.Hour,
	}
	maptilecache.New(oaipAirportsCacheConfig)
}

Headers and Request Params

Both headers and request parameters will be forwarded to the server "as is".

Organizing The Cache With "Params-Based" Subfolders

The constructor parameter structureParams allows you to specify parameter keys that are expected by the cache and that can be used to create subfolders inside the cache root directory. As an example, consider openflight maps.

OFM requires client to add a request parameter path which identifies the current AIRAC cycle (aviation term). A request url for Leaflet to request tiles from OFM would look like this:

https://nwy-tiles-api.prod.newaydata.com/tiles/{z}/{x}/{y}.png?path=2200/aero/latest

and the corresponding request to the cache would be

http://localhost:9001/maptilecache/ofm/{s}/{z}/{y}/{x}/?path=2200/aero/latest

Now configure your cache like this

ofmCacheConfig := maptilecache.CacheConfig{
	Route:             []string{"maptilecache", "ofm"},
	UrlScheme:         "https://nwy-tiles-api.prod.newaydata.com/tiles/{z}/{x}/{y}.png",
    StructureParams:   []string{"path"}, // <= expected query parameters
    /* ... */
}
maptilecache.New(ofmCacheConfig)

The cache will forward the path param to the server and will organize all locally cached tiles according to the AIRAC cycle. The folder structure would then look like this: maptilecache/ofm/{AIRAC-cycle}/z/y/x.png

Examples

See here for examples.

Documentation

Index

Constants

View Source
const DEFAULT_HTTP_CLIENT_TIMEOUT = 6 * time.Second
View Source
const MAX_SIZE_BYTES_UNLIMITED = -1

Variables

This section is empty.

Functions

func PrintlnDebugLogger added in v0.1.3

func PrintlnDebugLogger(message string)

func PrintlnErrorLogger added in v0.1.3

func PrintlnErrorLogger(message string)

func PrintlnInfoLogger added in v0.1.3

func PrintlnInfoLogger(message string)

func PrintlnWarnLogger added in v0.1.3

func PrintlnWarnLogger(message string)

Types

type Cache

type Cache struct {
	Host            string
	Port            string
	Route           []string
	RouteString     string
	UrlScheme       string
	StructureParams []string
	TimeToLive      time.Duration
	ForwardHeaders  bool
	SharedMemCache  *SharedMemoryCache
	Client          *http.Client
	ApiKey          string
	Stats           CacheStats
	Logger          LoggerConfig
}

func New

func New(config CacheConfig) (*Cache, error)

func (*Cache) InitLogStatsRunner added in v0.1.3

func (c *Cache) InitLogStatsRunner()

func (*Cache) LogStats

func (c *Cache) LogStats()

func (*Cache) LogSystemStats added in v0.1.5

func (c *Cache) LogSystemStats()

func (*Cache) PreloadMemoryMap added in v1.0.0

func (c *Cache) PreloadMemoryMap()

func (*Cache) ValidateCache added in v0.1.1

func (c *Cache) ValidateCache()

func (*Cache) WipeCache

func (c *Cache) WipeCache() error

type CacheConfig added in v1.1.0

type CacheConfig struct {
	Host              string
	Port              string
	Route             []string
	UrlScheme         string
	StructureParams   []string
	TimeToLive        time.Duration
	ForwardHeaders    bool
	SharedMemoryCache *SharedMemoryCache
	HttpClientTimeout time.Duration
	ApiKey            string
	DebugLogger       func(string)
	InfoLogger        func(string)
	WarnLogger        func(string)
	ErrorLogger       func(string)
	StatsLogDelay     time.Duration
}

type CacheStats

type CacheStats struct {
	BytesServedFromCache  int
	BytesServedFromHDD    int
	BytesServedFromMemory int
	BytesServedFromOrigin int
}

type FilePath

type FilePath struct {
	Path     string
	FullPath string
}

type LoggerConfig

type LoggerConfig struct {
	LogPrefix     string
	LogDebugFunc  func(string)
	LogInfoFunc   func(string)
	LogWarnFunc   func(string)
	LogErrorFunc  func(string)
	StatsLogDelay time.Duration
}

configure Log*Func with external callbacks to route log message to an existing logger of the embedding application

type MemoryMap added in v1.1.0

type MemoryMap struct {
	Tiles *map[string][]byte
	Mutex *sync.RWMutex
}

type SharedMemoryCache added in v1.1.0

type SharedMemoryCache struct {
	MemoryMaps            map[string]*MemoryMap
	TileKeyHistory        []TileKeyHistoryItem
	MapMutes              *sync.RWMutex
	HistoryMutex          *sync.RWMutex
	SizeBytes             int
	MaxSizeBytes          int
	EnsureMaxSizeInterval time.Duration
	DebugLogger           func(string)
	InfoLogger            func(string)
	WarnLogger            func(string)
	ErrorLogger           func(string)
}

func NewSharedMemoryCache added in v1.1.0

func NewSharedMemoryCache(config SharedMemoryCacheConfig) *SharedMemoryCache

func (*SharedMemoryCache) EnsureMaxSize added in v1.1.0

func (m *SharedMemoryCache) EnsureMaxSize()

func (*SharedMemoryCache) MaxSizeReachedMutex added in v1.1.0

func (m *SharedMemoryCache) MaxSizeReachedMutex() bool

func (*SharedMemoryCache) MemoryMapRead added in v1.1.0

func (m *SharedMemoryCache) MemoryMapRead(mapKey string, tileKey string) (*[]byte, bool)

func (*SharedMemoryCache) MemoryMapWrite added in v1.1.0

func (m *SharedMemoryCache) MemoryMapWrite(mapKey string, tileKey string, data *[]byte)

type SharedMemoryCacheConfig added in v1.1.0

type SharedMemoryCacheConfig struct {
	MaxSizeBytes          int
	EnsureMaxSizeInterval time.Duration
	DebugLogger           func(string)
	InfoLogger            func(string)
	WarnLogger            func(string)
	ErrorLogger           func(string)
}

type TileKeyHistoryItem added in v1.1.0

type TileKeyHistoryItem struct {
	MemoryMapKey string
	TileKey      string
}

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL