about summary refs log tree commit diff stats
path: root/cache.go
diff options
context:
space:
mode:
authorBen Morrison <ben@gbmor.dev>2019-05-21 04:13:21 -0400
committerBen Morrison <ben@gbmor.dev>2019-05-21 04:13:21 -0400
commitc896e6b85ff32c3c0c45336de8b75752a31574ca (patch)
treef9bbacbf49949e4b86adf676b33decbddec40fef /cache.go
parentbd23ef0959496aba4c6fc8ca2b3969bbf17aa9d5 (diff)
downloadgetwtxt-c896e6b85ff32c3c0c45336de8b75752a31574ca.tar.gz
database push/pull functions
Diffstat (limited to 'cache.go')
-rw-r--r--cache.go159
1 files changed, 159 insertions, 0 deletions
diff --git a/cache.go b/cache.go
new file mode 100644
index 0000000..253de98
--- /dev/null
+++ b/cache.go
@@ -0,0 +1,159 @@
+package main
+
+import (
+	"log"
+	"reflect"
+	"strings"
+	"time"
+
+	"github.com/getwtxt/registry"
+	"github.com/syndtr/goleveldb/leveldb"
+)
+
+// checks if it's time to refresh the cache or not
+func checkCacheTime() bool {
+	return time.Since(confObj.lastCache) > confObj.cacheInterval
+}
+
+// checks if it's time to push the cache to the database
+func checkDBtime() bool {
+	return time.Since(confObj.lastPush) > confObj.dbInterval
+}
+
+// launched by init as a goroutine to constantly watch
+// for the update interval to pass
+func cacheAndPush() {
+	for {
+		if checkCacheTime() {
+			refreshCache()
+		}
+		if checkDBtime() {
+			if err := pushDatabase(); err != nil {
+				log.Printf("Error pushing cache to database: %v\n", err)
+			}
+		}
+	}
+}
+
+// refreshes the cache
+func refreshCache() {
+
+	for k := range twtxtCache.Reg {
+		err := twtxtCache.UpdateUser(k)
+		if err != nil {
+			log.Printf("%v\n", err)
+			continue
+		}
+	}
+
+	for _, v := range remoteRegistries.List {
+		err := twtxtCache.ScrapeRemoteRegistry(v)
+		if err != nil {
+			log.Printf("Error while refreshing local copy of remote registry user data: %v\n", err)
+		}
+	}
+	confObj.mu.Lock()
+	confObj.lastCache = time.Now()
+	confObj.mu.Unlock()
+}
+
+// pushes the registry's cache data to a local
+// database for safe keeping
+func pushDatabase() error {
+	db := <-dbChan
+	twtxtCache.Mu.RLock()
+
+	// create a batch write job so it can
+	// be done at one time rather than
+	// per value
+	var dbBasket *leveldb.Batch
+	for k, v := range twtxtCache.Reg {
+		dbBasket.Put([]byte(k+".Nick"), []byte(v.Nick))
+		dbBasket.Put([]byte(k+".URL"), []byte(v.URL))
+		dbBasket.Put([]byte(k+".IP"), []byte(v.IP))
+		dbBasket.Put([]byte(k+".Date"), []byte(v.Date))
+		for i, e := range v.Status {
+			dbBasket.Put([]byte(k+".Status."+i.String()), []byte(e))
+		}
+	}
+
+	// save our list of remote registries to scrape
+	for k, v := range remoteRegistries.List {
+		dbBasket.Put([]byte("remote."+string(k)), []byte(v))
+	}
+
+	// execute the batch job
+	if err := db.Write(dbBasket, nil); err != nil {
+		return err
+	}
+
+	twtxtCache.Mu.RUnlock()
+	dbChan <- db
+
+	// update the last push time
+	confObj.mu.Lock()
+	confObj.lastPush = time.Now()
+	confObj.mu.Unlock()
+
+	return nil
+}
+
+// pulls registry data from the DB on startup
+func pullDatabase() {
+	db := <-dbChan
+
+	iter := db.NewIterator(nil, nil)
+
+	for iter.Next() {
+		key := iter.Key()
+		val := iter.Value()
+
+		split := strings.Split(string(key), ".")
+		urls := string(split[0])
+		field := string(split[1])
+		data := registry.NewUserData()
+
+		twtxtCache.Mu.RLock()
+		if _, ok := twtxtCache.Reg[urls]; ok {
+			data = twtxtCache.Reg[urls]
+		}
+		twtxtCache.Mu.RUnlock()
+
+		ref := reflect.ValueOf(data).Elem()
+
+		if field != "Status" && urls != "remote" {
+			for i := 0; i < ref.NumField(); i++ {
+
+				f := ref.Field(i)
+				if f.String() == field {
+					f.Set(reflect.ValueOf(val))
+					break
+				}
+			}
+		} else if field == "Status" && urls != "remote" {
+
+			thetime, err := time.Parse("RFC3339", split[2])
+			if err != nil {
+				log.Printf("%v\n", err)
+			}
+			data.Status[thetime] = string(val)
+
+		} else {
+			remoteRegistries.Mu.Lock()
+			remoteRegistries.List = append(remoteRegistries.List, string(val))
+			remoteRegistries.Mu.Unlock()
+		}
+
+		twtxtCache.Mu.Lock()
+		twtxtCache.Reg[urls] = data
+		twtxtCache.Mu.Unlock()
+	}
+
+	iter.Release()
+	err := iter.Error()
+	if err != nil {
+		log.Printf("Error while pulling DB into registry cache: %v\n", err)
+	}
+
+	dbChan <- db
+}