Files
plugins/plugin.go

1868 lines
46 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package plugins
import (
"context"
"encoding/json"
"fmt"
"io/fs"
"log"
"os"
"path/filepath"
"plugin"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"time"
)
// PluginInfo 插件信息
type PluginInfo struct {
Name string `json:"name"`
Version string `json:"version"`
Description string `json:"description"`
Author string `json:"author"`
Type PluginType `json:"type"`
Enabled bool `json:"enabled"`
Config map[string]interface{} `json:"config,omitempty"`
}
// PluginManager 插件管理器
type PluginManager struct {
pluginsDir string
plugins map[string]IPlugin
pluginsByType map[PluginType]map[string]IPlugin
configs map[string]map[string]interface{}
mu sync.RWMutex
dynamicLoadingSupported bool // 是否支持动态加载插件
eventHandlers map[PluginEventType][]PluginEventHandler // 全局事件处理器
}
// NewPluginManager 创建插件管理器
func NewPluginManager(pluginsDir string) *PluginManager {
// 检查当前系统是否支持动态加载插件
dynamicLoadingSupported := runtime.GOOS == "linux" || runtime.GOOS == "darwin"
return &PluginManager{
pluginsDir: pluginsDir,
plugins: make(map[string]IPlugin),
pluginsByType: make(map[PluginType]map[string]IPlugin),
configs: make(map[string]map[string]interface{}),
dynamicLoadingSupported: dynamicLoadingSupported,
eventHandlers: make(map[PluginEventType][]PluginEventHandler),
}
}
// IsDynamicLoadingSupported 检查是否支持动态加载插件
func (pm *PluginManager) IsDynamicLoadingSupported() bool {
return pm.dynamicLoadingSupported
}
// LoadPlugins 加载插件
func (pm *PluginManager) LoadPlugins() error {
// 确保插件目录存在
if err := os.MkdirAll(pm.pluginsDir, 0o755); err != nil {
return fmt.Errorf("创建插件目录失败: %v", err)
}
// 加载插件配置
if err := pm.loadPluginConfigs(); err != nil {
return fmt.Errorf("加载插件配置失败: %v", err)
}
// 如果不支持动态加载,则返回
if !pm.dynamicLoadingSupported {
fmt.Printf("警告: 当前系统(%s)不支持动态加载插件,跳过加载\n", runtime.GOOS)
return nil
}
// 遍历插件目录
err := filepath.Walk(pm.pluginsDir, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
// 跳过目录和非.so文件
if info.IsDir() || filepath.Ext(path) != ".so" {
return nil
}
// 加载插件
if err := pm.loadPlugin(path); err != nil {
fmt.Printf("加载插件 %s 失败: %v\n", path, err)
}
return nil
})
return err
}
// loadPluginConfigs 加载插件配置
func (pm *PluginManager) loadPluginConfigs() error {
configPath := filepath.Join(pm.pluginsDir, "plugins.json")
// 先检查配置文件是否存在
_, err := os.Stat(configPath)
if os.IsNotExist(err) {
// 配置文件不存在,创建一个空的
// 注意这里的文件IO操作在锁之外执行
file, err := os.Create(configPath)
if err != nil {
return fmt.Errorf("创建插件配置文件失败: %v", err)
}
file.Write([]byte("{}"))
file.Close()
// 初始化空配置
pm.mu.Lock()
pm.configs = make(map[string]map[string]interface{})
pm.mu.Unlock()
return nil
} else if err != nil {
return fmt.Errorf("检查插件配置文件状态失败: %v", err)
}
// 读取配置文件 - 在锁之外执行IO操作
data, err := os.ReadFile(configPath)
if err != nil {
return fmt.Errorf("读取插件配置文件失败: %v", err)
}
// 解析配置
var configs map[string]map[string]interface{}
if err := json.Unmarshal(data, &configs); err != nil {
return fmt.Errorf("解析插件配置文件失败: %v", err)
}
// 最后才用锁更新配置
pm.mu.Lock()
defer pm.mu.Unlock()
// 如果配置为nil初始化为空映射
if configs == nil {
configs = make(map[string]map[string]interface{})
}
pm.configs = configs
return nil
}
// savePluginConfigs 保存插件配置
func (pm *PluginManager) savePluginConfigs() error {
configPath := filepath.Join(pm.pluginsDir, "plugins.json")
// 创建配置数据的深度副本,使用读锁,减少锁持有时间
configs := make(map[string]map[string]interface{})
pm.mu.RLock()
// 复制所有插件的配置
for name, plugin := range pm.plugins {
config := make(map[string]interface{})
// 获取并复制现有配置
if existingConfig, ok := pm.configs[name]; ok {
for k, v := range existingConfig {
// 对于复杂类型,执行深度复制
switch val := v.(type) {
case map[string]interface{}:
nestedMap := make(map[string]interface{})
for nk, nv := range val {
nestedMap[nk] = nv
}
config[k] = nestedMap
case []interface{}:
nestedArray := make([]interface{}, len(val))
copy(nestedArray, val)
config[k] = nestedArray
default:
config[k] = v
}
}
}
// 添加基本信息
config["enabled"] = plugin.IsEnabled()
config["type"] = string(plugin.Type())
configs[name] = config
}
pm.mu.RUnlock()
// 在释放锁后执行所有IO操作
// 序列化配置
data, err := json.MarshalIndent(configs, "", " ")
if err != nil {
return fmt.Errorf("序列化插件配置失败: %v", err)
}
// 创建临时文件
tmpDir := filepath.Dir(configPath)
// 确保目录存在
if err := os.MkdirAll(tmpDir, 0755); err != nil {
return fmt.Errorf("创建配置目录失败: %v", err)
}
// 使用一个唯一的临时文件名
tmpFile := fmt.Sprintf("%s.%d.tmp", configPath, time.Now().UnixNano())
if err := os.WriteFile(tmpFile, data, 0o644); err != nil {
return fmt.Errorf("写入临时配置文件失败: %v", err)
}
// 重命名临时文件为正式文件(原子操作)
if err := os.Rename(tmpFile, configPath); err != nil {
// 如果重命名失败,确保清理临时文件
os.Remove(tmpFile)
return fmt.Errorf("更新配置文件失败: %v", err)
}
return nil
}
// CheckDependencies 检查插件依赖关系
func (pm *PluginManager) CheckDependencies(plugin IPlugin) error {
dependencies := plugin.Dependencies()
if len(dependencies) == 0 {
return nil // 没有依赖,直接返回
}
for _, dep := range dependencies {
depPlugin, exists := pm.plugins[dep.Name]
if !exists {
if dep.IsOptional {
continue // 可选依赖,忽略
}
return fmt.Errorf("依赖的插件 %s 不存在", dep.Name)
}
// 验证版本兼容性
if dep.MinVersion != "" || dep.MaxVersion != "" {
currentVersion := depPlugin.Version()
if dep.MinVersion != "" {
result, err := compareVersions(currentVersion, dep.MinVersion)
if err != nil {
return fmt.Errorf("版本比较错误: %v", err)
}
if result < 0 {
return fmt.Errorf("依赖插件 %s 版本 %s 低于最低版本要求 %s",
dep.Name, currentVersion, dep.MinVersion)
}
}
if dep.MaxVersion != "" {
result, err := compareVersions(currentVersion, dep.MaxVersion)
if err != nil {
return fmt.Errorf("版本比较错误: %v", err)
}
if result > 0 {
return fmt.Errorf("依赖插件 %s 版本 %s 高于最高版本要求 %s",
dep.Name, currentVersion, dep.MaxVersion)
}
}
}
// 检查依赖插件是否启用
if !depPlugin.IsEnabled() && !dep.IsOptional {
if dep.AutoDisableWith {
// 自动禁用当前插件
plugin.SetEnabled(false)
return fmt.Errorf("依赖插件 %s 已禁用,当前插件自动禁用", dep.Name)
}
return fmt.Errorf("依赖插件 %s 已禁用", dep.Name)
}
}
return nil
}
// InitializeWithDependencies 根据依赖关系初始化插件
func (pm *PluginManager) InitializeWithDependencies(ctx context.Context) error {
// 构建依赖图
dependencyGraph := make(map[string][]string)
pluginDeps := make(map[string][]PluginDependency)
pm.mu.RLock()
for name, plugin := range pm.plugins {
if !plugin.IsEnabled() {
continue
}
deps := plugin.Dependencies()
pluginDeps[name] = deps
dependencyGraph[name] = []string{}
for _, dep := range deps {
if !dep.IsOptional && dep.InitAfter {
dependencyGraph[name] = append(dependencyGraph[name], dep.Name)
}
}
}
pm.mu.RUnlock()
// 拓扑排序
initOrder, err := topologicalSort(dependencyGraph)
if err != nil {
return fmt.Errorf("解析依赖关系失败: %v", err)
}
// 按依赖顺序初始化插件
for _, name := range initOrder {
pm.mu.RLock()
plugin, exists := pm.plugins[name]
config := pm.configs[name]
pm.mu.RUnlock()
if !exists || !plugin.IsEnabled() {
continue
}
if err := plugin.Init(ctx, config); err != nil {
return fmt.Errorf("初始化插件 %s 失败: %v", name, err)
}
}
return nil
}
// SubscribeEvent 订阅全局插件事件
func (pm *PluginManager) SubscribeEvent(eventType PluginEventType, handler PluginEventHandler) {
pm.mu.Lock()
defer pm.mu.Unlock()
if pm.eventHandlers[eventType] == nil {
pm.eventHandlers[eventType] = []PluginEventHandler{}
}
pm.eventHandlers[eventType] = append(pm.eventHandlers[eventType], handler)
}
// UnsubscribeEvent 取消订阅全局插件事件
func (pm *PluginManager) UnsubscribeEvent(eventType PluginEventType, handler PluginEventHandler) {
pm.mu.Lock()
defer pm.mu.Unlock()
if handlers, exists := pm.eventHandlers[eventType]; exists {
for i, h := range handlers {
if fmt.Sprintf("%p", h) == fmt.Sprintf("%p", handler) {
pm.eventHandlers[eventType] = append(handlers[:i], handlers[i+1:]...)
break
}
}
}
}
// HandleEvent 处理全局插件事件
func (pm *PluginManager) HandleEvent(event PluginEvent) {
pm.mu.RLock()
defer pm.mu.RUnlock()
if handlers, exists := pm.eventHandlers[event.Type]; exists {
for _, handler := range handlers {
handler(event) // 忽略错误,不影响其他处理器
}
}
}
// BroadcastEvent 广播插件事件到所有处理器
func (pm *PluginManager) BroadcastEvent(event PluginEvent) {
// 先处理全局事件
pm.HandleEvent(event)
// 再传播到特定插件
if event.PluginID != "" {
pm.mu.RLock()
plugin, exists := pm.plugins[event.PluginID]
pm.mu.RUnlock()
if exists {
plugin.EmitEvent(event)
}
}
}
// 加载插件时的事件通知
func (pm *PluginManager) notifyPluginLoaded(plugin IPlugin) {
pm.BroadcastEvent(PluginEvent{
Type: PluginEventLoaded,
PluginID: plugin.Name(),
Timestamp: time.Now(),
Data: map[string]interface{}{
"name": plugin.Name(),
"version": plugin.Version(),
"type": plugin.Type(),
},
})
}
// loadPlugin 加载单个插件
func (pm *PluginManager) loadPlugin(path string) error {
if !strings.HasSuffix(path, ".so") && !strings.HasSuffix(path, ".dll") {
return nil
}
// 打开插件
plug, err := plugin.Open(path)
if err != nil {
return fmt.Errorf("打开插件失败: %v", err)
}
// 查找 Plugin 符号
symPlugin, err := plug.Lookup("Plugin")
if err != nil {
return fmt.Errorf("查找 Plugin 符号失败: %v", err)
}
// 尝试直接类型断言
fmt.Printf("插件类型: %T\n", symPlugin)
if p, ok := symPlugin.(IPlugin); ok {
pm.registerPlugin(p)
pm.notifyPluginLoaded(p)
return nil
}
// 直接类型断言失败,尝试通过反射获取值
fmt.Println("直接类型断言失败,尝试通过反射获取值")
// 获取原始插件值,用于存储在适配器中
origValue := reflect.ValueOf(symPlugin)
// 尝试在所有指针级别上查找方法
// 保存每一级指针值,用于查找方法
pointerValues := []reflect.Value{origValue}
currentValue := origValue
// 解引用并保存每一级指针
for currentValue.Kind() == reflect.Ptr && currentValue.Elem().IsValid() {
currentValue = currentValue.Elem()
pointerValues = append(pointerValues, currentValue)
}
// 尝试在不同级别的指针上查找Name和Version方法
var nameMethod reflect.Value
var versionMethod reflect.Value
var methodPointerLevel reflect.Value
for _, ptrValue := range pointerValues {
nm := ptrValue.MethodByName("Name")
vm := ptrValue.MethodByName("Version")
if nm.IsValid() && vm.IsValid() {
nameMethod = nm
versionMethod = vm
methodPointerLevel = ptrValue
break
}
}
if !nameMethod.IsValid() || !versionMethod.IsValid() {
return fmt.Errorf("插件缺少必需的方法: Name 或 Version")
}
// 调用 Name 和 Version 方法获取基本信息
nameResult := nameMethod.Call(nil)
versionResult := versionMethod.Call(nil)
if len(nameResult) == 0 || len(versionResult) == 0 {
return fmt.Errorf("插件方法返回无效结果")
}
pluginName := nameResult[0].String()
pluginVersion := versionResult[0].String()
fmt.Printf("找到插件: %s (版本 %s)\n", pluginName, pluginVersion)
// 创建适配器以包装插件
adapter := &PluginAdapter{
symPlugin: symPlugin,
pluginValue: methodPointerLevel, // 使用找到有效方法的指针级别
pluginName: pluginName,
pluginVersion: pluginVersion,
}
// 使用找到方法的同一级别指针值检查是否具有Execute方法
executeMethod := methodPointerLevel.MethodByName("Execute")
if !executeMethod.IsValid() {
fmt.Printf("插件未实现 Execute 方法,尝试查找特定操作方法\n")
// 查找常见的操作方法,如果找到,也可以认为是有效插件
methodFound := false
commonMethods := []string{"Log", "Info", "Error", "GetStat", "SaveFile", "LoadFile"}
for _, methodName := range commonMethods {
if method := methodPointerLevel.MethodByName(methodName); method.IsValid() {
methodFound = true
break
}
}
if !methodFound {
return fmt.Errorf("插件类型错误: 未实现 Execute 方法或任何已知的操作方法")
}
}
pm.registerPlugin(adapter)
pm.notifyPluginLoaded(adapter)
return nil
}
// registerPlugin 注册插件到插件管理器
func (pm *PluginManager) registerPlugin(plugin IPlugin) {
name := plugin.Name()
// 检查插件名称是否已存在
pm.mu.Lock()
defer pm.mu.Unlock()
if _, exists := pm.plugins[name]; exists {
log.Printf("警告: 插件 %s 已存在,将被覆盖", name)
}
// 设置插件启用状态
if config, exists := pm.configs[name]; exists {
if enabled, ok := config["enabled"].(bool); ok {
plugin.SetEnabled(enabled)
} else {
plugin.SetEnabled(true) // 默认启用
}
} else {
plugin.SetEnabled(true) // 默认启用
}
// 检查依赖关系
if err := pm.CheckDependencies(plugin); err != nil {
log.Printf("警告: 插件 %s 依赖检查失败: %v", name, err)
}
// 添加到插件映射
pm.plugins[name] = plugin
// 添加到类型映射
pluginType := plugin.Type()
if pm.pluginsByType[pluginType] == nil {
pm.pluginsByType[pluginType] = make(map[string]IPlugin)
}
pm.pluginsByType[pluginType][name] = plugin
log.Printf("插件 %s (类型: %s, 版本: %s) 已注册", name, pluginType, plugin.Version())
}
// RegisterPlugin 注册内置插件, 用于在不支持动态加载的平台上注册插件
func (pm *PluginManager) RegisterPlugin(plugin IPlugin) error {
pm.mu.Lock()
defer pm.mu.Unlock()
if _, exists := pm.plugins[plugin.Name()]; exists {
return fmt.Errorf("插件 %s 已存在", plugin.Name())
}
// 设置插件启用状态
if config, exists := pm.configs[plugin.Name()]; exists {
if enabled, ok := config["enabled"].(bool); ok {
plugin.SetEnabled(enabled)
} else {
plugin.SetEnabled(true) // 默认启用
}
} else {
plugin.SetEnabled(true) // 默认启用
}
// 检查依赖关系
if err := pm.CheckDependencies(plugin); err != nil {
return fmt.Errorf("依赖检查失败: %v", err)
}
// 注册插件
pm.registerPlugin(plugin)
// 通知插件已加载
go pm.notifyPluginLoaded(plugin)
return nil
}
// GetPlugin 获取插件
func (pm *PluginManager) GetPlugin(name string) (IPlugin, bool) {
pm.mu.RLock()
defer pm.mu.RUnlock()
plugin, exists := pm.plugins[name]
return plugin, exists
}
// GetPluginsByType 按类型获取插件
func (pm *PluginManager) GetPluginsByType(pluginType PluginType) []IPlugin {
pm.mu.RLock()
defer pm.mu.RUnlock()
plugins := make([]IPlugin, 0)
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
for _, plugin := range typePlugins {
if plugin.IsEnabled() {
plugins = append(plugins, plugin)
}
}
}
return plugins
}
// GetAllPluginsByType 获取所有指定类型的插件,无论是否启用
func (pm *PluginManager) GetAllPluginsByType(pluginType PluginType) []IPlugin {
pm.mu.RLock()
defer pm.mu.RUnlock()
plugins := make([]IPlugin, 0)
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
for _, plugin := range typePlugins {
plugins = append(plugins, plugin)
}
}
return plugins
}
// GetAllPlugins 获取所有插件
func (pm *PluginManager) GetAllPlugins() []IPlugin {
pm.mu.RLock()
defer pm.mu.RUnlock()
plugins := make([]IPlugin, 0, len(pm.plugins))
for _, plugin := range pm.plugins {
plugins = append(plugins, plugin)
}
return plugins
}
// GetPluginInfos 获取所有插件信息
func (pm *PluginManager) GetPluginInfos() []PluginInfo {
pm.mu.RLock()
defer pm.mu.RUnlock()
infos := make([]PluginInfo, 0, len(pm.plugins))
for name, plugin := range pm.plugins {
info := PluginInfo{
Name: plugin.Name(),
Version: plugin.Version(),
Description: plugin.Description(),
Author: plugin.Author(),
Type: plugin.Type(),
Enabled: plugin.IsEnabled(),
Config: pm.configs[name],
}
infos = append(infos, info)
}
return infos
}
// GetPluginInfosByType 按类型获取插件信息
func (pm *PluginManager) GetPluginInfosByType(pluginType PluginType) []PluginInfo {
pm.mu.RLock()
defer pm.mu.RUnlock()
infos := make([]PluginInfo, 0)
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
for name, plugin := range typePlugins {
info := PluginInfo{
Name: plugin.Name(),
Version: plugin.Version(),
Description: plugin.Description(),
Author: plugin.Author(),
Type: plugin.Type(),
Enabled: plugin.IsEnabled(),
Config: pm.configs[name],
}
infos = append(infos, info)
}
}
return infos
}
// EnablePlugin 启用插件
func (pm *PluginManager) EnablePlugin(name string) error {
// 先获取插件,避免长时间持有锁
pm.mu.RLock()
plugin, exists := pm.plugins[name]
pm.mu.RUnlock()
if !exists {
return fmt.Errorf("插件 %s 不存在", name)
}
// 设置插件状态
plugin.SetEnabled(true)
// 更新配置
config := make(map[string]interface{})
pm.mu.RLock()
if existingConfig, ok := pm.configs[name]; ok {
// 复制现有配置
for k, v := range existingConfig {
config[k] = v
}
}
pm.mu.RUnlock()
config["enabled"] = true
// 使用单独的锁来更新配置
pm.mu.Lock()
pm.configs[name] = config
pm.mu.Unlock()
// 保存配置到文件
return pm.savePluginConfigs()
}
// DisablePlugin 禁用插件
func (pm *PluginManager) DisablePlugin(name string) error {
// 先获取插件,避免长时间持有锁
pm.mu.RLock()
plugin, exists := pm.plugins[name]
pm.mu.RUnlock()
if !exists {
return fmt.Errorf("插件 %s 不存在", name)
}
// 设置插件状态
plugin.SetEnabled(false)
// 更新配置
config := make(map[string]interface{})
pm.mu.RLock()
if existingConfig, ok := pm.configs[name]; ok {
// 复制现有配置
for k, v := range existingConfig {
config[k] = v
}
}
pm.mu.RUnlock()
config["enabled"] = false
// 使用单独的锁来更新配置
pm.mu.Lock()
pm.configs[name] = config
pm.mu.Unlock()
// 保存配置到文件
return pm.savePluginConfigs()
}
// InitPlugins 初始化所有插件
func (pm *PluginManager) InitPlugins(ctx context.Context) error {
// 使用基于依赖的初始化
return pm.InitializeWithDependencies(ctx)
}
// InitPluginsByType 初始化指定类型的所有插件
func (pm *PluginManager) InitPluginsByType(ctx context.Context, pluginType PluginType) error {
pm.mu.RLock()
defer pm.mu.RUnlock()
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
for name, plugin := range typePlugins {
if !plugin.IsEnabled() {
continue
}
config := pm.configs[name]
if err := plugin.Init(ctx, config); err != nil {
return fmt.Errorf("初始化插件 %s 失败: %v", name, err)
}
}
}
return nil
}
// StartPlugins 启动所有插件
func (pm *PluginManager) StartPlugins(ctx context.Context) error {
pm.mu.RLock()
defer pm.mu.RUnlock()
for name, plugin := range pm.plugins {
if !plugin.IsEnabled() {
continue
}
if err := plugin.Start(ctx); err != nil {
return fmt.Errorf("启动插件 %s 失败: %v", name, err)
}
}
return nil
}
// StartPluginsByType 启动指定类型的所有插件
func (pm *PluginManager) StartPluginsByType(ctx context.Context, pluginType PluginType) error {
pm.mu.RLock()
defer pm.mu.RUnlock()
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
for name, plugin := range typePlugins {
if !plugin.IsEnabled() {
continue
}
if err := plugin.Start(ctx); err != nil {
return fmt.Errorf("启动插件 %s 失败: %v", name, err)
}
}
}
return nil
}
// StopPlugins 停止所有插件
func (pm *PluginManager) StopPlugins(ctx context.Context) error {
pm.mu.RLock()
defer pm.mu.RUnlock()
for name, plugin := range pm.plugins {
if !plugin.IsEnabled() {
continue
}
if err := plugin.Stop(ctx); err != nil {
return fmt.Errorf("停止插件 %s 失败: %v", name, err)
}
}
return nil
}
// StopPluginsByType 停止指定类型的所有插件
func (pm *PluginManager) StopPluginsByType(ctx context.Context, pluginType PluginType) error {
pm.mu.RLock()
defer pm.mu.RUnlock()
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
for name, plugin := range typePlugins {
if !plugin.IsEnabled() {
continue
}
if err := plugin.Stop(ctx); err != nil {
return fmt.Errorf("停止插件 %s 失败: %v", name, err)
}
}
}
return nil
}
// SetPluginConfig 设置插件配置
func (pm *PluginManager) SetPluginConfig(name string, config map[string]interface{}) error {
// 先检查插件是否存在,使用读锁
pm.mu.RLock()
_, exists := pm.plugins[name]
pm.mu.RUnlock()
if !exists {
return fmt.Errorf("插件 %s 不存在", name)
}
// 创建配置的深度副本
configCopy := make(map[string]interface{})
for k, v := range config {
// 对复杂类型进行深度复制
switch val := v.(type) {
case map[string]interface{}:
// 复制嵌套的map
nestedMap := make(map[string]interface{})
for nk, nv := range val {
nestedMap[nk] = nv
}
configCopy[k] = nestedMap
case []interface{}:
// 复制数组
nestedArray := make([]interface{}, len(val))
copy(nestedArray, val)
configCopy[k] = nestedArray
default:
// 简单类型直接复制
configCopy[k] = v
}
}
// 使用写锁更新配置,但尽量减少锁持有时间
pm.mu.Lock()
pm.configs[name] = configCopy
pm.mu.Unlock()
// 创建一个带有超时的上下文
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// 使用 channel 来处理保存操作
errChan := make(chan error, 1)
go func() {
errChan <- pm.savePluginConfigs()
}()
// 等待保存完成或超时
select {
case err := <-errChan:
return err
case <-ctx.Done():
return fmt.Errorf("保存配置超时")
}
}
// GetPluginConfig 获取插件配置
func (pm *PluginManager) GetPluginConfig(name string) (map[string]interface{}, error) {
pm.mu.RLock()
defer pm.mu.RUnlock()
if _, exists := pm.plugins[name]; !exists {
return nil, fmt.Errorf("插件 %s 不存在", name)
}
// 确保存在配置
config := pm.configs[name]
if config == nil {
return make(map[string]interface{}), nil
}
// 创建配置的深度副本
result := make(map[string]interface{})
for k, v := range config {
// 对复杂类型进行深度复制
switch val := v.(type) {
case map[string]interface{}:
// 复制嵌套的map
nestedMap := make(map[string]interface{})
for nk, nv := range val {
nestedMap[nk] = nv
}
result[k] = nestedMap
case []interface{}:
// 复制数组
nestedArray := make([]interface{}, len(val))
copy(nestedArray, val)
result[k] = nestedArray
default:
// 简单类型直接复制
result[k] = v
}
}
return result, nil
}
// ExecutePlugin 执行指定插件的操作
func (pm *PluginManager) ExecutePlugin(ctx context.Context, name string, action string, params map[string]interface{}) (interface{}, error) {
pm.mu.RLock()
defer pm.mu.RUnlock()
plugin, exists := pm.plugins[name]
if !exists {
return nil, fmt.Errorf("插件 %s 不存在", name)
}
if !plugin.IsEnabled() {
return nil, fmt.Errorf("插件 %s 已禁用", name)
}
return plugin.Execute(ctx, action, params)
}
// ExecutePluginsByType 对指定类型的所有插件执行操作
func (pm *PluginManager) ExecutePluginsByType(ctx context.Context, pluginType PluginType, action string, params map[string]interface{}) map[string]interface{} {
pm.mu.RLock()
defer pm.mu.RUnlock()
results := make(map[string]interface{})
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
for name, plugin := range typePlugins {
if !plugin.IsEnabled() {
continue
}
result, err := plugin.Execute(ctx, action, params)
results[name] = map[string]interface{}{
"result": result,
"error": err,
}
}
}
return results
}
// ExecuteAllPlugins 对所有插件执行操作
func (pm *PluginManager) ExecuteAllPlugins(ctx context.Context, action string, params map[string]interface{}) map[string]interface{} {
pm.mu.RLock()
defer pm.mu.RUnlock()
results := make(map[string]interface{})
for name, plugin := range pm.plugins {
if !plugin.IsEnabled() {
continue
}
result, err := plugin.Execute(ctx, action, params)
results[name] = map[string]interface{}{
"result": result,
"error": err,
}
}
return results
}
// GetPluginOperationInfo 获取插件特定操作的参数信息
func (pm *PluginManager) GetPluginOperationInfo(name string, operation string) (*OperationInfo, error) {
pm.mu.RLock()
defer pm.mu.RUnlock()
plugin, exists := pm.plugins[name]
if !exists {
return nil, fmt.Errorf("插件 %s 不存在", name)
}
if !plugin.IsEnabled() {
return nil, fmt.Errorf("插件 %s 已禁用", name)
}
return plugin.GetOperationInfo(operation)
}
// GetPluginAllOperations 获取插件所有操作及其参数信息
func (pm *PluginManager) GetPluginAllOperations(name string) (*PluginOperations, error) {
pm.mu.RLock()
defer pm.mu.RUnlock()
plugin, exists := pm.plugins[name]
if !exists {
return nil, fmt.Errorf("插件 %s 不存在", name)
}
if !plugin.IsEnabled() {
return nil, fmt.Errorf("插件 %s 已禁用", name)
}
ops := plugin.GetAllOperations()
return &PluginOperations{
PluginName: plugin.Name(),
PluginType: plugin.Type(),
Operations: ops,
}, nil
}
// GetOperationsByType 获取指定类型插件的所有操作信息
func (pm *PluginManager) GetOperationsByType(pluginType PluginType) []*PluginOperations {
pm.mu.RLock()
defer pm.mu.RUnlock()
result := make([]*PluginOperations, 0)
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
for _, plugin := range typePlugins {
if !plugin.IsEnabled() {
continue
}
ops := plugin.GetAllOperations()
result = append(result, &PluginOperations{
PluginName: plugin.Name(),
PluginType: plugin.Type(),
Operations: ops,
})
}
}
return result
}
// GetAllPluginsOperations 获取所有插件的所有操作信息
func (pm *PluginManager) GetAllPluginsOperations() []*PluginOperations {
pm.mu.RLock()
defer pm.mu.RUnlock()
result := make([]*PluginOperations, 0, len(pm.plugins))
for _, plugin := range pm.plugins {
if !plugin.IsEnabled() {
continue
}
ops := plugin.GetAllOperations()
result = append(result, &PluginOperations{
PluginName: plugin.Name(),
PluginType: plugin.Type(),
Operations: ops,
})
}
return result
}
// ReloadPlugin 重新加载单个插件
func (pm *PluginManager) ReloadPlugin(ctx context.Context, name string) error {
pm.mu.Lock()
plugin, exists := pm.plugins[name]
config := pm.configs[name]
pm.mu.Unlock()
if !exists {
return fmt.Errorf("插件 %s 不存在", name)
}
// 发出重载事件
pm.BroadcastEvent(PluginEvent{
Type: PluginEventCustom,
PluginID: name,
Timestamp: time.Now(),
Data: map[string]interface{}{
"action": "reloading",
},
})
// 执行重载
if err := plugin.Reload(ctx, config); err != nil {
// 发送错误事件
pm.BroadcastEvent(PluginEvent{
Type: PluginEventError,
PluginID: name,
Timestamp: time.Now(),
Data: map[string]interface{}{
"error": err.Error(),
"context": "reload",
},
})
return fmt.Errorf("重载插件 %s 失败: %v", name, err)
}
// 发送重载完成事件
pm.BroadcastEvent(PluginEvent{
Type: PluginEventCustom,
PluginID: name,
Timestamp: time.Now(),
Data: map[string]interface{}{
"action": "reloaded",
},
})
return nil
}
// ReloadAllPlugins 重新加载所有插件
func (pm *PluginManager) ReloadAllPlugins(ctx context.Context) map[string]error {
errors := make(map[string]error)
pm.mu.RLock()
pluginNames := make([]string, 0, len(pm.plugins))
for name := range pm.plugins {
pluginNames = append(pluginNames, name)
}
pm.mu.RUnlock()
for _, name := range pluginNames {
if err := pm.ReloadPlugin(ctx, name); err != nil {
errors[name] = err
}
}
return errors
}
// InstallErrorHandler 为插件安装错误处理器
func (pm *PluginManager) InstallErrorHandler() {
pm.SubscribeEvent(PluginEventError, func(event PluginEvent) error {
errData, ok := event.Data["error"].(string)
if !ok {
errData = "未知错误"
}
context, _ := event.Data["context"].(string)
if context == "" {
context = "general"
}
fmt.Printf("[错误] 插件 %s 在 %s 上下文中发生错误: %s\n",
event.PluginID, context, errData)
return nil
})
}
// RecoverPlugin 尝试恢复错误状态的插件
func (pm *PluginManager) RecoverPlugin(ctx context.Context, name string) error {
pm.mu.Lock()
plugin, exists := pm.plugins[name]
config := pm.configs[name]
pm.mu.Unlock()
if !exists {
return fmt.Errorf("插件 %s 不存在", name)
}
if plugin.Status() != PluginStatusError {
return nil // 插件不在错误状态,无需恢复
}
// 尝试清理、重新初始化和启动
if err := plugin.Cleanup(ctx); err != nil {
return fmt.Errorf("清理插件失败: %v", err)
}
if err := plugin.Init(ctx, config); err != nil {
return fmt.Errorf("重新初始化插件失败: %v", err)
}
if plugin.IsEnabled() {
if err := plugin.Start(ctx); err != nil {
return fmt.Errorf("重新启动插件失败: %v", err)
}
}
// 发送恢复事件
pm.BroadcastEvent(PluginEvent{
Type: PluginEventCustom,
PluginID: name,
Timestamp: time.Now(),
Data: map[string]interface{}{
"action": "recovered",
},
})
return nil
}
// RecoverAllPlugins 尝试恢复所有错误状态的插件
func (pm *PluginManager) RecoverAllPlugins(ctx context.Context) map[string]error {
errors := make(map[string]error)
pm.mu.RLock()
plugins := make([]IPlugin, 0)
for _, plugin := range pm.plugins {
if plugin.Status() == PluginStatusError {
plugins = append(plugins, plugin)
}
}
pm.mu.RUnlock()
for _, plugin := range plugins {
name := plugin.Name()
if err := pm.RecoverPlugin(ctx, name); err != nil {
errors[name] = err
}
}
return errors
}
// UnloadPlugin 卸载插件
func (pm *PluginManager) UnloadPlugin(ctx context.Context, name string) error {
pm.mu.Lock()
defer pm.mu.Unlock()
plugin, exists := pm.plugins[name]
if !exists {
return fmt.Errorf("插件 %s 不存在", name)
}
// 检查是否有其他插件依赖该插件
for otherName, otherPlugin := range pm.plugins {
if otherName == name {
continue
}
for _, dep := range otherPlugin.Dependencies() {
if dep.Name == name && !dep.IsOptional {
return fmt.Errorf("无法卸载插件 %s: 插件 %s 依赖它", name, otherName)
}
}
}
// 停止并清理插件
if plugin.Status() == PluginStatusRunning {
if err := plugin.Stop(ctx); err != nil {
return fmt.Errorf("停止插件失败: %v", err)
}
}
if err := plugin.Cleanup(ctx); err != nil {
return fmt.Errorf("清理插件失败: %v", err)
}
// 从管理器中移除插件
delete(pm.plugins, name)
if typePlugins, exists := pm.pluginsByType[plugin.Type()]; exists {
delete(typePlugins, name)
}
// 发送卸载事件
pm.BroadcastEvent(PluginEvent{
Type: PluginEventCustom,
PluginID: name,
Timestamp: time.Now(),
Data: map[string]interface{}{
"action": "unloaded",
},
})
return nil
}
// topologicalSort 拓扑排序,解决依赖顺序问题
func topologicalSort(graph map[string][]string) ([]string, error) {
result := make([]string, 0, len(graph))
visited := make(map[string]bool)
temp := make(map[string]bool)
var visit func(string) error
visit = func(node string) error {
if temp[node] {
return fmt.Errorf("检测到循环依赖: %s", node)
}
if visited[node] {
return nil
}
temp[node] = true
for _, dep := range graph[node] {
if err := visit(dep); err != nil {
return err
}
}
temp[node] = false
visited[node] = true
result = append(result, node)
return nil
}
for node := range graph {
if !visited[node] {
if err := visit(node); err != nil {
return nil, err
}
}
}
return result, nil
}
// 简单的版本比较函数
func compareVersions(v1, v2 string) (int, error) {
// 移除可能的'v'前缀
v1 = strings.TrimPrefix(v1, "v")
v2 = strings.TrimPrefix(v2, "v")
// 分割版本号
parts1 := strings.Split(v1, ".")
parts2 := strings.Split(v2, ".")
// 确保有足够的部分进行比较
for len(parts1) < 3 {
parts1 = append(parts1, "0")
}
for len(parts2) < 3 {
parts2 = append(parts2, "0")
}
// 比较各部分
for i := 0; i < 3; i++ {
n1, err := strconv.Atoi(parts1[i])
if err != nil {
return 0, fmt.Errorf("无效的版本号部分 %s: %v", parts1[i], err)
}
n2, err := strconv.Atoi(parts2[i])
if err != nil {
return 0, fmt.Errorf("无效的版本号部分 %s: %v", parts2[i], err)
}
if n1 < n2 {
return -1, nil // v1 < v2
} else if n1 > n2 {
return 1, nil // v1 > v2
}
}
return 0, nil // v1 == v2
}
// PluginAdapter 插件适配器
// 用于将通过反射获取的插件包装为 IPlugin 接口
type PluginAdapter struct {
symPlugin interface{}
pluginValue reflect.Value
pluginName string
pluginVersion string
}
// Name 获取插件名称
func (p *PluginAdapter) Name() string {
return p.pluginName
}
// Version 获取插件版本
func (p *PluginAdapter) Version() string {
return p.pluginVersion
}
// Description 获取插件描述
func (p *PluginAdapter) Description() string {
method := p.pluginValue.MethodByName("Description")
if !method.IsValid() {
return "未提供描述"
}
return method.Call(nil)[0].String()
}
// Author 获取插件作者
func (p *PluginAdapter) Author() string {
method := p.pluginValue.MethodByName("Author")
if !method.IsValid() {
return "未知作者"
}
return method.Call(nil)[0].String()
}
// Type 获取插件类型
func (p *PluginAdapter) Type() PluginType {
method := p.pluginValue.MethodByName("Type")
if !method.IsValid() {
return PluginTypeGeneral
}
return PluginType(method.Call(nil)[0].String())
}
// Status 获取插件状态
func (p *PluginAdapter) Status() PluginStatus {
method := p.pluginValue.MethodByName("Status")
if !method.IsValid() {
return PluginStatusUninitialized
}
return PluginStatus(method.Call(nil)[0].String())
}
// Dependencies 获取插件依赖
func (p *PluginAdapter) Dependencies() []PluginDependency {
method := p.pluginValue.MethodByName("Dependencies")
if !method.IsValid() {
return []PluginDependency{}
}
result := method.Call(nil)[0]
if result.IsNil() {
return []PluginDependency{}
}
// 尝试直接类型断言
if dependencies, ok := result.Interface().([]PluginDependency); ok {
return dependencies
}
// 尝试使用反射迭代切片并转换每个元素
if result.Kind() == reflect.Slice {
length := result.Len()
dependencies := make([]PluginDependency, 0, length)
for i := 0; i < length; i++ {
item := result.Index(i).Interface()
// 尝试将元素转换为PluginDependency
if dep, ok := item.(PluginDependency); ok {
dependencies = append(dependencies, dep)
} else {
// 如果无法直接转换,尝试使用反射读取字段
depValue := reflect.ValueOf(item)
if depValue.Kind() == reflect.Struct || (depValue.Kind() == reflect.Ptr && depValue.Elem().Kind() == reflect.Struct) {
// 解引用指针
if depValue.Kind() == reflect.Ptr {
depValue = depValue.Elem()
}
dependency := PluginDependency{}
// 获取字段值
if nameField := depValue.FieldByName("Name"); nameField.IsValid() {
dependency.Name = nameField.String()
}
if minVersionField := depValue.FieldByName("MinVersion"); minVersionField.IsValid() {
dependency.MinVersion = minVersionField.String()
}
if maxVersionField := depValue.FieldByName("MaxVersion"); maxVersionField.IsValid() {
dependency.MaxVersion = maxVersionField.String()
}
if isOptionalField := depValue.FieldByName("IsOptional"); isOptionalField.IsValid() && isOptionalField.Kind() == reflect.Bool {
dependency.IsOptional = isOptionalField.Bool()
}
if loadAfterField := depValue.FieldByName("LoadAfter"); loadAfterField.IsValid() && loadAfterField.Kind() == reflect.Bool {
dependency.LoadAfter = loadAfterField.Bool()
}
if initAfterField := depValue.FieldByName("InitAfter"); initAfterField.IsValid() && initAfterField.Kind() == reflect.Bool {
dependency.InitAfter = initAfterField.Bool()
}
if strictVersionsField := depValue.FieldByName("StrictVersions"); strictVersionsField.IsValid() && strictVersionsField.Kind() == reflect.Bool {
dependency.StrictVersions = strictVersionsField.Bool()
}
if autoDisableWithField := depValue.FieldByName("AutoDisableWith"); autoDisableWithField.IsValid() && autoDisableWithField.Kind() == reflect.Bool {
dependency.AutoDisableWith = autoDisableWithField.Bool()
}
dependencies = append(dependencies, dependency)
}
}
}
return dependencies
}
return []PluginDependency{}
}
// Init 初始化插件
func (p *PluginAdapter) Init(ctx context.Context, config map[string]interface{}) error {
method := p.pluginValue.MethodByName("Init")
if !method.IsValid() {
fmt.Printf("插件 %s 没有 Init 方法,跳过初始化\n", p.Name())
return nil
}
args := []reflect.Value{
reflect.ValueOf(ctx),
reflect.ValueOf(config),
}
result := method.Call(args)
if len(result) > 0 && !result[0].IsNil() {
return result[0].Interface().(error)
}
return nil
}
// Start 启动插件
func (p *PluginAdapter) Start(ctx context.Context) error {
method := p.pluginValue.MethodByName("Start")
if !method.IsValid() {
fmt.Printf("插件 %s 没有 Start 方法,跳过启动\n", p.Name())
return nil
}
args := []reflect.Value{
reflect.ValueOf(ctx),
}
result := method.Call(args)
if len(result) > 0 && !result[0].IsNil() {
return result[0].Interface().(error)
}
return nil
}
// Stop 停止插件
func (p *PluginAdapter) Stop(ctx context.Context) error {
method := p.pluginValue.MethodByName("Stop")
if !method.IsValid() {
return fmt.Errorf("插件未实现 Stop 方法")
}
args := []reflect.Value{
reflect.ValueOf(ctx),
}
result := method.Call(args)
if len(result) > 0 && !result[0].IsNil() {
return result[0].Interface().(error)
}
return nil
}
// IsEnabled 插件是否启用
func (p *PluginAdapter) IsEnabled() bool {
method := p.pluginValue.MethodByName("IsEnabled")
if !method.IsValid() {
return true
}
return method.Call(nil)[0].Bool()
}
// SetEnabled 设置插件启用状态
func (p *PluginAdapter) SetEnabled(enabled bool) {
method := p.pluginValue.MethodByName("SetEnabled")
if !method.IsValid() {
return
}
args := []reflect.Value{
reflect.ValueOf(enabled),
}
method.Call(args)
}
// GetOperationInfo 获取操作的参数信息
func (p *PluginAdapter) GetOperationInfo(operation string) (*OperationInfo, error) {
method := p.pluginValue.MethodByName("GetOperationInfo")
if !method.IsValid() {
return nil, fmt.Errorf("插件未实现 GetOperationInfo 方法")
}
args := []reflect.Value{
reflect.ValueOf(operation),
}
result := method.Call(args)
if len(result) > 1 && !result[1].IsNil() {
return nil, result[1].Interface().(error)
}
if result[0].IsNil() {
return nil, nil
}
// 尝试直接类型断言
if opInfo, ok := result[0].Interface().(*OperationInfo); ok {
return opInfo, nil
}
// 如果直接断言失败,尝试使用反射获取字段值
opValue := reflect.Indirect(result[0])
if opValue.Kind() != reflect.Struct {
// 如果不是结构体,返回基本信息
return &OperationInfo{
Name: operation,
Description: "通过适配器调用的操作",
Params: []OperationParamInfo{},
}, nil
}
// 创建操作信息对象
opInfo := &OperationInfo{
Name: operation,
Description: "",
Params: []OperationParamInfo{},
Extra: make(map[string]interface{}),
}
// 获取描述字段
if descField := opValue.FieldByName("Description"); descField.IsValid() && descField.Kind() == reflect.String {
opInfo.Description = descField.String()
}
// 获取参数列表
if paramsField := opValue.FieldByName("Params"); paramsField.IsValid() && paramsField.Kind() == reflect.Slice {
length := paramsField.Len()
opInfo.Params = make([]OperationParamInfo, 0, length)
for i := 0; i < length; i++ {
paramValue := reflect.Indirect(paramsField.Index(i))
if paramValue.Kind() != reflect.Struct {
continue
}
param := OperationParamInfo{}
// 获取参数字段
if nameField := paramValue.FieldByName("Name"); nameField.IsValid() && nameField.Kind() == reflect.String {
param.Name = nameField.String()
}
if typeField := paramValue.FieldByName("Type"); typeField.IsValid() && typeField.Kind() == reflect.String {
param.Type = typeField.String()
}
if requiredField := paramValue.FieldByName("Required"); requiredField.IsValid() && requiredField.Kind() == reflect.Bool {
param.Required = requiredField.Bool()
}
if defaultField := paramValue.FieldByName("Default"); defaultField.IsValid() {
param.Default = defaultField.Interface()
}
if descField := paramValue.FieldByName("Description"); descField.IsValid() && descField.Kind() == reflect.String {
param.Description = descField.String()
}
opInfo.Params = append(opInfo.Params, param)
}
}
// 获取额外信息
if extraField := opValue.FieldByName("Extra"); extraField.IsValid() && extraField.Kind() == reflect.Map {
for _, key := range extraField.MapKeys() {
if key.Kind() == reflect.String {
opInfo.Extra[key.String()] = extraField.MapIndex(key).Interface()
}
}
}
return opInfo, nil
}
// GetAllOperations 获取所有操作及其参数信息
func (p *PluginAdapter) GetAllOperations() []*OperationInfo {
method := p.pluginValue.MethodByName("GetAllOperations")
if !method.IsValid() {
return []*OperationInfo{}
}
result := method.Call(nil)[0]
if result.IsNil() {
return []*OperationInfo{}
}
// 解析返回的操作信息并返回
if operations, ok := result.Interface().([]*OperationInfo); ok {
return operations
}
// 尝试使用反射获取切片内容
if result.Kind() == reflect.Slice {
length := result.Len()
operations := make([]*OperationInfo, 0, length)
for i := 0; i < length; i++ {
item := result.Index(i).Interface()
if op, ok := item.(*OperationInfo); ok {
operations = append(operations, op)
}
}
return operations
}
// 如果无法解析,返回空数组
return []*OperationInfo{}
}
// Execute 执行插件功能
func (p *PluginAdapter) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
// 首先尝试调用 Execute 方法
method := p.pluginValue.MethodByName("Execute")
if method.IsValid() {
args := []reflect.Value{
reflect.ValueOf(ctx),
reflect.ValueOf(action),
reflect.ValueOf(params),
}
result := method.Call(args)
var retValue interface{}
var retError error
if len(result) > 0 && !result[0].IsNil() {
retValue = result[0].Interface()
}
if len(result) > 1 && !result[1].IsNil() {
retError = result[1].Interface().(error)
}
return retValue, retError
}
return nil, nil
}
// SubscribeEvent 订阅插件事件
func (p *PluginAdapter) SubscribeEvent(eventType PluginEventType, handler PluginEventHandler) {
method := p.pluginValue.MethodByName("SubscribeEvent")
if !method.IsValid() {
return
}
args := []reflect.Value{
reflect.ValueOf(eventType),
reflect.ValueOf(handler),
}
method.Call(args)
}
// UnsubscribeEvent 取消订阅插件事件
func (p *PluginAdapter) UnsubscribeEvent(eventType PluginEventType, handler PluginEventHandler) {
method := p.pluginValue.MethodByName("UnsubscribeEvent")
if !method.IsValid() {
return
}
args := []reflect.Value{
reflect.ValueOf(eventType),
reflect.ValueOf(handler),
}
method.Call(args)
}
// EmitEvent 发送插件事件
func (p *PluginAdapter) EmitEvent(event PluginEvent) error {
method := p.pluginValue.MethodByName("EmitEvent")
if !method.IsValid() {
return nil
}
args := []reflect.Value{
reflect.ValueOf(event),
}
result := method.Call(args)
if len(result) > 0 && !result[0].IsNil() {
return result[0].Interface().(error)
}
return nil
}
// Reload 重新加载插件
func (p *PluginAdapter) Reload(ctx context.Context, config map[string]interface{}) error {
method := p.pluginValue.MethodByName("Reload")
if !method.IsValid() {
// 默认实现:先停止,然后重新初始化和启动
if err := p.Stop(ctx); err != nil {
return fmt.Errorf("停止插件失败: %v", err)
}
if err := p.Init(ctx, config); err != nil {
return fmt.Errorf("重新初始化插件失败: %v", err)
}
if p.IsEnabled() {
if err := p.Start(ctx); err != nil {
return fmt.Errorf("重新启动插件失败: %v", err)
}
}
return nil
}
args := []reflect.Value{
reflect.ValueOf(ctx),
reflect.ValueOf(config),
}
result := method.Call(args)
if len(result) > 0 && !result[0].IsNil() {
return result[0].Interface().(error)
}
return nil
}
// Cleanup 清理插件资源
func (p *PluginAdapter) Cleanup(ctx context.Context) error {
method := p.pluginValue.MethodByName("Cleanup")
if !method.IsValid() {
// 默认实现:停止插件
if p.Status() == PluginStatusRunning {
return p.Stop(ctx)
}
return nil
}
args := []reflect.Value{
reflect.ValueOf(ctx),
}
result := method.Call(args)
if len(result) > 0 && !result[0].IsNil() {
return result[0].Interface().(error)
}
return nil
}