turash/bugulma/backend/internal/matching/plugins/registry.go
Damir Mukimov 000eab4740
Major repository reorganization and missing backend endpoints implementation
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools

Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
  * GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
  * GET /api/v1/users/me/organizations - User organizations
  * POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue

API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules

Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
2025-11-25 06:01:16 +01:00

108 lines
2.5 KiB
Go

package plugins
import (
"fmt"
"sync"
"bugulma/backend/internal/domain"
)
// Registry implements the PluginRegistry interface
type Registry struct {
plugins map[string]Plugin
byType map[domain.ResourceType][]Plugin
mutex sync.RWMutex
}
// NewRegistry creates a new plugin registry
func NewRegistry() *Registry {
return &Registry{
plugins: make(map[string]Plugin),
byType: make(map[domain.ResourceType][]Plugin),
}
}
// Register registers a plugin with the registry
func (r *Registry) Register(plugin Plugin) error {
r.mutex.Lock()
defer r.mutex.Unlock()
name := plugin.Name()
if _, exists := r.plugins[name]; exists {
return fmt.Errorf("plugin with name '%s' already registered", name)
}
r.plugins[name] = plugin
resourceType := plugin.ResourceType()
r.byType[resourceType] = append(r.byType[resourceType], plugin)
return nil
}
// GetByResourceType returns all plugins for a specific resource type
func (r *Registry) GetByResourceType(resourceType domain.ResourceType) []Plugin {
r.mutex.RLock()
defer r.mutex.RUnlock()
plugins, exists := r.byType[resourceType]
if !exists {
return []Plugin{}
}
// Return a copy to prevent external modification
result := make([]Plugin, len(plugins))
copy(result, plugins)
return result
}
// GetByName returns a plugin by its name
func (r *Registry) GetByName(name string) (Plugin, error) {
r.mutex.RLock()
defer r.mutex.RUnlock()
plugin, exists := r.plugins[name]
if !exists {
return nil, fmt.Errorf("plugin '%s' not found", name)
}
return plugin, nil
}
// ListAll returns all registered plugins
func (r *Registry) ListAll() []Plugin {
r.mutex.RLock()
defer r.mutex.RUnlock()
result := make([]Plugin, 0, len(r.plugins))
for _, plugin := range r.plugins {
result = append(result, plugin)
}
return result
}
// GetMetadata returns metadata for a plugin
func (r *Registry) GetMetadata(name string) (*PluginMetadata, error) {
plugin, err := r.GetByName(name)
if err != nil {
return nil, err
}
capabilities := []string{}
if plugin.SupportsQualityCheck() {
capabilities = append(capabilities, "quality_check")
}
if plugin.SupportsEconomicCalculation() {
capabilities = append(capabilities, "economic_calculation")
}
if plugin.SupportsTemporalCheck() {
capabilities = append(capabilities, "temporal_check")
}
return &PluginMetadata{
Name: plugin.Name(),
ResourceType: string(plugin.ResourceType()),
Capabilities: capabilities,
Description: fmt.Sprintf("Plugin for %s resource type", plugin.ResourceType()),
}, nil
}