Mercurial > gemma
diff pkg/octree/cache.go @ 724:6ab0c170e5b8
Moved octree stuff to own package.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sat, 22 Sep 2018 09:36:12 +0200 |
parents | pkg/models/octreecache.go@7eed7ff3142d |
children | e0437ec46798 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/octree/cache.go Sat Sep 22 09:36:12 2018 +0200 @@ -0,0 +1,103 @@ +package octree + +import ( + "context" + "database/sql" + "sync" + "time" +) + +type ( + cacheKey struct { + date time.Time + bottleneck string + } + + cacheEntry struct { + checksum string + tree *Octree + access time.Time + } + OctreeCache struct { + sync.Mutex + entries map[cacheKey]*cacheEntry + } +) + +const ( + cleanupCacheSleep = 6 * time.Minute + maxCacheAge = 5 * time.Minute + maxCacheEntries = 4 +) + +const ( + fetchOctreeSQL = ` +SELECT checksum, octree_index +FROM waterway.octrees ot +JOIN waterway.sounding_results sr ON ot.sounding_result_id = sr.id +WHERE sr.bottleneck_id = $1 AND sr.date_info = $2::date +` + checkOctreeSQL = ` +SELECT CASE + WHEN checksum = $3 THEN NULL + ELSE ot.octree_index + END +FROM waterway.octrees ot +JOIN waterway.sounding_results sr ON ot.sounding_result_id = sr.id +WHERE sr.bottleneck_id = $1 AND sr.date_info = $2::date +` +) + +var Cache = OctreeCache{ + entries: map[cacheKey]*cacheEntry{}, +} + +func init() { + go Cache.background() +} + +func (oc *OctreeCache) background() { + for { + time.Sleep(cleanupCacheSleep) + oc.cleanup() + } +} + +func (oc *OctreeCache) cleanup() { + oc.Lock() + defer oc.Unlock() + good := time.Now().Add(-maxCacheAge) + for k, v := range oc.entries { + if v.access.Before(good) { + delete(oc.entries, k) + } + } +} + +func (oc *OctreeCache) Get( + bottleneck string, date time.Time, + conn *sql.Conn, ctx context.Context, +) (*Octree, error) { + oc.Lock() + defer oc.Unlock() + + key := cacheKey{date, bottleneck} + entry := oc.entries[key] + if entry == nil { + // fetch from database + var data []byte + err := conn.QueryRowContext(ctx, fetchOctreeSQL, bottleneck, date).Scan(&data) + switch { + case err == sql.ErrNoRows: + return nil, nil + case err != nil: + return nil, err + } + // TODO: Deserialize! + } else { + // check if we are not outdated. + // TODO: Implement me! + } + + return nil, nil +}