// Command seed loads the frontend's demo dataset into PostgreSQL. // // Safe to run repeatedly: every record's key is derived deterministically from // its source id and written with ON CONFLICT DO UPDATE inside one transaction, // so re-running restores the seeded values without duplicating a row or // deleting anything. See internal/seeder. // // make seed package main import ( "context" "fmt" "os" "sort" "time" "github.com/krow/krow-backend/go-api/internal/config" "github.com/krow/krow-backend/go-api/internal/db" "github.com/krow/krow-backend/go-api/internal/seeder" ) func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, "seed failed:", err) os.Exit(1) } } func run() error { cfg, err := config.Load() if err != nil { return err } fixture, err := seeder.Load(cfg.Seed.FixturePath) if err != nil { return err } ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() database, err := db.Open(ctx, cfg.DB) if err != nil { return err } defer database.Close() started := time.Now() result, err := seeder.New(database.Pool, fixture, time.Now()).Run(ctx) if err != nil { return err } names := make([]string, 0, len(result.Counts)) total := 0 for name, n := range result.Counts { names = append(names, name) total += n } sort.Strings(names) fmt.Printf("seeded into %s (organization %s)\n", cfg.DB.Name, result.OrgID) for _, name := range names { fmt.Printf(" %-16s %4d\n", name, result.Counts[name]) } fmt.Printf(" %-16s %4d records in %s\n", "TOTAL", total, time.Since(started).Round(time.Millisecond)) if result.Pruned > 0 { // Shift records are a rolling window; ones that fell out of it are // removed. Said out loud, because a seed that deletes should say so. fmt.Printf(" %-16s %4d stale shift record(s) outside the current window\n", "PRUNED", result.Pruned) } return nil }