about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBen Morrison <ben@gbmor.dev>2019-06-06 16:07:53 -0400
committerBen Morrison <ben@gbmor.dev>2019-06-08 02:29:20 -0400
commite9d4a6b0e8624c6425d467f0efe14be1bc683bd9 (patch)
tree02b928c2c8fe28153980e6612c3349104091c083
parent6749dc4d215dd60900f0c1187ba20031ccdc4f85 (diff)
downloadgetwtxt-e9d4a6b0e8624c6425d467f0efe14be1bc683bd9.tar.gz
database refs and static assets concurrency-safe
-rw-r--r--svc/cache.go7
-rw-r--r--svc/db.go28
-rw-r--r--svc/handlers.go57
3 files changed, 64 insertions, 28 deletions
diff --git a/svc/cache.go b/svc/cache.go
index db427db..6b50a0e 100644
--- a/svc/cache.go
+++ b/svc/cache.go
@@ -18,6 +18,7 @@ type RemoteRegistries struct {
 }
 
 type staticAssets struct {
+	mu       sync.RWMutex
 	index    []byte
 	indexMod time.Time
 	css      []byte
@@ -98,8 +99,10 @@ func pingAssets() {
 		log.Printf("%v\n", err.Error())
 	}
 
+	staticCache.mu.RLock()
 	indexMod := staticCache.indexMod
 	cssMod := staticCache.cssMod
+	staticCache.mu.RUnlock()
 
 	if !indexMod.Equal(indexStat.ModTime()) {
 		tmpls = initTemplates()
@@ -114,8 +117,10 @@ func pingAssets() {
 			log.Printf("%v\n", err.Error())
 		}
 
+		staticCache.mu.Lock()
 		staticCache.index = buf.Bytes()
 		staticCache.indexMod = indexStat.ModTime()
+		staticCache.mu.Unlock()
 	}
 
 	if !cssMod.Equal(cssStat.ModTime()) {
@@ -125,7 +130,9 @@ func pingAssets() {
 			log.Printf("%v\n", err.Error())
 		}
 
+		staticCache.mu.Lock()
 		staticCache.css = css
 		staticCache.cssMod = cssStat.ModTime()
+		staticCache.mu.Unlock()
 	}
 }
diff --git a/svc/db.go b/svc/db.go
index 0bb96ee..e0c2690 100644
--- a/svc/db.go
+++ b/svc/db.go
@@ -11,6 +11,11 @@ import (
 	"github.com/syndtr/goleveldb/leveldb"
 )
 
+type dbase interface {
+	push() error
+	pull()
+}
+
 type dbLevel struct {
 	db *leveldb.DB
 }
@@ -19,9 +24,8 @@ type dbSqlite struct {
 	db *sql.DB
 }
 
-type dbase interface {
-	push() error
-	pull()
+type dbPostgres struct {
+	db *sql.DB
 }
 
 // Pull DB data into cache, if available.
@@ -41,6 +45,10 @@ func initDatabase() {
 		var lite *sql.DB
 		db = &dbSqlite{db: lite}
 
+	case "postgres":
+		var pg *sql.DB
+		db = &dbPostgres{db: pg}
+
 	}
 	confObj.Mu.RUnlock()
 
@@ -65,15 +73,16 @@ func dbTimer() bool {
 // database for safe keeping.
 func pushDB() error {
 	db := <-dbChan
+	err := db.push()
 	dbChan <- db
 
-	return db.push()
+	return err
 }
 
 func pullDB() {
 	db := <-dbChan
-	dbChan <- db
 	db.pull()
+	dbChan <- db
 }
 
 func (lvl dbLevel) push() error {
@@ -176,3 +185,12 @@ func (lite dbSqlite) push() error {
 func (lite dbSqlite) pull() {
 
 }
+
+func (pg dbPostgres) push() error {
+
+	return nil
+}
+
+func (pg dbPostgres) pull() {
+
+}
diff --git a/svc/handlers.go b/svc/handlers.go
index 7f7c730..3dcb84f 100644
--- a/svc/handlers.go
+++ b/svc/handlers.go
@@ -3,27 +3,59 @@ package svc // import "github.com/getwtxt/getwtxt/svc"
 import (
 	"crypto/sha256"
 	"fmt"
+	"log"
 	"net/http"
 	"strconv"
+	"time"
 
 	"github.com/getwtxt/registry"
 	"github.com/gorilla/mux"
 )
 
+func getEtag(modtime time.Time) string {
+	shabytes, err := modtime.MarshalText()
+	if err != nil {
+		log.Printf("%v\n", err.Error())
+	}
+	return fmt.Sprintf("%x", sha256.Sum256(shabytes))
+}
+
 // handles "/"
 func indexHandler(w http.ResponseWriter, r *http.Request) {
 
 	pingAssets()
 
-	etag := fmt.Sprintf("%x", sha256.Sum256([]byte(staticCache.indexMod.String())))
-
 	// Take the hex-encoded sha256 sum of the index template's mod time
 	// to send as an ETag. If an error occurred when grabbing the file info,
 	// the ETag will be empty.
+	staticCache.mu.RLock()
+	etag := getEtag(staticCache.indexMod)
 	w.Header().Set("ETag", "\""+etag+"\"")
 	w.Header().Set("Content-Type", htmlutf8)
 
 	_, err := w.Write(staticCache.index)
+	staticCache.mu.RUnlock()
+	if err != nil {
+		log500(w, r, err)
+		return
+	}
+
+	log200(r)
+}
+
+// Serving the stylesheet virtually because
+// files aren't served directly in getwtxt.
+func cssHandler(w http.ResponseWriter, r *http.Request) {
+
+	pingAssets()
+
+	staticCache.mu.RLock()
+	etag := getEtag(staticCache.cssMod)
+	w.Header().Set("ETag", "\""+etag+"\"")
+	w.Header().Set("Content-Type", cssutf8)
+
+	_, err := w.Write(staticCache.css)
+	staticCache.mu.RUnlock()
 	if err != nil {
 		log500(w, r, err)
 		return
@@ -183,24 +215,3 @@ func apiTagsHandler(w http.ResponseWriter, r *http.Request) {
 
 	log200(r)
 }
-
-// Serving the stylesheet virtually because
-// files aren't served directly in getwtxt.
-func cssHandler(w http.ResponseWriter, r *http.Request) {
-
-	// Sending the sha256 sum of the modtime in hexadecimal for the ETag header
-	etag := fmt.Sprintf("%x", sha256.Sum256([]byte(staticCache.cssMod.String())))
-
-	w.Header().Set("ETag", "\""+etag+"\"")
-	w.Header().Set("Content-Type", cssutf8)
-
-	pingAssets()
-
-	n, err := w.Write(staticCache.css)
-	if err != nil || n == 0 {
-		log500(w, r, err)
-		return
-	}
-
-	log200(r)
-}