summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBen Morrison <ben@gbmor.dev>2019-05-21 16:04:10 -0400
committerBen Morrison <ben@gbmor.dev>2019-05-21 16:04:10 -0400
commitb29e1c163f3cc88037f301c1cc1d71c7707ee64f (patch)
treeb06e51c3e27a8fb70f3801a27a957e5f7cae4bcb
parent137e237b17b770e9697e7367c1ee01f4f3bb5717 (diff)
downloadgetwtxt-b29e1c163f3cc88037f301c1cc1d71c7707ee64f.tar.gz
review of db functions
-rw-r--r--cache.go90
-rw-r--r--init.go16
2 files changed, 68 insertions, 38 deletions
diff --git a/cache.go b/cache.go
index 253de98..be3d7d3 100644
--- a/cache.go
+++ b/cache.go
@@ -10,18 +10,20 @@ import (
 	"github.com/syndtr/goleveldb/leveldb"
 )
 
-// checks if it's time to refresh the cache or not
+// Checks whether it's time to refresh
+// the cache.
 func checkCacheTime() bool {
 	return time.Since(confObj.lastCache) > confObj.cacheInterval
 }
 
-// checks if it's time to push the cache to the database
+// Checks whether 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
+// Launched by init as a goroutine to constantly watch
+// for the update interval to pass.
 func cacheAndPush() {
 	for {
 		if checkCacheTime() {
@@ -35,9 +37,11 @@ func cacheAndPush() {
 	}
 }
 
-// refreshes the cache
+// Refreshes the cache.
 func refreshCache() {
 
+	// Iterate over the registry and
+	// update each individual user.
 	for k := range twtxtCache.Reg {
 		err := twtxtCache.UpdateUser(k)
 		if err != nil {
@@ -46,6 +50,9 @@ func refreshCache() {
 		}
 	}
 
+	// Re-scrape all the remote registries
+	// to see if they have any new users
+	// to add locally.
 	for _, v := range remoteRegistries.List {
 		err := twtxtCache.ScrapeRemoteRegistry(v)
 		if err != nil {
@@ -57,40 +64,46 @@ func refreshCache() {
 	confObj.mu.Unlock()
 }
 
-// pushes the registry's cache data to a local
-// database for safe keeping
+// Pushes the registry's cache data to a local
+// database for safe keeping.
 func pushDatabase() error {
+	// Acquire the database from the aether.
+	// goleveldb is concurrency-safe, so we
+	// can immediately push it back into the
+	// channel for other functions to use.
 	db := <-dbChan
-	twtxtCache.Mu.RLock()
+	dbChan <- db
 
-	// create a batch write job so it can
+	// Create a batch write job so it can
 	// be done at one time rather than
-	// per value
+	// per entry.
+	twtxtCache.Mu.RLock()
 	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))
+		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))
+			rfc := i.Format(time.RFC3339)
+			dbBasket.Put([]byte(k+"*Status*"+rfc), []byte(e))
 		}
 	}
+	twtxtCache.Mu.RUnlock()
 
-	// save our list of remote registries to scrape
+	// Save our list of remote registries to scrape.
 	for k, v := range remoteRegistries.List {
-		dbBasket.Put([]byte("remote."+string(k)), []byte(v))
+		dbBasket.Put([]byte("remote*"+string(k)), []byte(v))
 	}
 
-	// execute the batch job
+	// Execute the batch job.
 	if err := db.Write(dbBasket, nil); err != nil {
 		return err
 	}
 
-	twtxtCache.Mu.RUnlock()
-	dbChan <- db
-
-	// update the last push time
+	// Update the last push time for
+	// our timer/watch function to
+	// reference.
 	confObj.mu.Lock()
 	confObj.lastPush = time.Now()
 	confObj.mu.Unlock()
@@ -98,29 +111,42 @@ func pushDatabase() error {
 	return nil
 }
 
-// pulls registry data from the DB on startup
+// Pulls registry data from the DB on startup.
+// Iterates over the database one entry at a time.
 func pullDatabase() {
+	// Acquire the database from the aether.
+	// goleveldb is concurrency-safe, so we
+	// can immediately push it back into the
+	// channel for other functions to use.
 	db := <-dbChan
+	dbChan <- db
 
 	iter := db.NewIterator(nil, nil)
 
+	// Read the database key-by-key
 	for iter.Next() {
 		key := iter.Key()
 		val := iter.Value()
 
-		split := strings.Split(string(key), ".")
+		split := strings.Split(string(key), "*")
 		urls := string(split[0])
 		field := string(split[1])
-		data := registry.NewUserData()
 
+		// Start with an empty Data struct. If
+		// there's already one in the cache, pull
+		// it and use it instead.
+		data := registry.NewUserData()
 		twtxtCache.Mu.RLock()
 		if _, ok := twtxtCache.Reg[urls]; ok {
 			data = twtxtCache.Reg[urls]
 		}
 		twtxtCache.Mu.RUnlock()
-
 		ref := reflect.ValueOf(data).Elem()
 
+		// Use reflection to find the right field
+		// in the Data struct. Once found, assign
+		// the value and break so the DB iteration
+		// can continue.
 		if field != "Status" && urls != "remote" {
 			for i := 0; i < ref.NumField(); i++ {
 
@@ -132,6 +158,9 @@ func pullDatabase() {
 			}
 		} else if field == "Status" && urls != "remote" {
 
+			// If we're looking at a Status entry in the DB,
+			// parse the time then add it to the TimeMap under
+			// data.Status
 			thetime, err := time.Parse("RFC3339", split[2])
 			if err != nil {
 				log.Printf("%v\n", err)
@@ -139,11 +168,18 @@ func pullDatabase() {
 			data.Status[thetime] = string(val)
 
 		} else {
+			// The third and final possibility is
+			// if we've come across an entry for
+			// a remote twtxt registry to scrape.
+			// If so, add it to our list.
 			remoteRegistries.Mu.Lock()
 			remoteRegistries.List = append(remoteRegistries.List, string(val))
 			remoteRegistries.Mu.Unlock()
+			continue
 		}
 
+		// Push the data struct (back) into
+		// the cache.
 		twtxtCache.Mu.Lock()
 		twtxtCache.Reg[urls] = data
 		twtxtCache.Mu.Unlock()
@@ -154,6 +190,4 @@ func pullDatabase() {
 	if err != nil {
 		log.Printf("Error while pulling DB into registry cache: %v\n", err)
 	}
-
-	dbChan <- db
 }
diff --git a/init.go b/init.go
index 6896a1a..639a78b 100644
--- a/init.go
+++ b/init.go
@@ -33,11 +33,6 @@ var closelog = make(chan bool, 1)
 // initialization
 var dbChan = make(chan *leveldb.DB, 1)
 
-// provides access to the database so it
-// can be closed outside of the init function's
-// scope.
-var dbCloseChan = make(chan *leveldb.DB, 1)
-
 // templates
 var tmpls *template.Template
 
@@ -54,7 +49,6 @@ func init() {
 	initLogging()
 	tmpls = initTemplates()
 	initDatabase()
-	go cacheAndPush()
 	watchForInterrupt()
 }
 
@@ -218,17 +212,19 @@ func initTemplates() *template.Template {
 	return template.Must(template.ParseFiles("assets/tmpl/index.html"))
 }
 
-// Pull DB data into cache, if available
+// Pull DB data into cache, if available.
 func initDatabase() {
 	db, err := leveldb.OpenFile(confObj.dbPath, nil)
 	if err != nil {
 		log.Fatalf("%v\n", err)
 	}
 
+	// Send the database reference into
+	// the aether.
 	dbChan <- db
-	dbCloseChan <- db
 
 	pullDatabase()
+	go cacheAndPush()
 }
 
 // Watch for SIGINT aka ^C
@@ -245,7 +241,7 @@ func watchForInterrupt() {
 
 			// Close the database cleanly
 			log.Printf("Closing database connection to %v...\n", confObj.dbPath)
-			db := <-dbCloseChan
+			db := <-dbChan
 			if err := db.Close(); err != nil {
 				log.Printf("%v\n", err)
 			}
@@ -256,7 +252,7 @@ func watchForInterrupt() {
 			}
 
 			confObj.mu.RUnlock()
-			close(dbCloseChan)
+			close(dbChan)
 			close(closelog)
 
 			// Let everything catch up