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:
@@ -42,7 +42,7 @@ func Apply(ctx context.Context, s store.Store, f *File, opts ApplyOpts) ([]Chang
|
||||
existingAlertsByName[a.Name] = a
|
||||
}
|
||||
|
||||
existingSitesByName := make(map[string]models.Site, len(existingSites))
|
||||
existingSitesByName := make(map[string]models.SiteConfig, len(existingSites))
|
||||
for _, s := range existingSites {
|
||||
existingSitesByName[s.Name] = s
|
||||
}
|
||||
@@ -181,7 +181,7 @@ func Apply(ctx context.Context, s store.Store, f *File, opts ApplyOpts) ([]Chang
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
func applyMonitor(ctx context.Context, s store.Store, m Monitor, alertMap map[string]int, existing map[string]models.Site, parentID int, dryRun bool) ([]Change, error) {
|
||||
func applyMonitor(ctx context.Context, s store.Store, m Monitor, alertMap map[string]int, existing map[string]models.SiteConfig, parentID int, dryRun bool) ([]Change, error) {
|
||||
alertID, err := resolveAlertID(alertMap, m.Alert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("monitor %q: %w", m.Name, err)
|
||||
@@ -222,8 +222,8 @@ func resolveAlertID(alertMap map[string]int, name string) (int, error) {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func monitorToSite(m Monitor, alertID, parentID int) models.Site {
|
||||
s := models.Site{
|
||||
func monitorToSite(m Monitor, alertID, parentID int) models.SiteConfig {
|
||||
s := models.SiteConfig{
|
||||
Name: m.Name,
|
||||
Type: m.Type,
|
||||
URL: m.URL,
|
||||
@@ -269,7 +269,7 @@ func collectMonitorNames(monitors []Monitor, names map[string]bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeSite(s models.Site) models.Site {
|
||||
func normalizeSite(s models.SiteConfig) models.SiteConfig {
|
||||
if s.Method == "" {
|
||||
s.Method = "GET"
|
||||
}
|
||||
@@ -293,7 +293,7 @@ func diffAlert(existing models.AlertConfig, desired Alert) string {
|
||||
return strings.Join(diffs, ", ")
|
||||
}
|
||||
|
||||
func diffSite(existing, desired models.Site) string {
|
||||
func diffSite(existing, desired models.SiteConfig) string {
|
||||
var diffs []string
|
||||
if existing.URL != desired.URL {
|
||||
diffs = append(diffs, fmt.Sprintf("url: %s -> %s", existing.URL, desired.URL))
|
||||
|
||||
@@ -114,8 +114,8 @@ func TestApplyUpdate(t *testing.T) {
|
||||
|
||||
func TestApplyPrune(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
s.AddSite(context.Background(), models.Site{Name: "Keep", URL: "https://keep.com", Type: "http", Interval: 30, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s.AddSite(context.Background(), models.Site{Name: "Remove", URL: "https://remove.com", Type: "http", Interval: 30, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s.AddSite(context.Background(), models.SiteConfig{Name: "Keep", URL: "https://keep.com", Type: "http", Interval: 30, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s.AddSite(context.Background(), models.SiteConfig{Name: "Remove", URL: "https://remove.com", Type: "http", Interval: 30, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
|
||||
f := &File{
|
||||
Monitors: []Monitor{
|
||||
@@ -191,7 +191,7 @@ func TestApplyGroupHierarchy(t *testing.T) {
|
||||
}
|
||||
|
||||
sites, _ := s.GetSites(context.Background())
|
||||
var group models.Site
|
||||
var group models.SiteConfig
|
||||
for _, s := range sites {
|
||||
if s.Type == "group" {
|
||||
group = s
|
||||
|
||||
@@ -34,9 +34,9 @@ func Export(ctx context.Context, s store.Store) (*File, error) {
|
||||
})
|
||||
}
|
||||
|
||||
groups := make(map[int]models.Site)
|
||||
children := make(map[int][]models.Site)
|
||||
var topLevel []models.Site
|
||||
groups := make(map[int]models.SiteConfig)
|
||||
children := make(map[int][]models.SiteConfig)
|
||||
var topLevel []models.SiteConfig
|
||||
|
||||
for _, s := range dbSites {
|
||||
switch {
|
||||
@@ -76,7 +76,7 @@ func Export(ctx context.Context, s store.Store) (*File, error) {
|
||||
return &File{Alerts: yamlAlerts, Monitors: yamlMonitors}, nil
|
||||
}
|
||||
|
||||
func siteToMonitor(s models.Site, alertIDToName map[int]string) Monitor {
|
||||
func siteToMonitor(s models.SiteConfig, alertIDToName map[int]string) Monitor {
|
||||
m := Monitor{
|
||||
Name: s.Name,
|
||||
Type: s.Type,
|
||||
|
||||
@@ -22,7 +22,7 @@ func TestExportAlertNames(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
s.AddAlert(context.Background(), "Discord", "discord", map[string]string{"url": "https://example.com"})
|
||||
alerts, _ := s.GetAllAlerts(context.Background())
|
||||
s.AddSite(context.Background(), models.Site{Name: "Web", URL: "https://example.com", Type: "http", Interval: 30, AlertID: alerts[0].ID, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s.AddSite(context.Background(), models.SiteConfig{Name: "Web", URL: "https://example.com", Type: "http", Interval: 30, AlertID: alerts[0].ID, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
|
||||
f, err := Export(context.Background(), s)
|
||||
if err != nil {
|
||||
@@ -39,9 +39,9 @@ func TestExportAlertNames(t *testing.T) {
|
||||
|
||||
func TestExportGroupHierarchy(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
groupID, _ := s.AddSiteReturningID(context.Background(), models.Site{Name: "Prod", Type: "group", ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s.AddSite(context.Background(), models.Site{Name: "Prod Web", URL: "https://prod.example.com", Type: "http", Interval: 15, ParentID: groupID, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s.AddSite(context.Background(), models.Site{Name: "Top Level", URL: "https://example.com", Type: "http", Interval: 30, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
groupID, _ := s.AddSiteReturningID(context.Background(), models.SiteConfig{Name: "Prod", Type: "group", ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s.AddSite(context.Background(), models.SiteConfig{Name: "Prod Web", URL: "https://prod.example.com", Type: "http", Interval: 15, ParentID: groupID, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s.AddSite(context.Background(), models.SiteConfig{Name: "Top Level", URL: "https://example.com", Type: "http", Interval: 30, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
|
||||
f, err := Export(context.Background(), s)
|
||||
if err != nil {
|
||||
@@ -72,7 +72,7 @@ func TestExportGroupHierarchy(t *testing.T) {
|
||||
|
||||
func TestExportOmitsDefaults(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
s.AddSite(context.Background(), models.Site{
|
||||
s.AddSite(context.Background(), models.SiteConfig{
|
||||
Name: "Web", URL: "https://example.com", Type: "http", Interval: 30,
|
||||
Method: "GET", AcceptedCodes: "200-299", ExpiryThreshold: 7,
|
||||
})
|
||||
@@ -98,8 +98,8 @@ func TestExportRoundTrip(t *testing.T) {
|
||||
s1 := newTestStore(t)
|
||||
s1.AddAlert(context.Background(), "Discord", "discord", map[string]string{"url": "https://example.com"})
|
||||
alerts, _ := s1.GetAllAlerts(context.Background())
|
||||
s1.AddSite(context.Background(), models.Site{Name: "Web", URL: "https://example.com", Type: "http", Interval: 30, AlertID: alerts[0].ID, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s1.AddSite(context.Background(), models.Site{Name: "Ping", Type: "ping", Hostname: "10.0.0.1", Interval: 60, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s1.AddSite(context.Background(), models.SiteConfig{Name: "Web", URL: "https://example.com", Type: "http", Interval: 30, AlertID: alerts[0].ID, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
s1.AddSite(context.Background(), models.SiteConfig{Name: "Ping", Type: "ping", Hostname: "10.0.0.1", Interval: 60, ExpiryThreshold: 7, Method: "GET", AcceptedCodes: "200-299"})
|
||||
|
||||
exported, err := Export(context.Background(), s1)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user