registry.go raw

   1  //go:build !(js && wasm)
   2  
   3  package sync
   4  
   5  import (
   6  	"context"
   7  	"sort"
   8  	"sync"
   9  
  10  	"next.orly.dev/pkg/lol/errorf"
  11  	"next.orly.dev/pkg/database"
  12  )
  13  
  14  // DriverFactory is the signature for sync driver factory functions.
  15  type DriverFactory func(ctx context.Context, db database.Database, cfg *DriverConfig) (Service, error)
  16  
  17  // DriverConfig holds configuration for sync drivers.
  18  type DriverConfig struct {
  19  	// Common settings
  20  	LogLevel string
  21  
  22  	// Negentropy-specific settings
  23  	TargetRelays []string
  24  	Filter       string
  25  	SyncInterval string
  26  	BatchSize    int
  27  
  28  	// Cluster-specific settings
  29  	AdminNpubs                []string
  30  	PropagatePrivilegedEvents bool
  31  	PollInterval              string
  32  
  33  	// Distributed-specific settings
  34  	NodeID   string
  35  	RelayURL string
  36  	Peers    []string
  37  
  38  	// Relay group settings
  39  	RelayGroups []string
  40  }
  41  
  42  // DriverInfo contains metadata about a registered sync driver.
  43  type DriverInfo struct {
  44  	Name        string
  45  	Description string
  46  	Factory     DriverFactory
  47  }
  48  
  49  // Service is the interface that sync drivers must implement.
  50  type Service interface {
  51  	// Start begins the sync service
  52  	Start() error
  53  	// Stop stops the sync service
  54  	Stop() error
  55  	// Type returns the service type name
  56  	Type() string
  57  }
  58  
  59  var (
  60  	driversMu sync.RWMutex
  61  	drivers   = make(map[string]*DriverInfo)
  62  )
  63  
  64  // RegisterDriver registers a sync driver with the given name and factory.
  65  // This is typically called from init() in the driver package.
  66  func RegisterDriver(name, description string, factory DriverFactory) {
  67  	driversMu.Lock()
  68  	defer driversMu.Unlock()
  69  	drivers[name] = &DriverInfo{
  70  		Name:        name,
  71  		Description: description,
  72  		Factory:     factory,
  73  	}
  74  }
  75  
  76  // GetDriver returns the factory for the named driver, or nil if not found.
  77  func GetDriver(name string) DriverFactory {
  78  	driversMu.RLock()
  79  	defer driversMu.RUnlock()
  80  	if info, ok := drivers[name]; ok {
  81  		return info.Factory
  82  	}
  83  	return nil
  84  }
  85  
  86  // HasDriver returns true if the named driver is registered.
  87  func HasDriver(name string) bool {
  88  	driversMu.RLock()
  89  	defer driversMu.RUnlock()
  90  	_, ok := drivers[name]
  91  	return ok
  92  }
  93  
  94  // ListDrivers returns a sorted list of registered driver names.
  95  func ListDrivers() []string {
  96  	driversMu.RLock()
  97  	defer driversMu.RUnlock()
  98  	names := make([]string, 0, len(drivers))
  99  	for name := range drivers {
 100  		names = append(names, name)
 101  	}
 102  	sort.Strings(names)
 103  	return names
 104  }
 105  
 106  // ListDriversWithInfo returns information about all registered drivers.
 107  func ListDriversWithInfo() []*DriverInfo {
 108  	driversMu.RLock()
 109  	defer driversMu.RUnlock()
 110  	infos := make([]*DriverInfo, 0, len(drivers))
 111  	for _, info := range drivers {
 112  		infos = append(infos, info)
 113  	}
 114  	// Sort by name for consistent output
 115  	sort.Slice(infos, func(i, j int) bool {
 116  		return infos[i].Name < infos[j].Name
 117  	})
 118  	return infos
 119  }
 120  
 121  // NewFromDriver creates a sync service using the named driver.
 122  // Returns an error if the driver is not registered.
 123  func NewFromDriver(ctx context.Context, driverName string, db database.Database, cfg *DriverConfig) (Service, error) {
 124  	factory := GetDriver(driverName)
 125  	if factory == nil {
 126  		return nil, errorf.E("sync driver %q not available; registered: %v", driverName, ListDrivers())
 127  	}
 128  	return factory(ctx, db, cfg)
 129  }
 130