Files
ddns-updater/internal/persistence/json/database.go
Quentin McGaw 844904aa7b Maintenance: upgrade linting setup
- Update Golangci-lint to v1.40.1
- Add more linters
- Remove rules from .golangci.yml in favor of inline nolint comments
- Fix linting errors
2021-05-19 01:00:42 +00:00

91 lines
2.0 KiB
Go

package json
import (
"encoding/json"
"fmt"
"sync"
"time"
"github.com/qdm12/golibs/files"
)
type Database struct {
data dataModel
filepath string
fileManager files.FileManager
sync.RWMutex
}
func (db *Database) Close() error {
db.Lock() // ensure a write operation finishes
defer db.Unlock()
return nil
}
// NewDatabase opens or creates the JSON file database.
func NewDatabase(dataDir string) (*Database, error) {
db := Database{
filepath: dataDir + "/updates.json",
fileManager: files.NewFileManager(),
}
exists, err := db.fileManager.FileExists(db.filepath)
if err != nil {
return nil, err
}
if !exists {
data, err := json.Marshal(db.data)
if err != nil {
return nil, err
}
if err := db.fileManager.WriteToFile(db.filepath, data); err != nil {
return nil, err
}
return &db, nil
}
data, err := db.fileManager.ReadFile(db.filepath)
if err != nil {
return nil, err
}
if err := json.Unmarshal(data, &db.data); err != nil {
return nil, err
}
if err := db.Check(); err != nil {
return nil, fmt.Errorf("%s validation error: %w", db.filepath, err)
}
return &db, nil
}
func (db *Database) Check() error {
for _, record := range db.data.Records {
switch {
case len(record.Domain) == 0:
return fmt.Errorf("domain is empty for record %s", record)
case len(record.Host) == 0:
return fmt.Errorf("host is empty for record %s", record)
}
var t time.Time
for i, event := range record.Events {
if event.Time.Before(t) {
return fmt.Errorf("IP records are not ordered correctly by time")
}
t = event.Time
switch {
case event.IP == nil:
return fmt.Errorf("IP %d of %d is empty for record %s", i+1, len(record.Events), record)
case event.Time.IsZero():
return fmt.Errorf("time of IP %d of %d is empty for record %s", i+1, len(record.Events), record)
}
}
}
return nil
}
func (db *Database) write() error {
data, err := json.MarshalIndent(db.data, "", " ")
if err != nil {
return err
}
return db.fileManager.WriteToFile(db.filepath, data)
}