mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 17:38:10 +00:00
插件删除回调:onRemove 生命周期(仅卸载触发,重载不触发)
- 公共 SDK(third_party/homeagent-sdk):RegisterOnRemoveHandler/RunOnRemoveHandlers (后注册先执行、幂等);内部 SDK PluginManager 接口新增 RemovePlugin - registry.RemovePlugin:runStopHandlers → Stop → 清理 plugins/sdkRefs/instances → runOnRemoveHandlers → toolCleaner.UnregisterPluginTools → cfgReg.RemoveDisabledPlugin - pluginmgr.removePlugin 先调 Registry.RemovePlugin 再删目录 - 配置清理:PluginSettings.Remove(key)(内部 SettingsAPI + settingsImpl) - 演示:timer 插件 onRemove 删 max_duration 键;plugindev 模板同步 onRemove 示例; SDK example/calendar cleanupData 删 events.json;manager plugins/uninstall 先停通道
This commit is contained in:
@ -745,6 +745,14 @@ func (p *PluginSettings) Set(key string, value interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove 删除插件配置中的单个键(用于插件删除时的自身配置清理)。
|
||||
func (p *PluginSettings) Remove(key string) error {
|
||||
p.registry.mu.Lock()
|
||||
defer p.registry.mu.Unlock()
|
||||
_, err := p.registry.db.Exec(fmt.Sprintf(`DELETE FROM %s WHERE key = ?`, p.table), key)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PluginSettings) List(prefix string) ([]string, error) {
|
||||
p.registry.mu.RLock()
|
||||
defer p.registry.mu.RUnlock()
|
||||
|
||||
@ -390,6 +390,13 @@ func (r *Registry) runStopHandlers(name string) {
|
||||
}
|
||||
}
|
||||
|
||||
// runOnRemoveHandlers 执行插件注册的删除清理回调(SDK 层),插件 Stop() 之后、从注册表移除前执行。
|
||||
func (r *Registry) runOnRemoveHandlers(name string) {
|
||||
if sdk, ok := r.sdkRefs[name]; ok {
|
||||
sdk.RunOnRemoveHandlers()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Registry) StopAll() {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
@ -580,6 +587,39 @@ func (r *Registry) DisablePlugin(name, by string) error {
|
||||
|
||||
func (r *Registry) EnablePlugin(name string) error { return r.Enable(name) }
|
||||
|
||||
// RemovePlugin 卸载插件:先停止(stop handlers + Stop),再执行插件注册的 onRemove
|
||||
// 回调(删除专用,重载不触发),最后从注册表移除并清理禁用/工具注册。
|
||||
// 插件目录的物理删除由调用方(pluginmgr)负责。
|
||||
func (r *Registry) RemovePlugin(name string) error {
|
||||
r.mu.Lock()
|
||||
p, ok := r.plugins[name]
|
||||
if ok {
|
||||
r.runStopHandlers(name)
|
||||
if err := p.Stop(); err != nil {
|
||||
log.Printf("[plugin] stop %s for remove: %v", name, err)
|
||||
}
|
||||
delete(r.plugins, name)
|
||||
delete(r.sdkRefs, name)
|
||||
for i, inst := range r.instances {
|
||||
if inst.Name() == name {
|
||||
r.instances = append(r.instances[:i], r.instances[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
r.runOnRemoveHandlers(name)
|
||||
r.mu.Unlock()
|
||||
|
||||
if r.toolCleaner != nil {
|
||||
r.toolCleaner.UnregisterPluginTools(name)
|
||||
}
|
||||
if r.cfgReg != nil {
|
||||
r.cfgReg.RemoveDisabledPlugin(name)
|
||||
}
|
||||
log.Printf("[plugin] removed: %s", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Registry) ReloadPlugins() (string, error) { return r.Reload(r.plgDir) }
|
||||
|
||||
// ListKnown 返回所有已知插件(已加载 + 已禁用 + 已安装但未加载)。
|
||||
|
||||
@ -456,6 +456,13 @@ func (p *Plugin) removePlugin(name string) (interface{}, error) {
|
||||
return map[string]interface{}{"error": "plugin not found", "name": name}, nil
|
||||
}
|
||||
|
||||
// 先经内核卸载:停止插件(stop handlers + Stop)并执行插件注册的 onRemove 回调
|
||||
if p.sdk != nil && p.sdk.PluginMgr() != nil {
|
||||
if err := p.sdk.PluginMgr().RemovePlugin(name); err != nil {
|
||||
log.Printf("[pluginmgr] RemovePlugin %s: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(dir); err != nil {
|
||||
return map[string]interface{}{"error": err.Error()}, nil
|
||||
}
|
||||
|
||||
@ -44,6 +44,12 @@ func (p *Plugin) Start(s *sdk.PluginSDK) error {
|
||||
p.maxDur = 24 * time.Hour
|
||||
// 停止清理(取消倒计时)交由 stop handler:内核在调用 Stop() 之前执行。
|
||||
s.RegisterStopHandler(func() { close(p.stopCh) })
|
||||
// 删除清理:移除插件自身配置(删除专用回调,重载不触发)。
|
||||
s.RegisterOnRemoveHandler(func() {
|
||||
if err := s.Settings().Remove("max_duration"); err != nil {
|
||||
log.Printf("[timer] onRemove cleanup: %v", err)
|
||||
}
|
||||
})
|
||||
s.Settings().RegisterDef(sdk.ConfigDef{
|
||||
Key: "max_duration", Type: "string", DisplayName: "最大定时时长",
|
||||
Description: "允许设置的最大定时时长,例如 24h, 7d, 1h(默认 24h)",
|
||||
|
||||
@ -69,6 +69,9 @@ type PluginManager interface {
|
||||
IsPluginDisabled(name string) bool
|
||||
DisablePlugin(name, by string) error
|
||||
EnablePlugin(name string) error
|
||||
// RemovePlugin 卸载插件:先停止(stop handlers + Stop),再执行插件注册的
|
||||
// onRemove 回调(RegisterOnRemoveHandler),最后从注册表移除。目录删除由调用方负责。
|
||||
RemovePlugin(name string) error
|
||||
ReloadPlugins() (string, error)
|
||||
PluginMetas() map[string]PluginMeta
|
||||
PluginDir() string
|
||||
|
||||
@ -9,6 +9,8 @@ type SettingsAPI interface {
|
||||
DefsCore(prefix string) []*ConfigDef
|
||||
// DefsPlugin 返回另一个插件的配置定义。
|
||||
DefsPlugin(plugin, prefix string) []*ConfigDef
|
||||
// Remove 删除本插件配置中的单个键(插件删除时清理自身配置用)。
|
||||
Remove(key string) error
|
||||
}
|
||||
|
||||
type ConfigDef = pubsdk.ConfigDef
|
||||
|
||||
@ -24,6 +24,10 @@ func (s *settingsImpl) Set(key string, value interface{}) error {
|
||||
if s.reg == nil { return nil }
|
||||
return s.reg.PluginConfig(s.pluginName).Set(key, value)
|
||||
}
|
||||
func (s *settingsImpl) Remove(key string) error {
|
||||
if s.reg == nil { return nil }
|
||||
return s.reg.PluginConfig(s.pluginName).Remove(key)
|
||||
}
|
||||
func (s *settingsImpl) List(prefix string) ([]string, error) {
|
||||
if s.reg == nil { return nil, nil }
|
||||
return s.reg.PluginConfig(s.pluginName).List(prefix)
|
||||
|
||||
28
third_party/homeagent-sdk/sdk/plugin.go
vendored
28
third_party/homeagent-sdk/sdk/plugin.go
vendored
@ -205,6 +205,9 @@ type PluginSDK struct {
|
||||
|
||||
stopMu sync.Mutex
|
||||
stopHandlers []func()
|
||||
|
||||
removeMu sync.Mutex
|
||||
removeHandlers []func()
|
||||
}
|
||||
|
||||
// New creates a PluginSDK with the given dependencies.
|
||||
@ -408,3 +411,28 @@ func (s *PluginSDK) RunStopHandlers() {
|
||||
handlers[i]()
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterOnRemoveHandler 注册插件被删除(卸载)时的清理回调。
|
||||
// 注册的 handler 会在插件目录被移除前按"后注册先执行"的顺序调用,
|
||||
// 适用于清理外部资源、删除配置表、下线状态等删除后处理。
|
||||
// 可注册多个;执行后清空(一次删除只执行一次)。
|
||||
func (s *PluginSDK) RegisterOnRemoveHandler(fn func()) {
|
||||
if fn == nil {
|
||||
return
|
||||
}
|
||||
s.removeMu.Lock()
|
||||
s.removeHandlers = append(s.removeHandlers, fn)
|
||||
s.removeMu.Unlock()
|
||||
}
|
||||
|
||||
// RunOnRemoveHandlers 执行全部已注册的 onRemove handler(后注册先执行,执行后清空,幂等)。
|
||||
// 由内核在卸载插件(registry.RemovePlugin)时、插件 Stop() 之后执行。
|
||||
func (s *PluginSDK) RunOnRemoveHandlers() {
|
||||
s.removeMu.Lock()
|
||||
handlers := append([]func(){}, s.removeHandlers...)
|
||||
s.removeHandlers = nil
|
||||
s.removeMu.Unlock()
|
||||
for i := len(handlers) - 1; i >= 0; i-- {
|
||||
handlers[i]()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user