diff pkg/models/octreecache.go @ 723:7eed7ff3142d

Started with model to load octrees from database.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 21 Sep 2018 18:32:41 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg/models/octreecache.go	Fri Sep 21 18:32:41 2018 +0200
@@ -0,0 +1,103 @@
+package models
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	"time"
+)
+
+type (
+	octreeCacheKey struct {
+		date       time.Time
+		bottleneck string
+	}
+
+	octreeCacheEntry struct {
+		checksum string
+		tree     *Octree
+		access   time.Time
+	}
+	octreeCache struct {
+		sync.Mutex
+		entries map[octreeCacheKey]*octreeCacheEntry
+	}
+)
+
+const (
+	cleanupOctreeCacheSleep = 6 * time.Minute
+	maxOctreeCacheAge       = 5 * time.Minute
+	maxOctreeCacheEntries   = 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 OctreeCache = octreeCache{
+	entries: map[octreeCacheKey]*octreeCacheEntry{},
+}
+
+func init() {
+	go OctreeCache.background()
+}
+
+func (oc *octreeCache) background() {
+	for {
+		time.Sleep(cleanupOctreeCacheSleep)
+		oc.cleanup()
+	}
+}
+
+func (oc *octreeCache) cleanup() {
+	oc.Lock()
+	defer oc.Unlock()
+	good := time.Now().Add(-maxOctreeCacheAge)
+	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 := octreeCacheKey{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
+}