package archiver import ( "context" "encoding/json" "fmt" "sort" "sync" archivalStore "git.nakama.town/fmartingr/hako/internal/archival/store" ) // Manager manages all registered archivers type Manager struct { archivers map[string]Archiver mu sync.RWMutex } // NewManager creates a new archiver manager func NewManager() *Manager { return &Manager{ archivers: make(map[string]Archiver), } } // Register registers an archiver func (m *Manager) Register(archiver Archiver) error { m.mu.Lock() defer m.mu.Unlock() key := archiver.Key() if _, exists := m.archivers[key]; exists { return fmt.Errorf("archiver with key %s already registered", key) } // Initialize the archiver if err := archiver.Init(); err != nil { return fmt.Errorf("failed to initialize archiver %s: %w", key, err) } m.archivers[key] = archiver return nil } // GetArchiver retrieves an archiver by key func (m *Manager) GetArchiver(key string) (Archiver, bool) { m.mu.RLock() defer m.mu.RUnlock() archiver, ok := m.archivers[key] return archiver, ok } // ListEnabled returns all enabled archivers func (m *Manager) ListEnabled(ctx context.Context) []Archiver { m.mu.RLock() defer m.mu.RUnlock() var enabled []Archiver for _, archiver := range m.archivers { if archiver.IsEnabled(ctx) { enabled = append(enabled, archiver) } } return enabled } // List returns all registered archivers func (m *Manager) List() []Archiver { m.mu.RLock() defer m.mu.RUnlock() var all []Archiver for _, archiver := range m.archivers { all = append(all, archiver) } return all } // ArchiverStatus represents the status of an archiver type ArchiverStatus struct { Key string `json:"key"` Name string `json:"name"` Enabled bool `json:"enabled"` DefaultConfig any `json:"default_config"` } // GetStatus returns status information for all registered archivers // If archiverConfigStore is provided, it will return stored configs if available, otherwise default configs func (m *Manager) GetStatus(ctx context.Context, archiverConfigStore *archivalStore.ArchiverConfigStore) []ArchiverStatus { m.mu.RLock() defer m.mu.RUnlock() var statuses []ArchiverStatus for _, archiver := range m.archivers { key := archiver.Key() var config any // Try to get stored config if store is provided if archiverConfigStore != nil { storedConfig, err := archiverConfigStore.Get(ctx, key) if err == nil && storedConfig != nil && storedConfig.ConfigJSON != "" { // Parse stored config JSON if err := json.Unmarshal([]byte(storedConfig.ConfigJSON), &config); err != nil { // If parsing fails, fall back to default config = archiver.GetDefaultConfig() } } else { // No stored config, use default config = archiver.GetDefaultConfig() } } else { // No store provided, use default config = archiver.GetDefaultConfig() } statuses = append(statuses, ArchiverStatus{ Key: key, Name: archiver.Name(), Enabled: archiver.IsEnabled(ctx), DefaultConfig: config, }) } // Sort by name sort.Slice(statuses, func(i, j int) bool { return statuses[i].Name < statuses[j].Name }) return statuses }