commit 3f892c246b1f5257a2d9829c9ffa99f4d997e96c
parent c3e836b084fe6e56f6a3ca3f2355e7e21dc36b1d
Author: Chris Bracken <chris@bracken.jp>
Date: Thu, 11 Nov 2021 09:57:52 -0800
Extract data storage logic to storage package
Extracts all code related to data storage into a new storage package.
This allows us to swap out the data storage layer in tests or have
different storage providers; e.g. postgres, sqlite, flat file.
Diffstat:
2 files changed, 54 insertions(+), 31 deletions(-)
diff --git a/main.go b/main.go
@@ -1,7 +1,6 @@
package main
import (
- "database/sql"
"encoding/json"
"fmt"
"io"
@@ -11,40 +10,16 @@ import (
"time"
"git.bracken.jp/tempestas/airrohr"
+ "git.bracken.jp/tempestas/storage"
_ "github.com/lib/pq"
"goji.io"
"goji.io/pat"
)
-const (
- INSERT_REPORT = "INSERT INTO " +
- "sensor_data(sensor_id, sw_version, reading_time, reading_type, reading_value) " +
- "VALUES($1, $2, $3, $4, $5)"
-)
-
var (
- db *sql.DB
+ ds *storage.DataStore
)
-func setupDB() *sql.DB {
- dbinfo := os.ExpandEnv("user=$TEMPESTAS_USER password=$TEMPESTAS_PASS dbname=$TEMPESTAS_DB sslmode=disable")
- db, err := sql.Open("postgres", dbinfo)
- if err != nil {
- panic("Error connecting to database")
- }
- return db
-}
-
-func storeReport(report *airrohr.Report, t time.Time) {
- for _, v := range report.Values {
- _, err := db.Exec(INSERT_REPORT, report.SensorId, report.SoftwareVersion, t, v.Type, v.Value)
- if err != nil {
- fmt.Println("Error: failed to write sensor data")
- fmt.Println(err)
- }
- }
-}
-
func PostAirrohr(w http.ResponseWriter, r *http.Request) {
contentType := r.Header.Get("Content-Type")
if contentType != "application/json" {
@@ -61,7 +36,7 @@ func PostAirrohr(w http.ResponseWriter, r *http.Request) {
}
t := time.Now().UTC()
fmt.Println(t.String() + " Report received from sensor " + report.SensorId)
- storeReport(&report, t)
+ ds.StoreReport(&report, t)
errorResponse(w, "Success", http.StatusOK)
}
@@ -76,12 +51,14 @@ func errorResponse(w http.ResponseWriter, message string, httpStatusCode int) {
func main() {
fmt.Println("Initializing database")
- db = setupDB()
- defer db.Close()
+ dbname := os.Getenv("TEMPESTAS_DB")
+ dbuser := os.Getenv("TEMPESTAS_USER")
+ dbpass := os.Getenv("TEMPESTAS_PASS")
+ ds := storage.Connect(dbname, dbuser, dbpass)
+ defer ds.Close()
fmt.Println("Waiting for requests")
mux := goji.NewMux()
mux.HandleFunc(pat.Post("/sensor/airrohr/"), PostAirrohr)
log.Fatal(http.ListenAndServe(":8080", mux))
-
}
diff --git a/storage/storage.go b/storage/storage.go
@@ -0,0 +1,46 @@
+package storage
+
+import (
+ "database/sql"
+ "fmt"
+ "time"
+
+ "git.bracken.jp/tempestas/airrohr"
+)
+
+const (
+ INSERT_REPORT = "INSERT INTO " +
+ "sensor_data(sensor_id, sw_version, reading_time, reading_type, reading_value) " +
+ "VALUES($1, $2, $3, $4, $5)"
+)
+
+type DataStore struct {
+ db *sql.DB
+}
+
+func Connect(dbname string, user string, password string) *DataStore {
+ var s = new(DataStore)
+ var err error
+ dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", user, password, dbname)
+ if s.db, err = sql.Open("postgres", dbinfo); err != nil {
+ panic("Error connecting to database")
+ }
+ return s
+}
+
+func (s DataStore) Close() {
+ s.db.Close()
+}
+
+func (s DataStore) StoreReport(report *airrohr.Report, t time.Time) {
+ if s.db == nil {
+ panic("Not connected to database")
+ }
+ for _, v := range report.Values {
+ _, err := s.db.Exec(INSERT_REPORT, report.SensorId, report.SoftwareVersion, t, v.Type, v.Value)
+ if err != nil {
+ fmt.Println("Error: failed to write sensor data")
+ fmt.Println(err)
+ }
+ }
+}