增强插件系统:添加插件执行功能
- 在插件接口和基本插件实现中新增 Execute 方法,支持插件功能的动态执行。 - 更新各个插件(如日志插件、统计插件、存储插件等)以实现 Execute 方法,允许通过操作名称和参数执行特定功能。 - 在插件管理器中添加 ExecutePlugin、ExecutePluginsByType 和 ExecuteAllPlugins 方法,便于批量执行插件操作。 - 示例程序中更新插件调用方式,展示如何使用 Execute 方法进行操作。 此更新提升了插件系统的灵活性和可扩展性,便于开发者动态管理和执行插件功能。
This commit is contained in:
133
examples/plugin/example/dynamic_params.go
Normal file
133
examples/plugin/example/dynamic_params.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/darkit/goproxy/examples/plugin"
|
||||
)
|
||||
|
||||
// 演示动态参数传递功能
|
||||
func DynamicParamsExample() {
|
||||
// 创建上下文
|
||||
ctx := context.Background()
|
||||
|
||||
// 获取插件目录
|
||||
pluginsDir := filepath.Join("..", "plugins", "dist")
|
||||
if _, err := os.Stat(pluginsDir); os.IsNotExist(err) {
|
||||
fmt.Printf("插件目录不存在: %s\n", pluginsDir)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建插件管理器
|
||||
pm := plugin.NewPluginManager(pluginsDir)
|
||||
|
||||
// 加载插件
|
||||
fmt.Println("正在加载插件...")
|
||||
if err := pm.LoadPlugins(); err != nil {
|
||||
fmt.Printf("加载插件失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化所有插件
|
||||
if err := pm.InitPlugins(ctx); err != nil {
|
||||
fmt.Printf("初始化插件失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 启动所有插件
|
||||
if err := pm.StartPlugins(ctx); err != nil {
|
||||
fmt.Printf("启动插件失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 打印所有插件信息
|
||||
fmt.Println("\n=== 已加载的插件 ===")
|
||||
for _, info := range pm.GetPluginInfos() {
|
||||
fmt.Printf("插件: %s (版本: %s, 类型: %s)\n", info.Name, info.Version, info.Type)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
// 示例1: 调用日志插件
|
||||
fmt.Println("=== 示例1: 调用日志插件 ===")
|
||||
logResult, err := pm.ExecutePlugin(ctx, "LoggerPlugin", "info", map[string]interface{}{
|
||||
"message": "这是通过动态参数传递的日志消息",
|
||||
})
|
||||
fmt.Printf("日志插件调用结果: %v, 错误: %v\n", logResult, err)
|
||||
|
||||
// 获取日志状态
|
||||
statusResult, err := pm.ExecutePlugin(ctx, "LoggerPlugin", "getLoggerStatus", nil)
|
||||
fmt.Printf("日志插件状态: %v, 错误: %v\n", statusResult, err)
|
||||
|
||||
// 示例2: 调用存储插件
|
||||
fmt.Println("\n=== 示例2: 调用存储插件 ===")
|
||||
// 保存文件
|
||||
saveResult, err := pm.ExecutePlugin(ctx, "StoragePlugin", "saveFile", map[string]interface{}{
|
||||
"filename": "test.txt",
|
||||
"data": "这是通过动态参数传递保存的测试数据",
|
||||
})
|
||||
fmt.Printf("保存文件结果: %v, 错误: %v\n", saveResult, err)
|
||||
|
||||
// 列出文件
|
||||
listResult, err := pm.ExecutePlugin(ctx, "StoragePlugin", "listFiles", nil)
|
||||
fmt.Printf("文件列表: %v, 错误: %v\n", listResult, err)
|
||||
|
||||
// 读取文件
|
||||
loadResult, err := pm.ExecutePlugin(ctx, "StoragePlugin", "loadFile", map[string]interface{}{
|
||||
"filename": "test.txt",
|
||||
})
|
||||
fmt.Printf("读取文件内容: %v, 错误: %v\n", loadResult, err)
|
||||
|
||||
// 获取存储信息
|
||||
infoResult, err := pm.ExecutePlugin(ctx, "StoragePlugin", "getStorageInfo", nil)
|
||||
fmt.Printf("存储插件信息: %v, 错误: %v\n", infoResult, err)
|
||||
|
||||
// 示例3: 调用统计插件
|
||||
fmt.Println("\n=== 示例3: 调用统计插件 ===")
|
||||
// 记录请求
|
||||
pm.ExecutePlugin(ctx, "StatsPlugin", "recordRequest", map[string]interface{}{
|
||||
"bytesReceived": 1024.0,
|
||||
"bytesSent": 2048.0,
|
||||
"isError": false,
|
||||
})
|
||||
|
||||
// 睡眠一段时间以便观察
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// 再次记录请求
|
||||
pm.ExecutePlugin(ctx, "StatsPlugin", "recordRequest", map[string]interface{}{
|
||||
"bytesReceived": 512.0,
|
||||
"bytesSent": 768.0,
|
||||
"isError": true,
|
||||
})
|
||||
|
||||
// 获取统计报告
|
||||
reportResult, err := pm.ExecutePlugin(ctx, "StatsPlugin", "getStatsReport", nil)
|
||||
fmt.Printf("统计报告: %v, 错误: %v\n", reportResult, err)
|
||||
|
||||
// 示例4: 使用ExecutePluginsByType调用所有工具类插件
|
||||
fmt.Println("\n=== 示例4: 按类型调用插件 ===")
|
||||
typeResults := pm.ExecutePluginsByType(ctx, plugin.PluginTypeUtils, "info", map[string]interface{}{
|
||||
"message": "这条消息将发送给所有工具类插件",
|
||||
})
|
||||
fmt.Printf("工具类插件调用结果: %v\n", typeResults)
|
||||
|
||||
// 示例5: 使用ExecuteAllPlugins调用所有插件
|
||||
fmt.Println("\n=== 示例5: 调用所有插件 ===")
|
||||
allResults := pm.ExecuteAllPlugins(ctx, "getLoggerStatus", nil)
|
||||
fmt.Println("所有插件调用结果:")
|
||||
for name, result := range allResults {
|
||||
fmt.Printf(" %s: %v\n", name, result)
|
||||
}
|
||||
|
||||
// 停止所有插件
|
||||
if err := pm.StopPlugins(ctx); err != nil {
|
||||
fmt.Printf("停止插件失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("\n示例结束")
|
||||
}
|
@@ -10,15 +10,36 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("==== 插件系统示例 ====")
|
||||
fmt.Println("请选择要运行的示例:")
|
||||
fmt.Println("1. 基本插件加载和管理")
|
||||
fmt.Println("2. 动态参数传递示例")
|
||||
fmt.Print("请输入选项 (1-2): ")
|
||||
|
||||
var choice int
|
||||
fmt.Scan(&choice)
|
||||
|
||||
switch choice {
|
||||
case 1:
|
||||
BasicPluginExample()
|
||||
case 2:
|
||||
DynamicParamsExample()
|
||||
default:
|
||||
fmt.Println("无效的选项")
|
||||
}
|
||||
}
|
||||
|
||||
// BasicPluginExample 基本的插件加载和管理示例
|
||||
func BasicPluginExample() {
|
||||
// 创建上下文
|
||||
ctx := context.Background()
|
||||
|
||||
// 获取插件目录
|
||||
pluginsDir := filepath.Join("..", "plugins")
|
||||
pluginsDir := filepath.Join("..", "plugins", "dist")
|
||||
if _, err := os.Stat(pluginsDir); os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(pluginsDir, 0o755); err != nil {
|
||||
fmt.Printf("创建插件目录失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,19 +60,19 @@ func main() {
|
||||
// 加载插件
|
||||
if err := pm.LoadPlugins(); err != nil {
|
||||
fmt.Printf("加载插件失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化所有插件
|
||||
if err := pm.InitPlugins(ctx); err != nil {
|
||||
fmt.Printf("初始化插件失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
// 启动所有插件
|
||||
if err := pm.StartPlugins(ctx); err != nil {
|
||||
fmt.Printf("启动插件失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
// 打印所有插件信息
|
||||
@@ -125,7 +146,7 @@ func main() {
|
||||
// 确保所有剩余插件都被停止
|
||||
if err := pm.StopPlugins(ctx); err != nil {
|
||||
fmt.Printf("停止剩余插件失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("\n所有插件已停止")
|
||||
|
15
examples/plugin/example/run.sh
Normal file
15
examples/plugin/example/run.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 首先编译所有插件
|
||||
echo "===== 编译插件 ====="
|
||||
cd ../plugins
|
||||
./build.sh
|
||||
cd ../example
|
||||
|
||||
# 编译示例程序
|
||||
echo "===== 编译示例程序 ====="
|
||||
go build -o plugin_demo
|
||||
|
||||
# 运行示例程序
|
||||
echo "===== 运行示例程序 ====="
|
||||
./plugin_demo
|
@@ -1,5 +1,9 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// PluginType 插件类型
|
||||
type PluginType string
|
||||
|
||||
@@ -8,10 +12,10 @@ const (
|
||||
PluginTypeGeneral PluginType = "general" // 通用插件
|
||||
PluginTypeStorage PluginType = "storage" // 存储插件
|
||||
PluginTypeSecurity PluginType = "security" // 安全插件
|
||||
PluginTypeUI PluginType = "ui" // 用户界面插件
|
||||
PluginTypeNetwork PluginType = "network" // 网络插件
|
||||
PluginTypeUtils PluginType = "utils" // 工具插件
|
||||
PluginTypeHardware PluginType = "hardware" // 硬件插件
|
||||
PluginTypeUI PluginType = "ui" // 用户界面插件
|
||||
// 可以根据需求添加更多插件类型
|
||||
)
|
||||
|
||||
@@ -39,6 +43,11 @@ type IPlugin interface {
|
||||
IsEnabled() bool
|
||||
// SetEnabled 设置插件启用状态
|
||||
SetEnabled(enabled bool)
|
||||
// Execute 执行插件功能
|
||||
// action: 要执行的操作名称
|
||||
// params: 操作所需的参数
|
||||
// 返回操作结果和可能的错误
|
||||
Execute(action string, params map[string]interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
// BasePlugin 提供插件接口的基本实现
|
||||
@@ -119,3 +128,8 @@ func (p *BasePlugin) Start() error {
|
||||
func (p *BasePlugin) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute 执行插件功能,子类需要重写此方法
|
||||
func (p *BasePlugin) Execute(action string, params map[string]interface{}) (interface{}, error) {
|
||||
return nil, fmt.Errorf("插件 %s 不支持 %s 操作", p.name, action)
|
||||
}
|
||||
|
@@ -94,6 +94,47 @@ func (p *LogPlugin) Stop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute 实现Execute方法以满足Plugin接口
|
||||
func (p *LogPlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||||
switch action {
|
||||
case "log":
|
||||
// 需要参数: message
|
||||
message, ok := params["message"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: message")
|
||||
}
|
||||
p.Log(message)
|
||||
return true, nil
|
||||
|
||||
case "setLevel":
|
||||
// 需要参数: level
|
||||
level, ok := params["level"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: level")
|
||||
}
|
||||
p.level = level
|
||||
return true, nil
|
||||
|
||||
case "getLevel":
|
||||
// 不需要参数,返回当前日志级别
|
||||
return p.level, nil
|
||||
|
||||
case "getStatus":
|
||||
// 返回插件状态信息
|
||||
status := map[string]interface{}{
|
||||
"name": p.name,
|
||||
"version": p.version,
|
||||
"level": p.level,
|
||||
"enabled": p.enabled,
|
||||
"type": p.Type(),
|
||||
}
|
||||
return status, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||||
}
|
||||
}
|
||||
|
||||
// Log 记录日志
|
||||
func (p *LogPlugin) Log(message string) {
|
||||
fmt.Printf("[%s][%s] %s\n", p.name, p.level, message)
|
||||
@@ -179,6 +220,10 @@ func main() {
|
||||
// 这里可以根据插件类型执行特定操作
|
||||
if logPlugin, ok := p.(*LogPlugin); ok {
|
||||
logPlugin.Log("这是一条测试日志消息")
|
||||
// 改用Execute方法调用
|
||||
logPlugin.Execute(ctx, "log", map[string]interface{}{
|
||||
"message": "这是一条测试日志消息",
|
||||
})
|
||||
}
|
||||
}
|
||||
break
|
||||
@@ -196,6 +241,10 @@ func main() {
|
||||
fmt.Printf("工具类插件: %s\n", p.Name())
|
||||
if logPlugin, ok := p.(*LogPlugin); ok {
|
||||
logPlugin.Log("通过类型获取到的日志插件记录消息")
|
||||
// 改用Execute方法调用
|
||||
logPlugin.Execute(ctx, "log", map[string]interface{}{
|
||||
"message": "通过类型获取到的日志插件记录消息",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +255,10 @@ func main() {
|
||||
fmt.Printf("通用类型插件: %s\n", p.Name())
|
||||
if logPlugin, ok := p.(*LogPlugin); ok {
|
||||
logPlugin.Log("通过类型获取到的通用类型插件记录消息")
|
||||
// 改用Execute方法调用
|
||||
logPlugin.Execute(ctx, "log", map[string]interface{}{
|
||||
"message": "通过类型获取到的通用类型插件记录消息",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,11 @@ type Plugin interface {
|
||||
IsEnabled() bool
|
||||
// SetEnabled 设置插件启用状态
|
||||
SetEnabled(enabled bool)
|
||||
// Execute 执行插件功能
|
||||
// action: 要执行的操作名称
|
||||
// params: 操作所需的参数
|
||||
// 返回操作结果和可能的错误
|
||||
Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
// BasePluginImpl 提供插件接口的基本实现,用于适配Plugin接口
|
||||
@@ -72,6 +77,11 @@ func (p *BasePluginImpl) Stop(ctx context.Context) error {
|
||||
return p.BasePlugin.Stop()
|
||||
}
|
||||
|
||||
// Execute 适配Execute方法以支持context参数
|
||||
func (p *BasePluginImpl) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||||
return p.BasePlugin.Execute(action, params)
|
||||
}
|
||||
|
||||
// PluginInfo 插件信息
|
||||
type PluginInfo struct {
|
||||
Name string `json:"name"`
|
||||
@@ -577,3 +587,66 @@ func (pm *PluginManager) GetPluginConfig(name string) (map[string]interface{}, e
|
||||
|
||||
return config, 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
|
||||
}
|
||||
|
@@ -104,6 +104,62 @@ func (p *LoggerPlugin) Stop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute 执行插件功能
|
||||
func (p *LoggerPlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||||
switch action {
|
||||
case "log":
|
||||
// 需要参数: level, message
|
||||
level, ok := params["level"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: level")
|
||||
}
|
||||
message, ok := params["message"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: message")
|
||||
}
|
||||
p.Log(level, message)
|
||||
return true, nil
|
||||
|
||||
case "info":
|
||||
// 需要参数: message
|
||||
message, ok := params["message"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: message")
|
||||
}
|
||||
p.Info(message)
|
||||
return true, nil
|
||||
|
||||
case "warn":
|
||||
// 需要参数: message
|
||||
message, ok := params["message"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: message")
|
||||
}
|
||||
p.Warn(message)
|
||||
return true, nil
|
||||
|
||||
case "error":
|
||||
// 需要参数: message
|
||||
message, ok := params["message"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: message")
|
||||
}
|
||||
p.Error(message)
|
||||
return true, nil
|
||||
|
||||
case "getLoggerStatus":
|
||||
// 不需要参数
|
||||
status := map[string]interface{}{
|
||||
"initialized": p.logger != nil,
|
||||
"config": p.config,
|
||||
}
|
||||
return status, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||||
}
|
||||
}
|
||||
|
||||
// Log 记录日志
|
||||
func (p *LoggerPlugin) Log(level, message string) {
|
||||
if p.logger == nil {
|
||||
|
@@ -109,6 +109,115 @@ func (p *StatsPlugin) Stop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute 执行插件功能
|
||||
func (p *StatsPlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||||
switch action {
|
||||
case "incrementStat":
|
||||
// 需要参数: name, value
|
||||
name, ok := params["name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: name")
|
||||
}
|
||||
|
||||
// 处理整数值参数
|
||||
var value int64
|
||||
if floatValue, ok := params["value"].(float64); ok {
|
||||
value = int64(floatValue)
|
||||
} else if strValue, ok := params["value"].(string); ok {
|
||||
var err error
|
||||
_, err = fmt.Sscanf(strValue, "%d", &value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("参数value必须是整数: %v", err)
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("缺少必需参数: value")
|
||||
}
|
||||
|
||||
p.IncrementStat(name, value)
|
||||
return true, nil
|
||||
|
||||
case "getStat":
|
||||
// 需要参数: name
|
||||
name, ok := params["name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: name")
|
||||
}
|
||||
|
||||
value := p.GetStat(name)
|
||||
return value, nil
|
||||
|
||||
case "getAllStats":
|
||||
// 不需要参数
|
||||
return p.GetAllStats(), nil
|
||||
|
||||
case "recordRequest":
|
||||
// 需要参数: bytesReceived, bytesSent, isError
|
||||
var bytesReceived, bytesSent int64
|
||||
var isError bool
|
||||
|
||||
// 处理bytesReceived参数
|
||||
if floatValue, ok := params["bytesReceived"].(float64); ok {
|
||||
bytesReceived = int64(floatValue)
|
||||
} else {
|
||||
return nil, fmt.Errorf("缺少必需参数: bytesReceived")
|
||||
}
|
||||
|
||||
// 处理bytesSent参数
|
||||
if floatValue, ok := params["bytesSent"].(float64); ok {
|
||||
bytesSent = int64(floatValue)
|
||||
} else {
|
||||
return nil, fmt.Errorf("缺少必需参数: bytesSent")
|
||||
}
|
||||
|
||||
// 处理isError参数
|
||||
if value, ok := params["isError"].(bool); ok {
|
||||
isError = value
|
||||
}
|
||||
|
||||
p.RecordRequest(bytesReceived, bytesSent, isError)
|
||||
return true, nil
|
||||
|
||||
case "resetStats":
|
||||
// 不需要参数
|
||||
p.mu.Lock()
|
||||
p.stats = make(map[string]int64)
|
||||
p.stats["requests"] = 0
|
||||
p.stats["errors"] = 0
|
||||
p.stats["bytes_sent"] = 0
|
||||
p.stats["bytes_received"] = 0
|
||||
p.startTime = time.Now()
|
||||
p.mu.Unlock()
|
||||
return true, nil
|
||||
|
||||
case "getStatsReport":
|
||||
// 生成统计报告
|
||||
report := p.generateStatsReport()
|
||||
return report, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||||
}
|
||||
}
|
||||
|
||||
// generateStatsReport 生成统计报告
|
||||
func (p *StatsPlugin) generateStatsReport() map[string]interface{} {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
|
||||
uptime := time.Since(p.startTime).Seconds()
|
||||
report := map[string]interface{}{
|
||||
"uptime_seconds": uptime,
|
||||
"stats": p.stats,
|
||||
}
|
||||
|
||||
if uptime > 0 && p.stats["requests"] > 0 {
|
||||
report["requests_per_second"] = float64(p.stats["requests"]) / uptime
|
||||
report["error_rate"] = float64(p.stats["errors"]) * 100 / float64(p.stats["requests"])
|
||||
}
|
||||
|
||||
return report
|
||||
}
|
||||
|
||||
// logStats 记录当前统计信息
|
||||
func (p *StatsPlugin) logStats() {
|
||||
p.mu.RLock()
|
||||
|
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -69,6 +70,83 @@ func (p *StoragePlugin) Stop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute 执行插件功能
|
||||
func (p *StoragePlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||||
switch action {
|
||||
case "saveFile":
|
||||
// 需要参数: filename, data
|
||||
filename, ok := params["filename"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: filename")
|
||||
}
|
||||
|
||||
// 处理两种数据格式:字符串或Base64编码的二进制数据
|
||||
var data []byte
|
||||
if dataStr, ok := params["data"].(string); ok {
|
||||
// 检查是否为Base64编码
|
||||
if base64Str, ok := params["isBase64"].(bool); ok && base64Str {
|
||||
var err error
|
||||
data, err = base64.StdEncoding.DecodeString(dataStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Base64解码失败: %v", err)
|
||||
}
|
||||
} else {
|
||||
data = []byte(dataStr)
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("缺少必需参数: data")
|
||||
}
|
||||
|
||||
err := p.SaveFile(filename, data)
|
||||
return err == nil, err
|
||||
|
||||
case "loadFile":
|
||||
// 需要参数: filename, returnBase64
|
||||
filename, ok := params["filename"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: filename")
|
||||
}
|
||||
|
||||
returnBase64, _ := params["returnBase64"].(bool)
|
||||
|
||||
data, err := p.LoadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if returnBase64 {
|
||||
return base64.StdEncoding.EncodeToString(data), nil
|
||||
}
|
||||
return string(data), nil
|
||||
|
||||
case "deleteFile":
|
||||
// 需要参数: filename
|
||||
filename, ok := params["filename"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: filename")
|
||||
}
|
||||
|
||||
err := p.DeleteFile(filename)
|
||||
return err == nil, err
|
||||
|
||||
case "listFiles":
|
||||
// 不需要参数
|
||||
files, err := p.ListFiles()
|
||||
return files, err
|
||||
|
||||
case "getStorageInfo":
|
||||
// 不需要参数
|
||||
info := map[string]interface{}{
|
||||
"storageDir": p.storageDir,
|
||||
"config": p.config,
|
||||
}
|
||||
return info, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||||
}
|
||||
}
|
||||
|
||||
// SaveFile 保存文件
|
||||
func (p *StoragePlugin) SaveFile(filename string, data []byte) error {
|
||||
p.mu.Lock()
|
||||
|
Reference in New Issue
Block a user