Open initializes the database connection
(dbPath string)
| 63 | |
| 64 | // Open initializes the database connection |
| 65 | func Open(dbPath string) *gorm.DB { |
| 66 | // Create directory if it doesn't exist |
| 67 | dir := filepath.Dir(dbPath) |
| 68 | if err := os.MkdirAll(dir, 0755); err != nil { |
| 69 | panic(errors.Wrapf(err, "creating database directory at %s", dir)) |
| 70 | } |
| 71 | |
| 72 | db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{ |
| 73 | Logger: logger.Default.LogMode(getDBLogLevel(log.GetLevel())), |
| 74 | }) |
| 75 | if err != nil { |
| 76 | panic(errors.Wrap(err, "opening database conection")) |
| 77 | } |
| 78 | |
| 79 | // Get underlying *sql.DB to configure connection pool |
| 80 | sqlDB, err := db.DB() |
| 81 | if err != nil { |
| 82 | panic(errors.Wrap(err, "getting underlying database connection")) |
| 83 | } |
| 84 | |
| 85 | // Configure connection pool for SQLite with WAL mode |
| 86 | sqlDB.SetMaxOpenConns(25) |
| 87 | sqlDB.SetMaxIdleConns(5) |
| 88 | sqlDB.SetConnMaxLifetime(0) // Doesn't expire. |
| 89 | |
| 90 | // Apply performance PRAGMAs |
| 91 | pragmas := []string{ |
| 92 | "PRAGMA journal_mode=WAL", // Enable WAL mode for better concurrency |
| 93 | "PRAGMA synchronous=NORMAL", // Balance between safety and speed |
| 94 | "PRAGMA cache_size=-64000", // 64MB cache (negative = KB) |
| 95 | "PRAGMA busy_timeout=5000", // Wait up to 5s for locks |
| 96 | "PRAGMA foreign_keys=ON", // Enforce foreign key constraints |
| 97 | "PRAGMA temp_store=MEMORY", // Store temp tables in memory |
| 98 | } |
| 99 | |
| 100 | for _, pragma := range pragmas { |
| 101 | if err := db.Exec(pragma).Error; err != nil { |
| 102 | panic(errors.Wrapf(err, "executing pragma: %s", pragma)) |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | return db |
| 107 | } |
| 108 | |
| 109 | // StartWALCheckpointing starts a background goroutine that periodically |
| 110 | // checkpoints the WAL file to prevent it from growing unbounded |