mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-07-03 18:36:35 +08:00
fix(plugin): reset stopped plugin config and data (#6031)
This commit is contained in:
@@ -615,9 +615,9 @@ def reset_plugin(
|
||||
# 事件处理器需要运行中插件完成补偿;补偿后先停止插件,避免删除数据时仍有任务读写旧状态。
|
||||
plugin_manager.stop(plugin_id)
|
||||
# 删除配置
|
||||
plugin_manager.delete_plugin_config(plugin_id)
|
||||
plugin_manager.delete_plugin_config(plugin_id, force=True)
|
||||
# 删除插件所有数据
|
||||
plugin_manager.delete_plugin_data(plugin_id)
|
||||
plugin_manager.delete_plugin_data(plugin_id, force=True)
|
||||
# 重新加载插件
|
||||
reload_plugin(plugin_id)
|
||||
return schemas.Response(success=True)
|
||||
|
||||
@@ -723,21 +723,23 @@ class PluginManager(ConfigReloadMixin, metaclass=Singleton):
|
||||
await SystemConfigOper().async_set(self._config_key % pid, conf)
|
||||
return True
|
||||
|
||||
def delete_plugin_config(self, pid: str) -> bool:
|
||||
def delete_plugin_config(self, pid: str, force: bool = False) -> bool:
|
||||
"""
|
||||
删除插件配置
|
||||
:param pid: 插件ID
|
||||
:param force: 插件停止后仍允许按插件 ID 删除持久化配置
|
||||
"""
|
||||
if not self._plugins.get(pid):
|
||||
if not force and not self._plugins.get(pid):
|
||||
return False
|
||||
return SystemConfigOper().delete(self._config_key % pid)
|
||||
|
||||
def delete_plugin_data(self, pid: str) -> bool:
|
||||
def delete_plugin_data(self, pid: str, force: bool = False) -> bool:
|
||||
"""
|
||||
删除插件数据
|
||||
:param pid: 插件ID
|
||||
:param force: 插件停止后仍允许按插件 ID 删除持久化数据
|
||||
"""
|
||||
if not self._plugins.get(pid):
|
||||
if not force and not self._plugins.get(pid):
|
||||
return False
|
||||
PluginDataOper().del_data(pid)
|
||||
return True
|
||||
|
||||
@@ -7,8 +7,10 @@ from app.api.endpoints.plugin import plugin_releases
|
||||
from app.api.endpoints.plugin import reset_plugin
|
||||
from app.api.endpoints.system import sync_plugin_market_from_wiki
|
||||
from app.core.config import settings
|
||||
from app.core.plugin import PluginManager
|
||||
from app.schemas.event import PluginDataResetEventData
|
||||
from app.schemas.types import ChainEventType
|
||||
from app.utils.singleton import Singleton
|
||||
|
||||
|
||||
def test_plugin_history_merges_remote_metadata():
|
||||
@@ -279,12 +281,12 @@ def test_reset_plugin_sends_pre_reset_chain_event_before_deleting_data():
|
||||
plugin_manager = MagicMock()
|
||||
calls = []
|
||||
|
||||
def delete_config(plugin_id):
|
||||
calls.append(("delete_config", plugin_id))
|
||||
def delete_config(plugin_id, force=False):
|
||||
calls.append(("delete_config", plugin_id, force))
|
||||
return True
|
||||
|
||||
def delete_data(plugin_id):
|
||||
calls.append(("delete_data", plugin_id))
|
||||
def delete_data(plugin_id, force=False):
|
||||
calls.append(("delete_data", plugin_id, force))
|
||||
return True
|
||||
|
||||
def stop_plugin(plugin_id):
|
||||
@@ -314,7 +316,38 @@ def test_reset_plugin_sends_pre_reset_chain_event_before_deleting_data():
|
||||
assert event_call[2].reset_data is True
|
||||
assert calls[1:] == [
|
||||
("stop", "SubscribeAssistantEnhanced"),
|
||||
("delete_config", "SubscribeAssistantEnhanced"),
|
||||
("delete_data", "SubscribeAssistantEnhanced"),
|
||||
("delete_config", "SubscribeAssistantEnhanced", True),
|
||||
("delete_data", "SubscribeAssistantEnhanced", True),
|
||||
]
|
||||
reload_plugin_mock.assert_called_once_with("SubscribeAssistantEnhanced")
|
||||
|
||||
|
||||
def test_delete_plugin_config_can_force_delete_after_plugin_is_stopped():
|
||||
"""
|
||||
重置入口会先停止插件;配置删除需要能处理运行态注册已清理的插件 ID。
|
||||
"""
|
||||
Singleton._instances.pop((PluginManager, (), frozenset()), None)
|
||||
manager = PluginManager()
|
||||
|
||||
with patch("app.core.plugin.SystemConfigOper") as system_config_oper:
|
||||
system_config_oper.return_value.delete.return_value = True
|
||||
assert manager.delete_plugin_config("DemoPlugin", force=True) is True
|
||||
|
||||
system_config_oper.return_value.delete.assert_called_once_with("plugin.DemoPlugin")
|
||||
Singleton._instances.pop((PluginManager, (), frozenset()), None)
|
||||
|
||||
|
||||
def test_delete_plugin_data_can_force_delete_after_plugin_is_stopped():
|
||||
"""
|
||||
重置入口会先停止插件;插件数据删除不能依赖运行态注册仍存在。
|
||||
"""
|
||||
Singleton._instances.pop((PluginManager, (), frozenset()), None)
|
||||
manager = PluginManager()
|
||||
calls = []
|
||||
|
||||
with patch("app.core.plugin.PluginDataOper") as plugin_data_oper:
|
||||
plugin_data_oper.return_value.del_data.side_effect = lambda pid: calls.append(pid)
|
||||
assert manager.delete_plugin_data("DemoPlugin", force=True) is True
|
||||
|
||||
assert calls == ["DemoPlugin"]
|
||||
Singleton._instances.pop((PluginManager, (), frozenset()), None)
|
||||
|
||||
Reference in New Issue
Block a user