go-latestver/internal/database/store.go
Knut Ahlers 9255fc6898
Lint: Update linter config, fix all linter issues
Signed-off-by: Knut Ahlers <knut@ahlers.me>
2023-03-18 17:57:13 +01:00

164 lines
4.6 KiB
Go

package database
import (
"strings"
"time"
"github.com/pkg/errors"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"github.com/Luzifer/go-latestver/internal/version"
"github.com/Luzifer/go_helpers/v2/fieldcollection"
)
type (
// CatalogEntry represents the entry in the config file
CatalogEntry struct {
Name string `json:"name" yaml:"name"`
Tag string `json:"tag" yaml:"tag"`
Fetcher string `json:"-" yaml:"fetcher"`
FetcherConfig *fieldcollection.FieldCollection `json:"-" yaml:"fetcher_config"`
VersionConstraint *version.Constraint `json:"-" yaml:"version_constraint"`
Links []CatalogLink `json:"links" yaml:"links"`
}
// CatalogLink represents a link assigned to a CatalogEntry
CatalogLink struct {
IconClass string `json:"icon_class" yaml:"icon_class"`
Name string `json:"name" yaml:"name"`
URL string `json:"url" yaml:"url"`
}
// CatalogMeta contains meta-information about the catalog entry
CatalogMeta struct {
CatalogName string `gorm:"primaryKey" json:"-"`
CatalogTag string `gorm:"primaryKey" json:"-"`
CurrentVersion string `json:"current_version,omitempty"`
Error string `json:"error,omitempty"`
LastChecked *time.Time `json:"last_checked,omitempty"`
VersionTime *time.Time `json:"version_time,omitempty"`
}
// LogEntry represents a single version change for a given catalog entry
LogEntry struct {
CatalogName string `gorm:"index:catalog_key" json:"catalog_name"`
CatalogTag string `gorm:"index:catalog_key" json:"catalog_tag"`
Timestamp time.Time `gorm:"index:,sort:desc" json:"timestamp"`
VersionTo string `json:"version_to"`
VersionFrom string `json:"version_from"`
}
// CatalogMetaStore is an accessor for the meta store and wraps a Client
CatalogMetaStore struct {
c *Client
}
// LogStore is an accessor for the log store and wraps a Client
LogStore struct {
c *Client
}
)
// Key returns the name / tag combination as a single key
func (c CatalogEntry) Key() string { return strings.Join([]string{c.Name, c.Tag}, ":") }
// GetMeta fetches the current database stored CatalogMeta for the CatalogEntry
func (c CatalogMetaStore) GetMeta(ce *CatalogEntry) (*CatalogMeta, error) {
out := &CatalogMeta{
CatalogName: ce.Name,
CatalogTag: ce.Tag,
}
err := c.c.db.
Where(out).
First(out).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
// If there is no meta yet we just return empty meta
err = nil
}
return out, errors.Wrap(err, "querying metadata")
}
// Migrate applies the updated database schema for the CatalogMetaStore
func (c CatalogMetaStore) Migrate(dest *Client) error {
var metas []*CatalogMeta
if err := c.c.db.Find(&metas).Error; err != nil {
return errors.Wrap(err, "listing meta entries")
}
for _, m := range metas {
if err := dest.Catalog.PutMeta(m); err != nil {
return errors.Wrap(err, "storing meta to dest database")
}
}
return nil
}
// PutMeta stores the updated CatalogMeta
func (c CatalogMetaStore) PutMeta(cm *CatalogMeta) error {
return errors.Wrap(
c.c.db.Clauses(clause.OnConflict{UpdateAll: true}).Create(cm).Error,
"writing catalog meta",
)
}
func (c CatalogMetaStore) ensureTable() error {
return errors.Wrap(c.c.db.AutoMigrate(&CatalogMeta{}), "applying migration")
}
// Add creates a new LogEntry inside the LogStore
func (l LogStore) Add(le *LogEntry) error {
return errors.Wrap(
l.c.db.Create(le).Error,
"writing log entry",
)
}
// List retrieves unfiltered log entries by page
func (l LogStore) List(num, page int) ([]LogEntry, error) {
return l.listWithFilter(l.c.db, num, page)
}
// ListForCatalogEntry retrieves filered log entries by page
func (l LogStore) ListForCatalogEntry(ce *CatalogEntry, num, page int) ([]LogEntry, error) {
return l.listWithFilter(l.c.db.Where(&LogEntry{CatalogName: ce.Name, CatalogTag: ce.Tag}), num, page)
}
// Migrate applies the updated database schema for the LogStore
func (l LogStore) Migrate(dest *Client) error {
var logs []*LogEntry
if err := l.c.db.Find(&logs).Error; err != nil {
return errors.Wrap(err, "listing log entries")
}
for _, l := range logs {
if err := dest.Logs.Add(l); err != nil {
return errors.Wrap(err, "storing log to dest database")
}
}
return nil
}
func (LogStore) listWithFilter(filter *gorm.DB, num, page int) ([]LogEntry, error) {
var out []LogEntry
return out, errors.Wrap(
filter.
Order("timestamp desc").
Limit(num).Offset(num*page).
Find(&out).
Error,
"fetching log entries",
)
}
func (l LogStore) ensureTable() error {
return errors.Wrap(l.c.db.AutoMigrate(&LogEntry{}), "applying migration")
}