127 lines
3 KiB
Go
127 lines
3 KiB
Go
package extractors
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"sort"
|
|
"sync"
|
|
)
|
|
|
|
// extractorStatus tracks the initialization status of an extractor
|
|
type extractorStatus struct {
|
|
extractor Extractor
|
|
available bool
|
|
errorMsg string
|
|
}
|
|
|
|
// Manager manages all registered extractors
|
|
type Manager struct {
|
|
extractors map[string]*extractorStatus
|
|
mu sync.RWMutex
|
|
logger *slog.Logger
|
|
}
|
|
|
|
// NewManager creates a new extractor manager
|
|
func NewManager(logger *slog.Logger) *Manager {
|
|
return &Manager{
|
|
extractors: make(map[string]*extractorStatus),
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// Register registers an extractor
|
|
// If Init() fails, the error is logged but registration continues
|
|
func (m *Manager) Register(extractor Extractor) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
key := extractor.Key()
|
|
if _, exists := m.extractors[key]; exists {
|
|
return fmt.Errorf("extractor with key %s already registered", key)
|
|
}
|
|
|
|
// Initialize the extractor
|
|
err := extractor.Init()
|
|
available := err == nil
|
|
errorMsg := ""
|
|
if err != nil {
|
|
m.logger.Error("Failed to initialize extractor",
|
|
"key", key,
|
|
"name", extractor.Name(),
|
|
"error", err)
|
|
errorMsg = err.Error()
|
|
// Continue registration even if Init() fails - extractor will be marked as unavailable
|
|
}
|
|
|
|
m.extractors[key] = &extractorStatus{
|
|
extractor: extractor,
|
|
available: available,
|
|
errorMsg: errorMsg,
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetExtractorForMimeType retrieves an extractor that supports the given MIME type
|
|
func (m *Manager) GetExtractorForMimeType(mimeType string) (Extractor, bool) {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
for _, status := range m.extractors {
|
|
if !status.available {
|
|
continue // Skip unavailable extractors
|
|
}
|
|
for _, supportedType := range status.extractor.SupportedMimeTypes() {
|
|
if supportedType == mimeType {
|
|
return status.extractor, true
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
// List returns all registered extractors
|
|
func (m *Manager) List() []Extractor {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
var all []Extractor
|
|
for _, status := range m.extractors {
|
|
all = append(all, status.extractor)
|
|
}
|
|
|
|
return all
|
|
}
|
|
|
|
// ExtractorStatus represents the status of an extractor
|
|
type ExtractorStatus struct {
|
|
Key string `json:"key"`
|
|
Name string `json:"name"`
|
|
SupportedMimeTypes []string `json:"supported_mime_types"`
|
|
Available bool `json:"available"`
|
|
ErrorMessage string `json:"error_message,omitempty"`
|
|
}
|
|
|
|
// GetStatus returns status information for all registered extractors
|
|
func (m *Manager) GetStatus() []ExtractorStatus {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
var statuses []ExtractorStatus
|
|
for _, status := range m.extractors {
|
|
statuses = append(statuses, ExtractorStatus{
|
|
Key: status.extractor.Key(),
|
|
Name: status.extractor.Name(),
|
|
SupportedMimeTypes: status.extractor.SupportedMimeTypes(),
|
|
Available: status.available,
|
|
ErrorMessage: status.errorMsg,
|
|
})
|
|
}
|
|
|
|
// Sort by name
|
|
sort.Slice(statuses, func(i, j int) bool {
|
|
return statuses[i].Name < statuses[j].Name
|
|
})
|
|
|
|
return statuses
|
|
}
|