refactor(models): split Site into SiteConfig + SiteState
Site now embeds SiteConfig (22 persistent fields) and SiteState (11 ephemeral runtime fields). Field access unchanged via promotion — site.Name and site.Status still work. Store layer deals exclusively in SiteConfig — the DB never sees runtime state. Engine's liveState keeps full Site composites. UpdateSiteConfig reduced from 11-line field-by-field copy to `existing.SiteConfig = cfg`. RunCheck takes SiteConfig (only needs config fields). Checker is now statically prevented from reading/writing runtime state. Backup.Sites changed to []SiteConfig — exports no longer carry zero-valued runtime fields. Import backward-compatible (json ignores unknown fields).
This commit was merged in pull request #109.
This commit is contained in:
@@ -112,7 +112,7 @@ func (s *SQLStore) Init(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetSites(ctx context.Context) ([]models.Site, error) {
|
||||
func (s *SQLStore) GetSites(ctx context.Context) ([]models.SiteConfig, error) {
|
||||
bf := s.dialect.BoolFalse()
|
||||
query := fmt.Sprintf( //nolint:gosec // bf is a dialect boolean literal, not user input
|
||||
"SELECT id, COALESCE(name, url), url, COALESCE(type, 'http'), COALESCE(token, ''), interval, alert_id, check_ssl, threshold, max_retries, COALESCE(hostname, ''), COALESCE(port, 0), COALESCE(timeout, 0), COALESCE(method, 'GET'), COALESCE(description, ''), COALESCE(parent_id, 0), COALESCE(accepted_codes, '200-299'), COALESCE(dns_resolve_type, ''), COALESCE(dns_server, ''), COALESCE(ignore_tls, %s), COALESCE(paused, %s), COALESCE(regions, '') FROM sites",
|
||||
@@ -123,9 +123,9 @@ func (s *SQLStore) GetSites(ctx context.Context) ([]models.Site, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var sites []models.Site
|
||||
var sites []models.SiteConfig
|
||||
for rows.Next() {
|
||||
var st models.Site
|
||||
var st models.SiteConfig
|
||||
if err := rows.Scan(&st.ID, &st.Name, &st.URL, &st.Type, &st.Token, &st.Interval, &st.AlertID,
|
||||
&st.CheckSSL, &st.ExpiryThreshold, &st.MaxRetries, &st.Hostname, &st.Port, &st.Timeout,
|
||||
&st.Method, &st.Description, &st.ParentID, &st.AcceptedCodes, &st.DNSResolveType,
|
||||
@@ -137,7 +137,7 @@ func (s *SQLStore) GetSites(ctx context.Context) ([]models.Site, error) {
|
||||
return sites, rows.Err()
|
||||
}
|
||||
|
||||
func (s *SQLStore) AddSite(ctx context.Context, site models.Site) error {
|
||||
func (s *SQLStore) AddSite(ctx context.Context, site models.SiteConfig) error {
|
||||
token := ""
|
||||
if site.Type == "push" {
|
||||
var err error
|
||||
@@ -152,7 +152,7 @@ func (s *SQLStore) AddSite(ctx context.Context, site models.Site) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *SQLStore) UpdateSite(ctx context.Context, site models.Site) error {
|
||||
func (s *SQLStore) UpdateSite(ctx context.Context, site models.SiteConfig) error {
|
||||
var existingToken string
|
||||
_ = s.db.QueryRowContext(ctx, s.q("SELECT token FROM sites WHERE id=?"), site.ID).Scan(&existingToken) //nolint:errcheck
|
||||
if site.Type == "push" && existingToken == "" {
|
||||
@@ -198,13 +198,13 @@ func (s *SQLStore) DeleteSite(ctx context.Context, id int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetSiteByName(ctx context.Context, name string) (models.Site, error) {
|
||||
func (s *SQLStore) GetSiteByName(ctx context.Context, name string) (models.SiteConfig, error) {
|
||||
bf := s.dialect.BoolFalse()
|
||||
query := fmt.Sprintf( //nolint:gosec // bf is a dialect boolean literal, not user input
|
||||
"SELECT id, COALESCE(name, url), url, COALESCE(type, 'http'), COALESCE(token, ''), interval, alert_id, check_ssl, threshold, max_retries, COALESCE(hostname, ''), COALESCE(port, 0), COALESCE(timeout, 0), COALESCE(method, 'GET'), COALESCE(description, ''), COALESCE(parent_id, 0), COALESCE(accepted_codes, '200-299'), COALESCE(dns_resolve_type, ''), COALESCE(dns_server, ''), COALESCE(ignore_tls, %s), COALESCE(paused, %s), COALESCE(regions, '') FROM sites WHERE name = %s",
|
||||
bf, bf, s.q("?"),
|
||||
)
|
||||
var st models.Site
|
||||
var st models.SiteConfig
|
||||
err := s.db.QueryRowContext(ctx, query, name).Scan(&st.ID, &st.Name, &st.URL, &st.Type, &st.Token, &st.Interval, &st.AlertID,
|
||||
&st.CheckSSL, &st.ExpiryThreshold, &st.MaxRetries, &st.Hostname, &st.Port, &st.Timeout,
|
||||
&st.Method, &st.Description, &st.ParentID, &st.AcceptedCodes, &st.DNSResolveType,
|
||||
@@ -246,7 +246,7 @@ func (s *SQLStore) GetAlertByName(ctx context.Context, name string) (models.Aler
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (s *SQLStore) AddSiteReturningID(ctx context.Context, site models.Site) (int, error) {
|
||||
func (s *SQLStore) AddSiteReturningID(ctx context.Context, site models.SiteConfig) (int, error) {
|
||||
token := ""
|
||||
if site.Type == "push" {
|
||||
var err error
|
||||
|
||||
@@ -33,7 +33,7 @@ func TestSiteCRUD(t *testing.T) {
|
||||
t.Fatalf("expected 0 sites, got %d", len(sites))
|
||||
}
|
||||
|
||||
if err := s.AddSite(context.Background(), models.Site{Name: "Test", URL: "https://example.com", Type: "http", Interval: 30}); err != nil {
|
||||
if err := s.AddSite(context.Background(), models.SiteConfig{Name: "Test", URL: "https://example.com", Type: "http", Interval: 30}); err != nil {
|
||||
t.Fatalf("AddSite: %v", err)
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ func TestUserCRUD(t *testing.T) {
|
||||
func TestPushTokenGeneration(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
|
||||
if err := s.AddSite(context.Background(), models.Site{Name: "Push Monitor", Type: "push", Interval: 60}); err != nil {
|
||||
if err := s.AddSite(context.Background(), models.SiteConfig{Name: "Push Monitor", Type: "push", Interval: 60}); err != nil {
|
||||
t.Fatalf("AddSite: %v", err)
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ func TestImportExport(t *testing.T) {
|
||||
if err := s.AddAlert(context.Background(), "Test Alert", "webhook", map[string]string{"url": "https://example.com"}); err != nil {
|
||||
t.Fatalf("AddAlert: %v", err)
|
||||
}
|
||||
if err := s.AddSite(context.Background(), models.Site{Name: "Site1", URL: "https://example.com", Type: "http", Interval: 30}); err != nil {
|
||||
if err := s.AddSite(context.Background(), models.SiteConfig{Name: "Site1", URL: "https://example.com", Type: "http", Interval: 30}); err != nil {
|
||||
t.Fatalf("AddSite: %v", err)
|
||||
}
|
||||
if err := s.AddUser(context.Background(), "user1", "ssh-ed25519 KEY", "user"); err != nil {
|
||||
@@ -239,7 +239,7 @@ func TestImportExport(t *testing.T) {
|
||||
func TestImportData_WipesHistory(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
|
||||
if err := s.AddSite(context.Background(), models.Site{Name: "OldSite", URL: "https://old.com", Type: "http", Interval: 30}); err != nil {
|
||||
if err := s.AddSite(context.Background(), models.SiteConfig{Name: "OldSite", URL: "https://old.com", Type: "http", Interval: 30}); err != nil {
|
||||
t.Fatalf("AddSite: %v", err)
|
||||
}
|
||||
if err := s.SaveCheck(context.Background(), 1, 5000, true); err != nil {
|
||||
@@ -253,7 +253,7 @@ func TestImportData_WipesHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
backup := models.Backup{
|
||||
Sites: []models.Site{{ID: 1, Name: "NewSite", URL: "https://new.com", Type: "http", Interval: 60}},
|
||||
Sites: []models.SiteConfig{{ID: 1, Name: "NewSite", URL: "https://new.com", Type: "http", Interval: 60}},
|
||||
}
|
||||
if err := s.ImportData(context.Background(), backup); err != nil {
|
||||
t.Fatalf("ImportData: %v", err)
|
||||
@@ -314,7 +314,7 @@ func TestCheckHistory(t *testing.T) {
|
||||
func TestDeleteSiteCascade(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
|
||||
site := models.Site{Name: "Cascade Test", URL: "https://example.com", Interval: 30}
|
||||
site := models.SiteConfig{Name: "Cascade Test", URL: "https://example.com", Interval: 30}
|
||||
if err := s.AddSite(context.Background(), site); err != nil {
|
||||
t.Fatalf("AddSite: %v", err)
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ type Store interface {
|
||||
Init(ctx context.Context) error
|
||||
|
||||
// Sites
|
||||
GetSites(ctx context.Context) ([]models.Site, error)
|
||||
AddSite(ctx context.Context, site models.Site) error
|
||||
UpdateSite(ctx context.Context, site models.Site) error
|
||||
GetSites(ctx context.Context) ([]models.SiteConfig, error)
|
||||
AddSite(ctx context.Context, site models.SiteConfig) error
|
||||
UpdateSite(ctx context.Context, site models.SiteConfig) error
|
||||
UpdateSitePaused(ctx context.Context, id int, paused bool) error
|
||||
DeleteSite(ctx context.Context, id int) error
|
||||
|
||||
@@ -25,9 +25,9 @@ type Store interface {
|
||||
DeleteAlert(ctx context.Context, id int) error
|
||||
|
||||
// Declarative config support
|
||||
GetSiteByName(ctx context.Context, name string) (models.Site, error)
|
||||
GetSiteByName(ctx context.Context, name string) (models.SiteConfig, error)
|
||||
GetAlertByName(ctx context.Context, name string) (models.AlertConfig, error)
|
||||
AddSiteReturningID(ctx context.Context, site models.Site) (int, error)
|
||||
AddSiteReturningID(ctx context.Context, site models.SiteConfig) (int, error)
|
||||
AddAlertReturningID(ctx context.Context, name, aType string, settings map[string]string) (int, error)
|
||||
|
||||
// Users
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
// mocks and override only the methods you need via the exported Func fields or
|
||||
// by shadowing the method on the embedding struct.
|
||||
type BaseMock struct {
|
||||
GetSitesFunc func(ctx context.Context) ([]models.Site, error)
|
||||
AddSiteFunc func(ctx context.Context, site models.Site) error
|
||||
UpdateSiteFunc func(ctx context.Context, site models.Site) error
|
||||
GetSitesFunc func(ctx context.Context) ([]models.SiteConfig, error)
|
||||
AddSiteFunc func(ctx context.Context, site models.SiteConfig) error
|
||||
UpdateSiteFunc func(ctx context.Context, site models.SiteConfig) error
|
||||
GetAllAlertsFunc func(ctx context.Context) ([]models.AlertConfig, error)
|
||||
GetAlertFunc func(ctx context.Context, id int) (models.AlertConfig, error)
|
||||
GetAllUsersFunc func(ctx context.Context) ([]models.User, error)
|
||||
@@ -41,21 +41,21 @@ type BaseMock struct {
|
||||
func (m *BaseMock) Init(_ context.Context) error { return nil }
|
||||
func (m *BaseMock) Close() error { return nil }
|
||||
|
||||
func (m *BaseMock) GetSites(ctx context.Context) ([]models.Site, error) {
|
||||
func (m *BaseMock) GetSites(ctx context.Context) ([]models.SiteConfig, error) {
|
||||
if m.GetSitesFunc != nil {
|
||||
return m.GetSitesFunc(ctx)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *BaseMock) AddSite(ctx context.Context, site models.Site) error {
|
||||
func (m *BaseMock) AddSite(ctx context.Context, site models.SiteConfig) error {
|
||||
if m.AddSiteFunc != nil {
|
||||
return m.AddSiteFunc(ctx, site)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BaseMock) UpdateSite(ctx context.Context, site models.Site) error {
|
||||
func (m *BaseMock) UpdateSite(ctx context.Context, site models.SiteConfig) error {
|
||||
if m.UpdateSiteFunc != nil {
|
||||
return m.UpdateSiteFunc(ctx, site)
|
||||
}
|
||||
@@ -90,15 +90,17 @@ func (m *BaseMock) UpdateAlert(_ context.Context, _ int, _ string, _ string, _ m
|
||||
|
||||
func (m *BaseMock) DeleteAlert(_ context.Context, _ int) error { return nil }
|
||||
|
||||
func (m *BaseMock) GetSiteByName(_ context.Context, _ string) (models.Site, error) {
|
||||
return models.Site{}, nil
|
||||
func (m *BaseMock) GetSiteByName(_ context.Context, _ string) (models.SiteConfig, error) {
|
||||
return models.SiteConfig{}, nil
|
||||
}
|
||||
|
||||
func (m *BaseMock) GetAlertByName(_ context.Context, _ string) (models.AlertConfig, error) {
|
||||
return models.AlertConfig{}, nil
|
||||
}
|
||||
|
||||
func (m *BaseMock) AddSiteReturningID(_ context.Context, _ models.Site) (int, error) { return 0, nil }
|
||||
func (m *BaseMock) AddSiteReturningID(_ context.Context, _ models.SiteConfig) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *BaseMock) AddAlertReturningID(_ context.Context, _ string, _ string, _ map[string]string) (int, error) {
|
||||
return 0, nil
|
||||
|
||||
Reference in New Issue
Block a user