feat: status page schema, licence feature and indexes
This commit is contained in:
@@ -46,6 +46,8 @@ var ScopedCollections = []string{
|
||||
"vuln_alert_rules",
|
||||
"api_tokens",
|
||||
"server_workloads",
|
||||
"status_pages",
|
||||
"status_incidents",
|
||||
}
|
||||
|
||||
// collectionRenames maps the two collections whose names change. Ordered so the
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"gitea.hostxtra.co.uk/mrhid6/vantage/server/internal/db"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"go.mongodb.org/mongo-driver/v2/mongo"
|
||||
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
||||
)
|
||||
|
||||
func spCtx() (context.Context, context.CancelFunc) {
|
||||
return context.WithTimeout(context.Background(), 5*time.Second)
|
||||
}
|
||||
|
||||
// EnsureStatusPageIndexes follows EnsureWorkflowIndexes rather than
|
||||
// EnsureAuthIndexes: the unique page_id index is a correctness property, but a
|
||||
// missing secondary index on a small collection degrades to a scan, which is no
|
||||
// reason to refuse to serve the fleet. main.go warns rather than exiting.
|
||||
func EnsureStatusPageIndexes() error {
|
||||
ctx, cancel := spCtx()
|
||||
defer cancel()
|
||||
|
||||
if _, err := db.Col("status_pages").Indexes().CreateOne(ctx, mongo.IndexModel{
|
||||
Keys: bson.D{{Key: "instance_id", Value: 1}, {Key: "page_id", Value: 1}},
|
||||
Options: options.Index().SetUnique(true),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := db.Col("status_incidents").Indexes().CreateOne(ctx, mongo.IndexModel{
|
||||
Keys: bson.D{{Key: "instance_id", Value: 1}, {Key: "incident_id", Value: 1}},
|
||||
Options: options.Index().SetUnique(true),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The public read filters by page and orders by recency, and it is the
|
||||
// only query on this collection that runs on every visit.
|
||||
if _, err := db.Col("status_incidents").Indexes().CreateOne(ctx, mongo.IndexModel{
|
||||
Keys: bson.D{{Key: "instance_id", Value: 1}, {Key: "page_ids", Value: 1}, {Key: "started_at", Value: -1}},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package services
|
||||
|
||||
import "testing"
|
||||
|
||||
// A new instance-scoped collection that is not in ScopedCollections leaves its
|
||||
// rows behind when the instance is deleted. This is the cheapest possible
|
||||
// guard against the omission.
|
||||
func TestStatusCollectionsAreScoped(t *testing.T) {
|
||||
want := []string{"status_pages", "status_incidents"}
|
||||
for _, name := range want {
|
||||
found := false
|
||||
for _, got := range ScopedCollections {
|
||||
if got == name {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("ScopedCollections is missing %q", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user