feat: 插件文件更改热重载

This commit is contained in:
Junyan Qin
2024-11-16 16:45:13 +08:00
parent 658eb278c4
commit ca3999d251
4 changed files with 50 additions and 10 deletions

View File

@@ -5,6 +5,7 @@ import asyncio
import threading import threading
import traceback import traceback
import enum import enum
import sys
from ..platform import manager as im_mgr from ..platform import manager as im_mgr
from ..provider.session import sessionmgr as llm_session_mgr from ..provider.session import sessionmgr as llm_session_mgr
@@ -106,10 +107,8 @@ class Application:
pass pass
async def run(self): async def run(self):
await self.plugin_mgr.initialize_plugins()
try: try:
await self.plugin_mgr.initialize_plugins()
# 后续可能会允许动态重启其他任务 # 后续可能会允许动态重启其他任务
# 故为了防止程序在非 Ctrl-C 情况下退出,这里创建一个不会结束的协程 # 故为了防止程序在非 Ctrl-C 情况下退出,这里创建一个不会结束的协程
async def never_ending(): async def never_ending():
@@ -171,5 +170,21 @@ class Application:
await self.platform_mgr.initialize() await self.platform_mgr.initialize()
self.task_mgr.create_task(self.platform_mgr.run(), name="platform-manager", scopes=[core_entities.LifecycleControlScope.APPLICATION, core_entities.LifecycleControlScope.PLATFORM]) self.task_mgr.create_task(self.platform_mgr.run(), name="platform-manager", scopes=[core_entities.LifecycleControlScope.APPLICATION, core_entities.LifecycleControlScope.PLATFORM])
case core_entities.LifecycleControlScope.PLUGIN.value:
self.logger.info("执行热重载 scope="+scope)
await self.plugin_mgr.destroy_plugins()
# 删除 sys.module 中所有的 plugins/* 下的模块
for mod in list(sys.modules.keys()):
if mod.startswith("plugins."):
del sys.modules[mod]
self.plugin_mgr = plugin_mgr.PluginManager(self)
await self.plugin_mgr.initialize()
await self.plugin_mgr.initialize_plugins()
await self.plugin_mgr.load_plugins()
await self.plugin_mgr.initialize_plugins()
case _: case _:
pass pass

View File

@@ -98,6 +98,7 @@ class BasePlugin(metaclass=abc.ABCMeta):
pass pass
def __del__(self): def __del__(self):
"""释放/禁用插件时被调用"""
pass pass

View File

@@ -89,6 +89,7 @@ class PluginManager:
return return
self.ap.logger.debug(f'释放插件 {plugin.plugin_name}') self.ap.logger.debug(f'释放插件 {plugin.plugin_name}')
plugin.plugin_inst.__del__()
await plugin.plugin_inst.destroy() await plugin.plugin_inst.destroy()
plugin.plugin_inst = None plugin.plugin_inst = None
plugin.status = context.RuntimeContainerStatus.MOUNTED plugin.status = context.RuntimeContainerStatus.MOUNTED
@@ -124,6 +125,9 @@ class PluginManager:
} }
) )
task_context.trace('重载插件..', 'reload-plugin')
await self.ap.reload(scope='plugin')
async def uninstall_plugin( async def uninstall_plugin(
self, self,
plugin_name: str, plugin_name: str,
@@ -131,10 +135,15 @@ class PluginManager:
): ):
"""卸载插件 """卸载插件
""" """
await self.installer.uninstall_plugin(plugin_name, task_context)
plugin_container = self.get_plugin_by_name(plugin_name) plugin_container = self.get_plugin_by_name(plugin_name)
if plugin_container is None:
raise ValueError(f'插件 {plugin_name} 不存在')
await self.destroy_plugin(plugin_container)
await self.installer.uninstall_plugin(plugin_name, task_context)
await self.ap.ctr_mgr.plugin.post_remove_record( await self.ap.ctr_mgr.plugin.post_remove_record(
{ {
"name": plugin_name, "name": plugin_name,
@@ -144,6 +153,9 @@ class PluginManager:
} }
) )
task_context.trace('重载插件..', 'reload-plugin')
await self.ap.reload(scope='plugin')
async def update_plugin( async def update_plugin(
self, self,
plugin_name: str, plugin_name: str,
@@ -167,6 +179,8 @@ class PluginManager:
new_version="HEAD" new_version="HEAD"
) )
task_context.trace('重载插件..', 'reload-plugin')
await self.ap.reload(scope='plugin')
def get_plugin_by_name(self, plugin_name: str) -> context.RuntimeContainer: def get_plugin_by_name(self, plugin_name: str) -> context.RuntimeContainer:
"""通过插件名获取插件 """通过插件名获取插件

View File

@@ -73,6 +73,11 @@
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
<v-list-item @click="reload('plugin')">
<v-list-item-title>
重载插件
</v-list-item-title>
</v-list-item>
</v-list> </v-list>
</v-menu> </v-menu>
</v-list-item> </v-list-item>
@@ -143,21 +148,26 @@ function openDocs() {
window.open('https://docs.langbot.app', '_blank') window.open('https://docs.langbot.app', '_blank')
} }
const reloadScopeLabel = {
'platform': "消息平台",
'plugin': "插件"
}
function reload(scope) { function reload(scope) {
proxy.$axios.post('/system/reload', let label = reloadScopeLabel[scope]
proxy.$axios.post('/system/reload',
{ scope: scope }, { scope: scope },
{ headers: { 'Content-Type': 'application/json' } } { headers: { 'Content-Type': 'application/json' } }
).then(response => { ).then(response => {
if (response.data.code === 0) { if (response.data.code === 0) {
success('消息平台已重载') success(label+'已重载')
// 关闭菜单 // 关闭菜单
} else { } else {
error('消息平台重载失败:' + response.data.message) error(label+'重载失败:' + response.data.message)
} }
}).catch(error => { }).catch(err => {
console.error(error) error(label+'重载失败:' + err)
error('消息平台重载失败:' + error)
}) })
} }