// Package database provides database factory for creating the appropriate backend. package database import ( "fmt" "os" "path/filepath" "tyto/internal/config" ) // New creates a new database connection based on configuration. func New(cfg *config.DatabaseConfig) (Database, error) { retention := DefaultRetentionConfig() // Override retention from config if provided if cfg.Retention.RawRetention > 0 { retention.RawRetention = cfg.Retention.RawRetention } if cfg.Retention.OneMinuteRetention > 0 { retention.OneMinuteRetention = cfg.Retention.OneMinuteRetention } if cfg.Retention.FiveMinuteRetention > 0 { retention.FiveMinuteRetention = cfg.Retention.FiveMinuteRetention } if cfg.Retention.HourlyRetention > 0 { retention.HourlyRetention = cfg.Retention.HourlyRetention } switch cfg.Type { case "sqlite", "": return newSQLiteFromConfig(cfg, retention) case "postgres", "postgresql": return newPostgresFromConfig(cfg, retention) default: return nil, fmt.Errorf("unsupported database type: %s", cfg.Type) } } func newSQLiteFromConfig(cfg *config.DatabaseConfig, retention RetentionConfig) (*SQLiteDB, error) { path := cfg.Path if path == "" { path = "tyto.db" } // Ensure directory exists dir := filepath.Dir(path) if dir != "" && dir != "." { if err := os.MkdirAll(dir, 0755); err != nil { return nil, fmt.Errorf("create database directory: %w", err) } } db, err := NewSQLiteDB(path, retention) if err != nil { return nil, err } // Run migrations if err := db.Migrate(); err != nil { db.Close() return nil, fmt.Errorf("migrate: %w", err) } return db, nil } func newPostgresFromConfig(cfg *config.DatabaseConfig, retention RetentionConfig) (*PostgresDB, error) { connStr := cfg.ConnectionString if connStr == "" { // Build connection string from individual fields connStr = fmt.Sprintf( "host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", cfg.Host, cfg.Port, cfg.User, cfg.Password, cfg.Database, cfg.SSLMode, ) } db, err := NewPostgresDB(connStr, retention) if err != nil { return nil, err } // Run migrations if err := db.Migrate(); err != nil { db.Close() return nil, fmt.Errorf("migrate: %w", err) } return db, nil }