fix: new implementation

changes:
- Remove cli
  Some cli commands are not complete tested and are deprecated.

- Daemon
  - Old version has a very bad implementation of how to verify, if the
    device or the sensors are in the database insert. The current
    implementation can be improved but this one is betten then the old
    one.
  - Remove complete the cache store implementation. Use a normal array
    and query the length and capacity to determine how the array cache
    must be cleaned.

- Type
  Remove unused types and functions
This commit is contained in:
2020-05-03 14:04:08 +02:00
parent 84d052184e
commit fb8d4dd5eb
137 changed files with 658 additions and 14048 deletions

View File

@ -1,98 +0,0 @@
package daemon
import (
"context"
"net/url"
"sync"
"github.com/volker-raschek/flucky/pkg/storage"
"github.com/volker-raschek/flucky/pkg/storage/logfile"
"github.com/volker-raschek/flucky/pkg/types"
)
type cacheStore struct {
compression bool
cache []*types.MeasuredValue
mux *sync.Mutex
round float64
URL *url.URL
}
func (cs *cacheStore) Add(measuredValue *types.MeasuredValue) {
cs.mux.Lock()
defer cs.mux.Unlock()
cs.cache = append(cs.cache, measuredValue)
}
func (cs *cacheStore) Flush(measuredValue *types.MeasuredValue) *cacheStore {
cs.mux.Lock()
defer cs.mux.Unlock()
cs.cache = make([]*types.MeasuredValue, 0)
return cs
}
func (cs *cacheStore) Get(id string) *types.MeasuredValue {
cs.mux.Lock()
defer cs.mux.Unlock()
for _, measuredValue := range cs.cache {
if measuredValue.ID == id {
return measuredValue
}
}
return nil
}
func (cs *cacheStore) Size() int {
cs.mux.Lock()
defer cs.mux.Unlock()
return len(cs.cache)
}
func (cs *cacheStore) WriteToEndpoint() error {
cs.mux.Lock()
defer cs.mux.Unlock()
defer func() { cs.cache = make([]*types.MeasuredValue, 0) }()
switch cs.URL.Scheme {
case "file":
return cs.logfile()
case "postgres":
return cs.postgres()
}
return nil
}
func (cs *cacheStore) logfile() error {
newMeasuredValues := make([]*types.MeasuredValue, 0)
for _, measuredValue := range cs.cache {
newMeasuredValues = append(newMeasuredValues, measuredValue)
}
if cs.round != 0 {
storage.Round(newMeasuredValues, cs.round)
}
measuredLogfile := logfile.New(cs.URL.Path)
measuredValues, err := measuredLogfile.Read()
if err != nil {
return err
}
measuredValues = append(measuredValues, newMeasuredValues...)
if cs.compression {
measuredValues = storage.Compression(measuredValues)
}
err = measuredLogfile.Write(measuredValues)
if err != nil {
return err
}
return nil
}
func (cs *cacheStore) postgres() error {
ctx := context.Background()
return storage.Write(ctx, cs.cache, cs.URL)
}

View File

@ -2,81 +2,77 @@ package daemon
import (
"context"
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"github.com/volker-raschek/flucky/pkg/config"
"github.com/volker-raschek/flucky/pkg/sensor"
"github.com/volker-raschek/flucky/pkg/storage"
"github.com/volker-raschek/flucky/pkg/types"
"github.com/volker-raschek/go-logger/pkg/logger"
)
var (
flogger = logger.NewSilentLogger()
)
func Start(cnf *config.Config, flogger logger.Logger) error {
func SetLogger(logger logger.Logger) {
flogger = logger
}
sensors := make([]sensor.Sensor, 0)
for _, cnfSensor := range cnf.Sensors {
if !cnfSensor.Enabled {
continue
}
// Start the daemon
func Start(cnf *config.Configuration, cacheSize uint, compression bool, round float64) error {
sensor, err := sensor.New(cnfSensor)
if err != nil {
return err
}
sensors = append(sensors, sensor)
}
storageEndpointURL, err := cnf.GetStorageEndpointURL()
measuredValueChannel := make(chan *types.MeasuredValue, 0)
// load storage endpoint
storageEndpoint, err := storage.New(cnf.StorageEndpoint, flogger)
if err != nil {
return err
}
cache := &cacheStore{
compression: compression,
cache: make([]*types.MeasuredValue, 0),
mux: new(sync.Mutex),
round: round,
URL: storageEndpointURL,
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, os.Kill, syscall.SIGTERM)
// Collection
parentCtx := context.Background()
// Insert device if not exist
device, _ := storageEndpoint.SelectDevice(parentCtx, cnf.Device.ID)
if device == nil {
if err := storageEndpoint.InsertDevice(parentCtx, cnf.Device); err != nil {
return err
}
}
// Insert sensors if not exist
for _, cnfSensor := range cnf.Sensors {
sensor, _ := storageEndpoint.SelectSensor(parentCtx, cnfSensor.ID)
if sensor == nil {
if err := storageEndpoint.InsertSensor(parentCtx, cnfSensor); err != nil {
return err
}
}
}
// Context
parentCtx := context.Background()
ctx, cancel := context.WithCancel(parentCtx)
// channels
debugChannel := make(chan string, 0)
infoChannel := make(chan string, 0)
warnChannel := make(chan string, 0)
errorChannel := make(chan error, 0)
fatalChannel := make(chan error, 1)
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
measuredValueChannel := make(chan *types.MeasuredValue, 0)
// Info
flogger.Debug("Use compression: %v", compression)
flogger.Debug("Round values to: %v", round)
// Init semaphoreChannel
semaphoreChannels := make(map[string]chan struct{})
for _, sensor := range cnf.GetSensors(config.ENABLED) {
semaphoreChannels[sensor.GetID()] = make(chan struct{}, 1)
}
// Start producers
for _, s := range cnf.GetSensors(config.ENABLED) {
// start go routine for each sensor
for _, s := range sensors {
go func(sensor sensor.Sensor) {
// run forever
for {
select {
case <-ctx.Done():
return
case <-semaphoreChannels[sensor.GetID()]:
case <-sensor.GetTicker().C:
measuredValues, err := sensor.Read()
if err != nil {
errorChannel <- err
return
flogger.Error("%v", err)
continue
}
for _, measuredValue := range measuredValues {
measuredValueChannel <- measuredValue
@ -84,98 +80,36 @@ func Start(cnf *config.Configuration, cacheSize uint, compression bool, round fl
}
}
}(s)
// start ticker for each sensor
go func(sensor sensor.Sensor) {
for {
select {
case <-ctx.Done():
return
case <-sensor.GetTicker().C:
semaphoreChannels[sensor.GetID()] <- struct{}{}
}
}
}(s)
}
go func() {
for {
select {
case <-ctx.Done():
debugChannel <- fmt.Sprintf("Stop consumer of measured values: Closed context: %v", ctx.Err().Error())
return
case measuredValue := <-measuredValueChannel:
cache.Add(measuredValue)
debugChannel <- fmt.Sprintf("CacheStore ID: %v, Sensor ID: %v, Type: %v, Value: %v", cache.Size(), measuredValue.SensorID, measuredValue.ValueType, measuredValue.Value)
if cache.Size() >= int(cacheSize) {
debugChannel <- fmt.Sprint("Write cache into storage endpoint")
err := cache.WriteToEndpoint()
if err != nil {
errorChannel <- err
}
}
}
}
}()
measuredValues := make([]*types.MeasuredValue, 0, 10)
for {
select {
case debug, _ := <-debugChannel:
flogger.Debug("%v", debug)
case info, _ := <-infoChannel:
flogger.Info("%v", info)
case warn, _ := <-warnChannel:
flogger.Warn("%v", warn)
case err, _ := <-errorChannel:
flogger.Error("%v", err)
case fatal, _ := <-fatalChannel:
flogger.Fatal("Received a fatal error: %v", fatal)
case measuredValue := <-measuredValueChannel:
flogger.Debug("%v\t%v\t%v", measuredValue.ID, measuredValue.ValueType, measuredValue.Value)
measuredValues = append(measuredValues, measuredValue)
if cap(measuredValues) == len(measuredValues) {
flogger.Debug("Flush cache")
err := storageEndpoint.InsertMeasuredValues(ctx, measuredValues)
if err != nil {
flogger.Error("%v", err)
}
measuredValues = make([]*types.MeasuredValue, 0, 10)
}
case <-interruptChannel:
flogger.Debug("Write %v cached values into storage endpoint", cache.Size())
err := cache.WriteToEndpoint()
cancel()
close(measuredValueChannel)
err := storageEndpoint.InsertMeasuredValues(ctx, measuredValues)
if err != nil {
flogger.Error("%v", err)
}
flogger.Debug("Close context")
cancel()
flogger.Debug("Close channels")
close(debugChannel)
close(infoChannel)
close(warnChannel)
close(errorChannel)
close(interruptChannel)
return nil
break
}
}
return nil
}
// func checkDeviceInDatabase(ctx context.Context, device *types.Device, database db.Database) {
// _, err := database.SelectDeviceByID(ctx, device.ID)
// if err != nil {
// flogger.Debug("It's seems the current device is not registered in the database. Register the device now")
// err2 := database.InsertDevices(ctx, []*types.Device{device})
// if err2 != nil {
// flogger.Fatal("Can not register device into database: %v", err2)
// }
// flogger.Debug("Device successfully registered into the database")
// return
// }
// flogger.Debug("Device already registered into the database")
// }
// func checkSensorsInDatabase(ctx context.Context, sensors []*types.Sensor, database db.Database) {
// for _, sensor := range sensors {
// _, err := database.SelectSensorByID(ctx, sensor.ID)
// if err != nil {
// flogger.Debug("It's seems the sensor %v is not registered in the database. Register the sensor now", sensor.Name)
// err2 := database.InsertSensors(ctx, []*types.Sensor{sensor})
// if err2 != nil {
// flogger.Fatal("Can not register sensor %v into database: %v", sensor.Name, err2)
// }
// flogger.Debug("Sensor %v successfully registered into the database", sensor.Name)
// continue
// }
// flogger.Debug("Sensor %v is already registered into the database", sensor.Name)
// }
// }