tempestas

A REST API for processing sensor.community data
git clone https://git.bracken.jp/tempestas.git
Log | Files | Refs | README | LICENSE

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:
Mmain.go | 39++++++++-------------------------------
Astorage/storage.go | 46++++++++++++++++++++++++++++++++++++++++++++++
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) + } + } +}