From c5e95dd73456ab45ea30952f89214d88096ba2d5 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski <janne@kuschku.de> Date: Sat, 4 May 2019 17:35:05 +0200 Subject: [PATCH] Improve cache handling --- cache_redis.go | 19 +++++++++---- config.go | 31 ++++++++++++++++++++++ go.mod | 3 ++- go.sum | 5 ++-- main.go | 72 ++++++++++++++++++++++++++++++++++---------------- 5 files changed, 99 insertions(+), 31 deletions(-) create mode 100644 config.go diff --git a/cache_redis.go b/cache_redis.go index cf4ac66..cc2af24 100644 --- a/cache_redis.go +++ b/cache_redis.go @@ -2,6 +2,7 @@ package main import ( "encoding/json" + "errors" "git.kuschku.de/justjanne/bahn-api" "github.com/go-redis/cache" "github.com/go-redis/redis" @@ -15,24 +16,32 @@ type RedisCache struct { func (m RedisCache) Set(key string, value interface{}) error { return m.backend.Set(&cache.Item{ - Key: key, - Object: value, + Key: key, + Object: value, Expiration: m.expirationTime, }) } func (m RedisCache) Get(key string, value interface{}) error { - return m.backend.Get(key, &value) + err := m.backend.Get(key, &value) + if err != nil { + return err + } else if value == nil { + return errors.New("redis returned empty result") + } + return nil } -func NewRedisCache(expirationTime time.Duration) bahn.CacheBackend { +func NewRedisCache(address string, password string, expirationTime time.Duration) bahn.CacheBackend { return RedisCache{ backend: &cache.Codec{ Redis: redis.NewClient(&redis.Options{ - + Addr: address, + Password: password, }), Marshal: json.Marshal, Unmarshal: json.Unmarshal, }, + expirationTime: expirationTime, } } diff --git a/config.go b/config.go new file mode 100644 index 0000000..020ab1e --- /dev/null +++ b/config.go @@ -0,0 +1,31 @@ +package main + +import "time" + +type Config struct { + Endpoints EndpointConfig `yaml:"endpoints"` + Caches CacheConfig `yaml:"caches"` + RequestTimeout time.Duration `yaml:"request_timeout"` + MaxResults int `yaml:"max_results"` +} + +type EndpointConfig struct { + Iris string `yaml:"iris"` + CoachSequence string `yaml:"coach_sequence"` + Hafas string `yaml:"hafas"` +} + +type CacheConfig struct { + Redis RedisCacheConfig `yaml:"redis"` + Memory MemoryCacheConfig `yaml:"memory"` +} + +type RedisCacheConfig struct { + Address string `yaml:"address"` + Password string `yaml:"password"` + Timeout time.Duration `yaml:"timeout"` +} + +type MemoryCacheConfig struct { + Timeout time.Duration `yaml:"timeout"` +} diff --git a/go.mod b/go.mod index 52e01cf..571943c 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,9 @@ module git.kuschku.de/justjanne/bahn-proxy go 1.12 require ( - git.kuschku.de/justjanne/bahn-api v0.0.0-20190504114009-71c830fe0812 + git.kuschku.de/justjanne/bahn-api v0.0.0-20190504153151-3f6741590505 github.com/go-redis/cache v6.3.5+incompatible github.com/go-redis/redis v6.15.2+incompatible github.com/patrickmn/go-cache v2.1.0+incompatible + gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index 494c061..ce54561 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -git.kuschku.de/justjanne/bahn-api v0.0.0-20190504114009-71c830fe0812 h1:dhL0LHGoud1so9Be3namg7g+/PtGVGhldtw+agNActg= -git.kuschku.de/justjanne/bahn-api v0.0.0-20190504114009-71c830fe0812/go.mod h1:WQsAQzBR+0dlaVVuwwkx8j5uMoWDIdc8xtX4vlRrp5E= +git.kuschku.de/justjanne/bahn-api v0.0.0-20190504153151-3f6741590505 h1:5ZpJaz2ltYxdBpqPGVdLfVgUx0GIQ+h+Kt9o/qI/JzI= +git.kuschku.de/justjanne/bahn-api v0.0.0-20190504153151-3f6741590505/go.mod h1:WQsAQzBR+0dlaVVuwwkx8j5uMoWDIdc8xtX4vlRrp5E= github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/go-redis/cache v6.3.5+incompatible h1:4OUyoXXYRRQ6tKA4ue3TlPUkBzk3occzjtXBZBxCzgs= @@ -14,4 +14,5 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index e0180a5..a3a4cdc 100644 --- a/main.go +++ b/main.go @@ -2,10 +2,13 @@ package main import ( "encoding/json" + "flag" "fmt" "git.kuschku.de/justjanne/bahn-api" + "gopkg.in/yaml.v2" "log" "net/http" + "os" "path" "sort" "strconv" @@ -28,22 +31,41 @@ func returnJson(w http.ResponseWriter, data interface{}) error { } func main() { + var err error + + configPath := flag.String("config", "config.yaml", "Path to config file") + listen := flag.String("listen", ":8080", "Listen address") + flag.Parse() + + var configFile *os.File + if configFile, err = os.Open(*configPath); err != nil { + panic(err) + } + + var config Config + if err = yaml.NewDecoder(configFile).Decode(&config); err != nil { + panic(err) + } + autocompleteStations := loadAutocompleteStations() apiClient := bahn.ApiClient{ - IrisBaseUrl: "http://iris.noncd.db.de/iris-tts", - CoachSequenceBaseUrl: "https://www.apps-bahn.de/wr/wagenreihung/1.0", - HafasBaseUrl: "https://reiseauskunft.bahn.de/bin", + IrisBaseUrl: config.Endpoints.Iris, + CoachSequenceBaseUrl: config.Endpoints.CoachSequence, + HafasBaseUrl: config.Endpoints.Hafas, HttpClient: &http.Client{ - Timeout: time.Second * 10, + Timeout: config.RequestTimeout, }, Caches: []bahn.CacheBackend{ - NewMemoryCache(5 * time.Minute), + NewMemoryCache(config.Caches.Memory.Timeout), + NewRedisCache( + config.Caches.Redis.Address, + config.Caches.Redis.Password, + config.Caches.Redis.Timeout, + ), }, } - MaxResults := 20 - http.HandleFunc("/autocomplete/", func(w http.ResponseWriter, r *http.Request) { if stationName := strings.TrimSpace(r.FormValue("name")); stationName != "" { var perfectMatch []AutocompleteStation @@ -62,14 +84,14 @@ func main() { contains = append(contains, station) } - if len(perfectMatch)+len(prefix)+len(contains) >= MaxResults { + if len(perfectMatch)+len(prefix)+len(contains) >= config.MaxResults { break } } result := append(append(perfectMatch, prefix...), contains...) if err := returnJson(w, result); err != nil { - log.Fatal(err) + log.Println(err) return } } else if position, err := PositionFromString(strings.TrimSpace(r.FormValue("position"))); err == nil { @@ -87,8 +109,8 @@ func main() { return result[i].Distance < result[j].Distance }) - if err := returnJson(w, result[:MaxResults]); err != nil { - log.Fatal(err) + if err := returnJson(w, result[:config.MaxResults]); err != nil { + log.Println(err) return } } @@ -101,18 +123,18 @@ func main() { var evaId int64 if evaId, err = strconv.ParseInt(rawEvaId, 10, 64); err != nil { - log.Fatal(err) + log.Println(err) return } var stations []bahn.Station if stations, err = apiClient.Station(evaId); err != nil { - log.Fatal(err) + log.Println(err) return } if err = returnJson(w, stations); err != nil { - log.Fatal(err) + log.Println(err) return } }) @@ -124,7 +146,7 @@ func main() { var evaId int64 if evaId, err = strconv.ParseInt(rawEvaId, 10, 64); err != nil { - log.Fatal(err) + log.Println(err) return } @@ -137,7 +159,7 @@ func main() { var timetable bahn.Timetable if timetable, err = apiClient.Timetable(evaId, date); err != nil { - log.Fatal(err) + log.Println(err) return } for _, stop := range timetable.Stops { @@ -148,7 +170,7 @@ func main() { var realtime bahn.Timetable if realtime, err = apiClient.RealtimeAll(evaId, date); err != nil { - log.Fatal(err) + log.Println(err) return } for _, stop := range realtime.Stops { @@ -161,11 +183,13 @@ func main() { for key, combined := range data { if combined.Timetable.Arrival != nil && combined.Timetable.Arrival.Wings != "" { if combined.WingDefinition, err = apiClient.WingDefinition(combined.Timetable.StopId, combined.Timetable.Arrival.Wings); err != nil { - log.Fatal(err) + log.Println(err) + return } } else if combined.Timetable.Departure != nil && combined.Timetable.Departure.Wings != "" { if combined.WingDefinition, err = apiClient.WingDefinition(combined.Timetable.StopId, combined.Timetable.Departure.Wings); err != nil { - log.Fatal(err) + log.Println(err) + return } } data[key] = combined @@ -183,7 +207,8 @@ func main() { searchQuery := fmt.Sprintf("%s %s", combined.Timetable.TripLabel.TripCategory, combined.Timetable.TripLabel.TripNumber) var suggestions []bahn.Suggestion if suggestions, err = apiClient.Suggestions(searchQuery, moment); err != nil { - log.Fatal(err) + log.Println(err) + return } var targetStation = timetable.Station if combined.Timetable.Departure != nil { @@ -213,7 +238,8 @@ func main() { for key, combined := range data { if combined.TrainLink != "" { if combined.HafasMessages, err = apiClient.HafasMessages(combined.TrainLink); err != nil { - log.Fatal(err) + log.Println(err) + return } } data[key] = combined @@ -225,11 +251,11 @@ func main() { } if err = returnJson(w, result); err != nil { - log.Fatal(err) + log.Println(err) return } }) - if err := http.ListenAndServe(":8080", nil); err != nil { + if err := http.ListenAndServe(*listen, nil); err != nil { log.Fatal(err) } } -- GitLab