package datasource import ( "context" "fmt" "strings" "gitea.maximumdirect.net/ejr/weatherapi/internal/platform/config" ) // DataSource is a generic opened datasource handle. type DataSource interface { Close() } // Factory constructs datasource handles for a specific driver. type Factory interface { Driver() string Open(ctx context.Context, cfg config.DatabaseConfig) (DataSource, error) } // Registry maps driver names to datasource factories. type Registry struct { factories map[string]Factory } func NewRegistry() *Registry { return &Registry{factories: map[string]Factory{}} } func (r *Registry) Register(factory Factory) error { if factory == nil { return fmt.Errorf("register datasource factory: factory is nil") } driver := normalizeDriver(factory.Driver()) if driver == "" { return fmt.Errorf("register datasource factory: factory driver is empty") } if _, exists := r.factories[driver]; exists { return fmt.Errorf("register datasource factory: driver %q already registered", driver) } r.factories[driver] = factory return nil } func (r *Registry) Open(ctx context.Context, cfg config.DatabaseConfig) (DataSource, error) { if r == nil { return nil, fmt.Errorf("open datasource: registry is nil") } driver := normalizeDriver(cfg.Driver) factory, ok := r.factories[driver] if !ok { return nil, fmt.Errorf("open datasource: unsupported driver %q", cfg.Driver) } ds, err := factory.Open(ctx, cfg) if err != nil { return nil, err } return ds, nil } func normalizeDriver(driver string) string { return strings.ToLower(strings.TrimSpace(driver)) }