mirror of
https://github.com/navidrome/navidrome.git
synced 2025-08-10 00:52:20 +00:00
87 lines
2.6 KiB
Go
87 lines
2.6 KiB
Go
|
|
package plugins
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"maps"
|
||
|
|
"sync"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/navidrome/navidrome/conf"
|
||
|
|
"github.com/navidrome/navidrome/consts"
|
||
|
|
"github.com/navidrome/navidrome/log"
|
||
|
|
"github.com/navidrome/navidrome/plugins/api"
|
||
|
|
)
|
||
|
|
|
||
|
|
// pluginLifecycleManager tracks which plugins have been initialized and manages their lifecycle
|
||
|
|
type pluginLifecycleManager struct {
|
||
|
|
plugins sync.Map // string -> bool
|
||
|
|
config map[string]map[string]string
|
||
|
|
}
|
||
|
|
|
||
|
|
// newPluginLifecycleManager creates a new plugin lifecycle manager
|
||
|
|
func newPluginLifecycleManager() *pluginLifecycleManager {
|
||
|
|
config := maps.Clone(conf.Server.PluginConfig)
|
||
|
|
return &pluginLifecycleManager{
|
||
|
|
config: config,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// isInitialized checks if a plugin has been initialized
|
||
|
|
func (m *pluginLifecycleManager) isInitialized(plugin *plugin) bool {
|
||
|
|
key := plugin.ID + consts.Zwsp + plugin.Manifest.Version
|
||
|
|
value, exists := m.plugins.Load(key)
|
||
|
|
return exists && value.(bool)
|
||
|
|
}
|
||
|
|
|
||
|
|
// markInitialized marks a plugin as initialized
|
||
|
|
func (m *pluginLifecycleManager) markInitialized(plugin *plugin) {
|
||
|
|
key := plugin.ID + consts.Zwsp + plugin.Manifest.Version
|
||
|
|
m.plugins.Store(key, true)
|
||
|
|
}
|
||
|
|
|
||
|
|
// callOnInit calls the OnInit method on a plugin that implements LifecycleManagement
|
||
|
|
func (m *pluginLifecycleManager) callOnInit(plugin *plugin) {
|
||
|
|
ctx := context.Background()
|
||
|
|
log.Debug("Initializing plugin", "name", plugin.ID)
|
||
|
|
start := time.Now()
|
||
|
|
|
||
|
|
// Create LifecycleManagement plugin instance
|
||
|
|
loader, err := api.NewLifecycleManagementPlugin(ctx, api.WazeroRuntime(plugin.Runtime), api.WazeroModuleConfig(plugin.ModConfig))
|
||
|
|
if loader == nil || err != nil {
|
||
|
|
log.Error("Error creating LifecycleManagement plugin", "plugin", plugin.ID, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
initPlugin, err := loader.Load(ctx, plugin.WasmPath)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("Error loading LifecycleManagement plugin", "plugin", plugin.ID, "path", plugin.WasmPath, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
defer initPlugin.Close(ctx)
|
||
|
|
|
||
|
|
// Prepare the request with plugin-specific configuration
|
||
|
|
req := &api.InitRequest{}
|
||
|
|
|
||
|
|
// Add plugin configuration if available
|
||
|
|
if m.config != nil {
|
||
|
|
if pluginConfig, ok := m.config[plugin.ID]; ok && len(pluginConfig) > 0 {
|
||
|
|
req.Config = maps.Clone(pluginConfig)
|
||
|
|
log.Debug("Passing configuration to plugin", "plugin", plugin.ID, "configKeys", len(pluginConfig))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call OnInit
|
||
|
|
resp, err := initPlugin.OnInit(ctx, req)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("Error initializing plugin", "plugin", plugin.ID, "elapsed", time.Since(start), err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if resp.Error != "" {
|
||
|
|
log.Error("Plugin reported error during initialization", "plugin", plugin.ID, "error", resp.Error)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
log.Debug("Plugin initialized successfully", "plugin", plugin.ID, "elapsed", time.Since(start))
|
||
|
|
}
|