package database import ( "context" "database/sql" "fmt" "os" "go.ntppool.org/common/logger" ) // OpenDB opens a database connection with the specified configuration options func OpenDB(ctx context.Context, options ConfigOptions) (*sql.DB, error) { log := logger.Setup() configFile, err := findConfigFile(options.ConfigFiles) if err != nil { return nil, err } dbconn := sql.OpenDB(Driver{ CreateConnectorFunc: createConnector(configFile), }) // Set connection pool parameters dbconn.SetConnMaxLifetime(options.ConnMaxLifetime) dbconn.SetMaxOpenConns(options.MaxOpenConns) dbconn.SetMaxIdleConns(options.MaxIdleConns) err = dbconn.Ping() if err != nil { log.Error("could not connect to database", "err", err) return nil, err } // Start optional connection pool monitoring if options.EnablePoolMonitoring && options.PrometheusRegisterer != nil { go monitorConnectionPool(ctx, dbconn, options.PrometheusRegisterer) } return dbconn, nil } // OpenDBWithConfigFile opens a database connection using an explicit config file path // This is a convenience function for API package compatibility func OpenDBWithConfigFile(ctx context.Context, configFile string) (*sql.DB, error) { options := DefaultConfigOptions() options.ConfigFiles = []string{configFile} return OpenDB(ctx, options) } // OpenDBMonitor opens a database connection with monitor-specific defaults // This is a convenience function for Monitor package compatibility func OpenDBMonitor() (*sql.DB, error) { options := MonitorConfigOptions() return OpenDB(context.Background(), options) } // findConfigFile searches for the first existing config file from the list func findConfigFile(configFiles []string) (string, error) { var firstErr error for _, configFile := range configFiles { if configFile == "" { continue } if _, err := os.Stat(configFile); err == nil { return configFile, nil } else if firstErr == nil { firstErr = err } } if firstErr != nil { return "", fmt.Errorf("no config file found: %w", firstErr) } return "", fmt.Errorf("no valid config files provided") }