registry.go raw

   1  //go:build !(js && wasm)
   2  
   3  package database
   4  
   5  import (
   6  	"context"
   7  	"sort"
   8  	"sync"
   9  
  10  	"next.orly.dev/pkg/lol/errorf"
  11  )
  12  
  13  // DriverFactory is the signature for database driver factory functions.
  14  type DriverFactory func(ctx context.Context, cancel context.CancelFunc, cfg *DatabaseConfig) (Database, error)
  15  
  16  // DriverInfo contains metadata about a registered driver.
  17  type DriverInfo struct {
  18  	Name        string
  19  	Description string
  20  	Factory     DriverFactory
  21  }
  22  
  23  var (
  24  	driversMu sync.RWMutex
  25  	drivers   = make(map[string]*DriverInfo)
  26  )
  27  
  28  // RegisterDriver registers a database driver with the given name and factory.
  29  // This is typically called from init() in the driver package.
  30  func RegisterDriver(name, description string, factory DriverFactory) {
  31  	driversMu.Lock()
  32  	defer driversMu.Unlock()
  33  	drivers[name] = &DriverInfo{
  34  		Name:        name,
  35  		Description: description,
  36  		Factory:     factory,
  37  	}
  38  }
  39  
  40  // GetDriver returns the factory for the named driver, or nil if not found.
  41  func GetDriver(name string) DriverFactory {
  42  	driversMu.RLock()
  43  	defer driversMu.RUnlock()
  44  	if info, ok := drivers[name]; ok {
  45  		return info.Factory
  46  	}
  47  	return nil
  48  }
  49  
  50  // HasDriver returns true if the named driver is registered.
  51  func HasDriver(name string) bool {
  52  	driversMu.RLock()
  53  	defer driversMu.RUnlock()
  54  	_, ok := drivers[name]
  55  	return ok
  56  }
  57  
  58  // ListDrivers returns a sorted list of registered driver names.
  59  func ListDrivers() []string {
  60  	driversMu.RLock()
  61  	defer driversMu.RUnlock()
  62  	names := make([]string, 0, len(drivers))
  63  	for name := range drivers {
  64  		names = append(names, name)
  65  	}
  66  	sort.Strings(names)
  67  	return names
  68  }
  69  
  70  // ListDriversWithInfo returns information about all registered drivers.
  71  func ListDriversWithInfo() []*DriverInfo {
  72  	driversMu.RLock()
  73  	defer driversMu.RUnlock()
  74  	infos := make([]*DriverInfo, 0, len(drivers))
  75  	for _, info := range drivers {
  76  		infos = append(infos, info)
  77  	}
  78  	// Sort by name for consistent output
  79  	sort.Slice(infos, func(i, j int) bool {
  80  		return infos[i].Name < infos[j].Name
  81  	})
  82  	return infos
  83  }
  84  
  85  // NewFromDriver creates a database using the named driver.
  86  // Returns an error if the driver is not registered.
  87  func NewFromDriver(ctx context.Context, cancel context.CancelFunc, driverName string, cfg *DatabaseConfig) (Database, error) {
  88  	factory := GetDriver(driverName)
  89  	if factory == nil {
  90  		return nil, errorf.E("database driver %q not available; registered: %v", driverName, ListDrivers())
  91  	}
  92  	return factory(ctx, cancel, cfg)
  93  }
  94