mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-30 04:27:40 +08:00
72 lines
2.3 KiB
Python
72 lines
2.3 KiB
Python
"""插件安装与启动同步之间共享的生命周期互斥。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import threading
|
|
from contextlib import asynccontextmanager
|
|
|
|
|
|
class PluginLifecycleCoordinator:
|
|
"""在事件循环和同步启动线程之间协调插件生命周期操作。"""
|
|
|
|
def __init__(self) -> None:
|
|
self._condition = threading.Condition()
|
|
self._active_plugins: set[str] = set()
|
|
self._startup_active = False
|
|
|
|
@staticmethod
|
|
def _normalize(plugin_id: str) -> str:
|
|
return (plugin_id or "").strip().lower()
|
|
|
|
def _try_acquire_plugin(self, plugin_id: str) -> bool:
|
|
normalized_id = self._normalize(plugin_id)
|
|
if not normalized_id:
|
|
raise ValueError("插件ID不能为空")
|
|
with self._condition:
|
|
if self._startup_active or normalized_id in self._active_plugins:
|
|
return False
|
|
self._active_plugins.add(normalized_id)
|
|
return True
|
|
|
|
def _release_plugin(self, plugin_id: str) -> None:
|
|
normalized_id = self._normalize(plugin_id)
|
|
with self._condition:
|
|
self._active_plugins.discard(normalized_id)
|
|
self._condition.notify_all()
|
|
|
|
def _try_acquire_startup(self) -> bool:
|
|
with self._condition:
|
|
if self._startup_active or self._active_plugins:
|
|
return False
|
|
self._startup_active = True
|
|
return True
|
|
|
|
def _release_startup(self) -> None:
|
|
with self._condition:
|
|
self._startup_active = False
|
|
self._condition.notify_all()
|
|
|
|
@asynccontextmanager
|
|
async def hold(self, plugin_id: str):
|
|
"""异步持有单个插件的生命周期资格,不在线程池中等待锁。"""
|
|
while not self._try_acquire_plugin(plugin_id):
|
|
await asyncio.sleep(0.01)
|
|
try:
|
|
yield
|
|
finally:
|
|
self._release_plugin(plugin_id)
|
|
|
|
@asynccontextmanager
|
|
async def hold_startup(self):
|
|
"""异步持有启动同步的全局资格,阻止安装请求穿过启动收口。"""
|
|
while not self._try_acquire_startup():
|
|
await asyncio.sleep(0.01)
|
|
try:
|
|
yield
|
|
finally:
|
|
self._release_startup()
|
|
|
|
|
|
plugin_lifecycle = PluginLifecycleCoordinator()
|