fix(pkg/config): use storage endpoints

changes:
- Only one storage endpoint can be defined. This consists of a URL which
  can be used to specify whether the data is to be stored in a file or
  in a database.
This commit is contained in:
2019-12-07 16:53:49 +01:00
parent afe55b3d33
commit dbef4f8241
30 changed files with 959 additions and 882 deletions

View File

@ -3,8 +3,8 @@ package db
import (
"database/sql"
"fmt"
"net/url"
"github.com/go-flucky/flucky/pkg/config"
_ "github.com/lib/pq"
"github.com/volker-raschek/go-logger/pkg/logger"
)
@ -13,15 +13,14 @@ var (
flogger = logger.NewSilentLogger()
)
func New(databaseSettings *config.DatabaseSettings) (Database, error) {
connStr := fmt.Sprintf("%v://%v:%v@%v:%v/%v?sslmode=disable", databaseSettings.Vendor.String(), databaseSettings.User, databaseSettings.Password, databaseSettings.Host, databaseSettings.Port, databaseSettings.Database)
newDBO, err := sql.Open(databaseSettings.Vendor.String(), connStr)
func New(storageEndpoint *url.URL) (Database, error) {
newDBO, err := sql.Open(storageEndpoint.Scheme, storageEndpoint.String())
if err != nil {
return nil, err
}
switch databaseSettings.Vendor {
case config.VendorPostgreSQL:
switch storageEndpoint.Scheme {
case "postgres":
return &Postgres{
dbo: newDBO,
}, nil

View File

@ -29,6 +29,7 @@ type Database interface {
SelectDeviceByID(ctx context.Context, id string) (*types.Device, error)
SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error)
SelectHumidityByID(ctx context.Context, id string) (*types.MeasuredValue, error)
SelectMeasuredValues(ctx context.Context) ([]*types.MeasuredValue, error)
SelectMeasuredValuesByIDAndType(ctx context.Context, id string, valueType types.MeasuredValueType) (*types.MeasuredValue, error)
SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error)
SelectPressureByID(ctx context.Context, id string) (*types.MeasuredValue, error)

View File

@ -11,6 +11,8 @@ import (
"github.com/Masterminds/semver"
"github.com/go-flucky/flucky/pkg/types"
// PostgreSQL lib
_ "github.com/lib/pq"
)
@ -18,17 +20,19 @@ var (
postgresAssetPath = "pkg/storage/db/sql/psql"
)
// Postgres provide functions to interact with a postgres database
type Postgres struct {
dbo *sql.DB
}
// Close the database connection
func (p *Postgres) Close() error {
return p.dbo.Close()
}
// Schema create or upgrade database schema to the version of the flucky binary
// Schema create or updates the database schema to a given version. Normally the
// version is the same as the flucky binary version.
func (p *Postgres) Schema(ctx context.Context, version *semver.Version) error {
schemaFunc := func(ctx context.Context, fromVersion *semver.Version, toVersion *semver.Version) error {
assetPath := fmt.Sprintf("%v/schema", postgresAssetPath)
@ -94,9 +98,10 @@ func (p *Postgres) Schema(ctx context.Context, version *semver.Version) error {
}
return schemaFunc(ctx, fromVersion, version)
}
}
// DeleteDevices delete recursively all spicified devices, including sensors and
// all measured values
func (p *Postgres) DeleteDevices(ctx context.Context, devices []*types.Device) error {
asset := fmt.Sprintf("%v/deleteDevice.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
@ -121,6 +126,8 @@ func (p *Postgres) DeleteDevices(ctx context.Context, devices []*types.Device) e
return nil
}
// DeleteSensors delete recusively all spicified sensors, including all measured
// values
func (p *Postgres) DeleteSensors(ctx context.Context, sensors []*types.Sensor) error {
asset := fmt.Sprintf("%v/deleteSensor.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
@ -145,6 +152,7 @@ func (p *Postgres) DeleteSensors(ctx context.Context, sensors []*types.Sensor) e
return nil
}
// DeleteMeasuredValues delete all spicified measured values
func (p *Postgres) DeleteMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error {
deleteMeasuredValue := func(ctx context.Context, query string, measuredValues []*types.MeasuredValue) error {
@ -214,6 +222,7 @@ func (p *Postgres) DeleteMeasuredValues(ctx context.Context, measuredValues []*t
return nil
}
// InsertDevices insert all specified devices into the database
func (p *Postgres) InsertDevices(ctx context.Context, devices []*types.Device) error {
asset := fmt.Sprintf("%v/insertDevice.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
@ -238,6 +247,7 @@ func (p *Postgres) InsertDevices(ctx context.Context, devices []*types.Device) e
return nil
}
// InsertInfo insert into the database additional informations, based on a key value syntax
func (p *Postgres) InsertInfo(ctx context.Context, key string, value string) error {
asset := fmt.Sprintf("%v/insertInfo.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
@ -260,6 +270,7 @@ func (p *Postgres) InsertInfo(ctx context.Context, key string, value string) err
return nil
}
// InsertMeasuredValues insert all specified measured values into the database
func (p *Postgres) InsertMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error {
sortedMeasuredValueTypes := make(map[types.MeasuredValueType][]*types.MeasuredValue)
@ -343,7 +354,7 @@ func (p *Postgres) insertPressure(ctx context.Context, measuredValues []*types.M
_, err := stmt.ExecContext(ctx, &measuredValue.ID, &measuredValue.Value, &measuredValue.FromDate, &measuredValue.TillDate, &measuredValue.SensorID, &measuredValue.CreationDate, &measuredValue.UpdateDate)
if err != nil {
return fmt.Errorf("%v: %v", errorStatementExecute, err)
return fmt.Errorf("%v: Measured value id %v: %v", errorStatementExecute, measuredValue.ID, err)
}
}
return nil
@ -372,12 +383,13 @@ func (p *Postgres) insertTemperature(ctx context.Context, measuredValues []*type
_, err := stmt.ExecContext(ctx, &measuredValue.ID, &measuredValue.Value, &measuredValue.FromDate, &measuredValue.TillDate, &measuredValue.SensorID, &measuredValue.CreationDate, &measuredValue.UpdateDate)
if err != nil {
return fmt.Errorf("%v: %v", errorStatementExecute, err)
return fmt.Errorf("%v: Measured value id %v: %v", errorStatementExecute, measuredValue.ID, err)
}
}
return nil
}
// InsertSensors insert all specified sensors into the database
func (p *Postgres) InsertSensors(ctx context.Context, sensors []*types.Sensor) error {
asset := fmt.Sprintf("%v/insertSensor.sql", postgresAssetPath)
@ -403,6 +415,7 @@ func (p *Postgres) InsertSensors(ctx context.Context, sensors []*types.Sensor) e
return nil
}
// SelectDeviceByID returns a device by his ID
func (p *Postgres) SelectDeviceByID(ctx context.Context, id string) (*types.Device, error) {
asset := fmt.Sprintf("%v/selectDeviceByID.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
@ -430,6 +443,7 @@ func (p *Postgres) SelectDeviceByID(ctx context.Context, id string) (*types.Devi
return device, nil
}
// SelectInfo returns the value of a key stored in the database
func (p *Postgres) SelectInfo(ctx context.Context, key string) (string, error) {
asset := fmt.Sprintf("%v/selectInfo.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
@ -457,6 +471,7 @@ func (p *Postgres) SelectInfo(ctx context.Context, key string) (string, error) {
return value, nil
}
// SelectHumidities returns humidity values
func (p *Postgres) SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error) {
queryFile := fmt.Sprintf("%v/selectHumidities.sql", postgresAssetPath)
measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeHumidity, queryFile, nil)
@ -466,6 +481,7 @@ func (p *Postgres) SelectHumidities(ctx context.Context) ([]*types.MeasuredValue
return measuredValues, nil
}
// SelectHumidityByID returns a humidity value by his ID
func (p *Postgres) SelectHumidityByID(ctx context.Context, id string) (*types.MeasuredValue, error) {
queryFile := fmt.Sprintf("%v/selectHumidityByID.sql", postgresAssetPath)
args := []interface{}{id}
@ -481,6 +497,30 @@ func (p *Postgres) SelectHumidityByID(ctx context.Context, id string) (*types.Me
return measuredValues[0], nil
}
// SelectMeasuredValues returns all measured values about all diffferent value
// types
func (p *Postgres) SelectMeasuredValues(ctx context.Context) ([]*types.MeasuredValue, error) {
measuredValues := make([]*types.MeasuredValue, 0)
// MeasuredValue query functions
queryFunctions := []func(ctx context.Context) ([]*types.MeasuredValue, error){
p.SelectHumidities,
p.SelectPressures,
p.SelectTemperatures,
}
// Execute query functions
for _, queryFunction := range queryFunctions {
queriedMeasuredValues, err := queryFunction(ctx)
if err != nil {
return nil, err
}
measuredValues = append(measuredValues, queriedMeasuredValues...)
}
return measuredValues, nil
}
// SelectMeasuredValuesByIDAndType returns a measured value by his ID and type
func (p *Postgres) SelectMeasuredValuesByIDAndType(ctx context.Context, id string, valueType types.MeasuredValueType) (*types.MeasuredValue, error) {
switch valueType {
case types.MeasuredValueTypeHumidity:
@ -494,6 +534,7 @@ func (p *Postgres) SelectMeasuredValuesByIDAndType(ctx context.Context, id strin
}
}
// SelectPressures returns pressure values
func (p *Postgres) SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error) {
queryFile := fmt.Sprintf("%v/selectPressures.sql", postgresAssetPath)
measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypePressure, queryFile, nil)
@ -503,6 +544,7 @@ func (p *Postgres) SelectPressures(ctx context.Context) ([]*types.MeasuredValue,
return measuredValues, nil
}
// SelectPressureByID returns a pressure value by his ID
func (p *Postgres) SelectPressureByID(ctx context.Context, id string) (*types.MeasuredValue, error) {
queryFile := fmt.Sprintf("%v/selectPressureByID.sql", postgresAssetPath)
args := []interface{}{id}
@ -518,6 +560,7 @@ func (p *Postgres) SelectPressureByID(ctx context.Context, id string) (*types.Me
return measuredValues[0], nil
}
// SelectSensorByID returns a sensor by his ID
func (p *Postgres) SelectSensorByID(ctx context.Context, id string) (*types.Sensor, error) {
asset := fmt.Sprintf("%v/selectSensorByID.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
@ -545,6 +588,7 @@ func (p *Postgres) SelectSensorByID(ctx context.Context, id string) (*types.Sens
return sensor, nil
}
// SelectTemperatures returns temperature values
func (p *Postgres) SelectTemperatures(ctx context.Context) ([]*types.MeasuredValue, error) {
queryFile := fmt.Sprintf("%v/selectTemperatures.sql", postgresAssetPath)
measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeTemperature, queryFile, nil)
@ -554,6 +598,7 @@ func (p *Postgres) SelectTemperatures(ctx context.Context) ([]*types.MeasuredVal
return measuredValues, nil
}
// SelectTemperatureByID returns a temperature value by his ID
func (p *Postgres) SelectTemperatureByID(ctx context.Context, id string) (*types.MeasuredValue, error) {
queryFile := fmt.Sprintf("%v/selectTemperatureByID.sql", postgresAssetPath)
args := []interface{}{id}
@ -597,10 +642,12 @@ func (p *Postgres) selectMeasuredValues(ctx context.Context, measuredValueType t
return measuredValues, nil
}
// UpdateDevices updates all specified devices into the database
func (p *Postgres) UpdateDevices(ctx context.Context, devices []*types.Device) error {
return nil
}
// UpdateInfo updates the value which is stored to a key in the database
func (p *Postgres) UpdateInfo(ctx context.Context, key string, value string) error {
asset := fmt.Sprintf("%v/updateInfo.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
@ -623,10 +670,12 @@ func (p *Postgres) UpdateInfo(ctx context.Context, key string, value string) err
return nil
}
// UpdateMeasuredValues updates the measured values which are stored in the database
func (p *Postgres) UpdateMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error {
return nil
}
// UpdateSensors updates the sensors which are stored in the database
func (p *Postgres) UpdateSensors(ctx context.Context, sensots []*types.Sensor) error {
return nil
}

View File

@ -2,11 +2,11 @@ package db_test
import (
"context"
"net/url"
"strings"
"testing"
"github.com/Masterminds/semver"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/storage/db"
"github.com/go-flucky/flucky/pkg/types"
"github.com/go-flucky/flucky/test/goldenfiles"
@ -23,14 +23,7 @@ var (
postgresContainerImage string = "docker.io/postgres/postgres"
postgresSettings = &config.DatabaseSettings{
Vendor: config.VendorPostgreSQL,
Host: "localhost",
Port: "5432",
User: "postgres",
Password: "postgres",
Database: "postgres",
}
storageEndpointString string = "postgres://flucky:flucky@markus-pc.trier.cryptic.systems/postgres?sslmode=disable"
goldenDevicesFilePath string = "test/goldenfiles/json/goldenDevices.json"
goldenSensorsFilePath string = "test/goldenfiles/json/goldenSensors.json"
@ -81,7 +74,10 @@ func TestPostgres(t *testing.T) {
load(t)
db, err := db.New(postgresSettings)
storageEndpoint, err := url.Parse(storageEndpointString)
require.Nil(err)
db, err := db.New(storageEndpoint)
database = db
require.Nil(err)

View File

@ -0,0 +1,3 @@
ALTER TABLE humidities ALTER COLUMN creation_date DROP NOT NULL;
ALTER TABLE pressures ALTER COLUMN creation_date DROP NOT NULL;
ALTER TABLE temperatures ALTER COLUMN creation_date DROP NOT NULL;