feat(index-builder, evolver): improve evolution system initialization and logging
Index builder: - Add slog import for structured logging - Improve fetchEvolutionMeta to return empty meta instead of error when programs table is empty - Add logging to show evolution system status (running vs not initialized) - Add logging in generateEvolutionMeta to show when evolution data is written Evolver: - Add automatic schema initialization and population seeding in RunEvolutionLoop - Programs table is now automatically seeded with 6 initial strategy bots on startup - Log seeding status to indicate whether programs table was already initialized These changes ensure the evolution system properly initializes when deployed and provides better visibility into its status via structured logging. Closes: bf-4zde
This commit is contained in:
parent
6fbe221fe7
commit
04b860a8be
3 changed files with 55 additions and 19 deletions
|
|
@ -187,7 +187,21 @@ func RunEvolutionLoop(ctx context.Context, dbURL string, args []string) {
|
|||
}
|
||||
defer db.Close()
|
||||
|
||||
// Initialize database schema and seed initial population if needed
|
||||
ctx := context.Background()
|
||||
if err := evolverdb.EnsureSchema(ctx, db); err != nil {
|
||||
log.Fatalf("ensure schema: %v", err)
|
||||
}
|
||||
|
||||
// Seed initial population if programs table is empty
|
||||
store := evolverdb.NewStore(db)
|
||||
if inserted, err := evolverdb.SeedPopulation(ctx, store); err != nil {
|
||||
log.Fatalf("seed population: %v", err)
|
||||
} else if inserted > 0 {
|
||||
log.Printf("Seeded %d initial programs", inserted)
|
||||
} else {
|
||||
log.Println("Programs table already seeded")
|
||||
}
|
||||
|
||||
// Load config from env with overrides
|
||||
cfg := DefaultRunConfig()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -258,9 +259,18 @@ func fetchAllData(ctx context.Context, db *sql.DB) (*IndexData, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Evolution data (may be missing if evolver DB is not available)
|
||||
// Evolution data (may be missing if evolver is not running)
|
||||
data.EvolutionMeta, _ = fetchEvolutionMeta(ctx, db)
|
||||
data.Lineage, _ = fetchLineage(ctx, db)
|
||||
if data.EvolutionMeta != nil && data.EvolutionMeta.Generation > 0 {
|
||||
slog.Info("Evolution system running",
|
||||
"generation", data.EvolutionMeta.Generation,
|
||||
"promoted_today", data.EvolutionMeta.PromotedToday,
|
||||
"total_promoted", data.EvolutionMeta.TotalPromoted,
|
||||
"islands", len(data.EvolutionMeta.IslandPopulations))
|
||||
} else {
|
||||
slog.Info("Evolution system not initialized or not running")
|
||||
}
|
||||
|
||||
data.TopPredictors = computeTopPredictors(data.PredictorStats)
|
||||
|
||||
|
|
@ -1050,6 +1060,7 @@ type LineageNode struct {
|
|||
|
||||
// fetchEvolutionMeta queries the evolver database for evolution statistics.
|
||||
// It connects to the evolver database using the same connection parameters.
|
||||
// Returns empty meta (not an error) if the evolution system is not running.
|
||||
func fetchEvolutionMeta(ctx context.Context, db *sql.DB) (*EvolutionMeta, error) {
|
||||
// Query the programs table in the evolver database
|
||||
// Note: the evolver uses a separate database but same PostgreSQL instance
|
||||
|
|
@ -1068,20 +1079,19 @@ func fetchEvolutionMeta(ctx context.Context, db *sql.DB) (*EvolutionMeta, error)
|
|||
|
||||
err := db.QueryRowContext(ctx, query).Scan(&meta.Generation, &meta.PromotedToday, &meta.TotalPromoted, &totalPrograms)
|
||||
if err != nil {
|
||||
// If evolver tables don't exist, return empty meta
|
||||
if err == sql.ErrNoRows {
|
||||
return &EvolutionMeta{
|
||||
Generation: 0,
|
||||
PromotedToday: 0,
|
||||
Top10Count: 0,
|
||||
IslandPopulations: make(map[string]int),
|
||||
BestRatings: []EvolvedBotRating{},
|
||||
TotalPromoted: 0,
|
||||
PromotionRate: 0,
|
||||
UpdatedAt: updatedAt,
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("fetch evolution meta: %w", err)
|
||||
// If evolver tables don't exist or query fails, return empty meta
|
||||
// This is expected when the evolution system has not been initialized yet
|
||||
slog.Info("Evolution system not running or programs table empty", "error", err)
|
||||
return &EvolutionMeta{
|
||||
Generation: 0,
|
||||
PromotedToday: 0,
|
||||
Top10Count: 0,
|
||||
IslandPopulations: make(map[string]int),
|
||||
BestRatings: []EvolvedBotRating{},
|
||||
TotalPromoted: 0,
|
||||
PromotionRate: 0,
|
||||
UpdatedAt: updatedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Calculate promotion rate
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -2094,12 +2095,23 @@ func generateEvolutionMeta(data *IndexData, outputDir string) error {
|
|||
// If no evolution meta data, write empty placeholder
|
||||
meta := data.EvolutionMeta
|
||||
if meta == nil {
|
||||
slog.Info("Evolution meta data not available - evolution system not running")
|
||||
meta = &EvolutionMeta{
|
||||
Generation: 0,
|
||||
PromotedToday: 0,
|
||||
Top10Count: 0,
|
||||
UpdatedAt: data.GeneratedAt.Format(time.RFC3339),
|
||||
Generation: 0,
|
||||
PromotedToday: 0,
|
||||
Top10Count: 0,
|
||||
IslandPopulations: make(map[string]int),
|
||||
BestRatings: []EvolvedBotRating{},
|
||||
TotalPromoted: 0,
|
||||
PromotionRate: 0,
|
||||
UpdatedAt: data.GeneratedAt.Format(time.RFC3339),
|
||||
}
|
||||
} else {
|
||||
slog.Info("Writing evolution meta data",
|
||||
"generation", meta.Generation,
|
||||
"promoted_today", meta.PromotedToday,
|
||||
"total_promoted", meta.TotalPromoted,
|
||||
"islands", len(meta.IslandPopulations))
|
||||
}
|
||||
|
||||
return writeJSON(filepath.Join(evolDir, "meta.json"), meta)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue