mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 07:27:15 +08:00
refactor: unify capability shutdown convergence
This commit is contained in:
@@ -1126,7 +1126,8 @@ class CapabilityRuntime:
|
||||
"""同步撤销并停止能力资源;物化实现保留供后续显式重启。"""
|
||||
self._stop_sync(capability_id, reason=reason, shutdown=False)
|
||||
|
||||
def _stop_sync(self, capability_id: str, *, reason: str, shutdown: bool) -> None:
|
||||
def _stop_sync(self, capability_id: str, *, reason: str, shutdown: bool) -> bool:
|
||||
"""停止同步能力并返回资源 owner 是否已经真实收敛。"""
|
||||
state = self._state(capability_id)
|
||||
adapter = self._adapter(state, AdapterExecutionMode.SYNC)
|
||||
while True:
|
||||
@@ -1146,7 +1147,7 @@ class CapabilityRuntime:
|
||||
if stop_owner is None and pending is None:
|
||||
if state.lifecycle is not CapabilityLifecycleState.FAILED:
|
||||
state.lifecycle = CapabilityLifecycleState.STOPPED
|
||||
return
|
||||
return True
|
||||
state.generation += 1
|
||||
generation = state.generation
|
||||
future: Future[Any] = Future()
|
||||
@@ -1166,8 +1167,10 @@ class CapabilityRuntime:
|
||||
except BaseException:
|
||||
if not shutdown:
|
||||
raise
|
||||
if waiter_operation == "stop":
|
||||
return False
|
||||
if waiter_operation == "stop":
|
||||
return
|
||||
return True
|
||||
continue
|
||||
break
|
||||
|
||||
@@ -1207,6 +1210,7 @@ class CapabilityRuntime:
|
||||
reason=reason,
|
||||
started_at=started_at,
|
||||
)
|
||||
return True
|
||||
except BaseException as error:
|
||||
with state.lock:
|
||||
state.lifecycle = CapabilityLifecycleState.FAILED
|
||||
@@ -1229,12 +1233,20 @@ class CapabilityRuntime:
|
||||
)
|
||||
if not shutdown:
|
||||
raise operation_error from error
|
||||
return False
|
||||
|
||||
async def stop_async(self, capability_id: str, *, reason: str) -> None:
|
||||
"""异步撤销并停止能力资源。"""
|
||||
await self._stop_async(capability_id, reason=reason, shutdown=False)
|
||||
|
||||
async def _stop_async(self, capability_id: str, *, reason: str, shutdown: bool) -> None:
|
||||
async def _stop_async(
|
||||
self,
|
||||
capability_id: str,
|
||||
*,
|
||||
reason: str,
|
||||
shutdown: bool,
|
||||
) -> bool:
|
||||
"""停止异步能力并返回资源 owner 是否已经真实收敛。"""
|
||||
state = self._state(capability_id)
|
||||
adapter = self._adapter(state, AdapterExecutionMode.ASYNC)
|
||||
while True:
|
||||
@@ -1254,7 +1266,7 @@ class CapabilityRuntime:
|
||||
if stop_owner is None and pending is None:
|
||||
if state.lifecycle is not CapabilityLifecycleState.FAILED:
|
||||
state.lifecycle = CapabilityLifecycleState.STOPPED
|
||||
return
|
||||
return True
|
||||
state.generation += 1
|
||||
generation = state.generation
|
||||
future: Future[Any] = Future()
|
||||
@@ -1274,8 +1286,10 @@ class CapabilityRuntime:
|
||||
except BaseException:
|
||||
if not shutdown:
|
||||
raise
|
||||
if waiter_operation == "stop":
|
||||
return False
|
||||
if waiter_operation == "stop":
|
||||
return
|
||||
return True
|
||||
continue
|
||||
break
|
||||
|
||||
@@ -1321,6 +1335,7 @@ class CapabilityRuntime:
|
||||
reason=reason,
|
||||
started_at=started_at,
|
||||
)
|
||||
return True
|
||||
except BaseException as error:
|
||||
with state.lock:
|
||||
state.lifecycle = CapabilityLifecycleState.FAILED
|
||||
@@ -1343,9 +1358,10 @@ class CapabilityRuntime:
|
||||
)
|
||||
if not shutdown:
|
||||
raise operation_error from error
|
||||
return False
|
||||
|
||||
def shutdown(self, *, reason: str) -> None:
|
||||
"""不可逆关闭仅含同步 adapter 的 Runtime,并阻止并发首启重新发布。"""
|
||||
def shutdown(self, *, reason: str) -> bool:
|
||||
"""不可逆关闭同步 Runtime,并返回全部 owner 是否收敛。"""
|
||||
async_kinds = {
|
||||
kind
|
||||
for kind, adapter in self._adapters.items()
|
||||
@@ -1357,21 +1373,32 @@ class CapabilityRuntime:
|
||||
)
|
||||
with self._shutdown_lock:
|
||||
self._shutdown = True
|
||||
converged = True
|
||||
for spec in self._registry.list_specs():
|
||||
self._stop_sync(spec.id, reason=reason, shutdown=True)
|
||||
if not self._stop_sync(spec.id, reason=reason, shutdown=True):
|
||||
converged = False
|
||||
return converged
|
||||
|
||||
async def shutdown_async(self, *, reason: str) -> None:
|
||||
"""不可逆关闭混合同步/异步 adapter 的 Runtime。"""
|
||||
async def shutdown_async(self, *, reason: str) -> bool:
|
||||
"""不可逆关闭混合 Runtime,并返回全部 owner 是否收敛。"""
|
||||
with self._shutdown_lock:
|
||||
self._shutdown = True
|
||||
converged = True
|
||||
for spec in self._registry.list_specs():
|
||||
adapter = self._adapters[spec.kind]
|
||||
if getattr(adapter, "execution_mode", None) is AdapterExecutionMode.ASYNC:
|
||||
await self._stop_async(spec.id, reason=reason, shutdown=True)
|
||||
stopped = await self._stop_async(
|
||||
spec.id,
|
||||
reason=reason,
|
||||
shutdown=True,
|
||||
)
|
||||
else:
|
||||
await asyncio.to_thread(
|
||||
stopped = await asyncio.to_thread(
|
||||
self._stop_sync,
|
||||
spec.id,
|
||||
reason=reason,
|
||||
shutdown=True,
|
||||
)
|
||||
if not stopped:
|
||||
converged = False
|
||||
return converged
|
||||
|
||||
@@ -247,8 +247,9 @@ class HostModuleAdapter:
|
||||
@staticmethod
|
||||
def stop(spec: CapabilitySpec, instance: Any, generation: int) -> None:
|
||||
"""停止实例拥有的资源;Runtime 会先撤销其运行态可见性。"""
|
||||
del spec, generation
|
||||
instance.stop()
|
||||
del generation
|
||||
if instance.stop() is False:
|
||||
raise RuntimeError(f"Host Module {spec.id} 资源未完成收口")
|
||||
|
||||
@staticmethod
|
||||
def cleanup(
|
||||
|
||||
@@ -224,13 +224,17 @@ class ModuleManager(metaclass=Singleton):
|
||||
self._refresh_running_projection()
|
||||
logger.info("所有模块停止完成")
|
||||
|
||||
def shutdown(self) -> None:
|
||||
"""进程关闭时不可逆停止 Runtime,阻止并发能力重新发布。"""
|
||||
def shutdown(self) -> bool:
|
||||
"""不可逆停止 Runtime,并返回所有模块 owner 是否收敛。"""
|
||||
logger.info("正在关闭模块运行时...")
|
||||
with self._lifecycle_lock:
|
||||
self._runtime.shutdown(reason="application_shutdown")
|
||||
converged = self._runtime.shutdown(reason="application_shutdown")
|
||||
self._refresh_running_projection()
|
||||
logger.info("模块运行时关闭完成")
|
||||
if converged:
|
||||
logger.info("模块运行时关闭完成")
|
||||
else:
|
||||
logger.error("模块运行时关闭后仍有资源 owner 未收敛")
|
||||
return converged
|
||||
|
||||
def reload(self) -> None:
|
||||
"""保留旧插件可观察的 stop、load、ModuleReload 同步顺序。"""
|
||||
|
||||
@@ -48,8 +48,8 @@ class ManagedResourceRuntime(Protocol):
|
||||
async def stop_async(self, capability_id: str, *, reason: str) -> None:
|
||||
"""通过异步 adapter 停止资源。"""
|
||||
|
||||
async def shutdown_async(self, *, reason: str) -> None:
|
||||
"""关闭混合同步和异步 adapter 的 Runtime。"""
|
||||
async def shutdown_async(self, *, reason: str) -> bool:
|
||||
"""关闭混合 Runtime,并返回全部资源是否收敛。"""
|
||||
|
||||
|
||||
_runtime_lock = threading.RLock()
|
||||
@@ -174,9 +174,9 @@ async def stop_managed_resource_async(capability_id: str, *, reason: str) -> Non
|
||||
raise RuntimeError(f"未知 Managed Resource kind:{kind}")
|
||||
|
||||
|
||||
async def shutdown_managed_resource_runtime(*, reason: str) -> None:
|
||||
"""关闭已配置 Runtime;未配置时直接返回,绝不因关闭而创建资源。"""
|
||||
async def shutdown_managed_resource_runtime(*, reason: str) -> bool:
|
||||
"""关闭已配置 Runtime,未配置时按已收敛处理。"""
|
||||
runtime = _runtime(required=False)
|
||||
if runtime is None:
|
||||
return
|
||||
await runtime.shutdown_async(reason=reason)
|
||||
return True
|
||||
return await runtime.shutdown_async(reason=reason)
|
||||
|
||||
Reference in New Issue
Block a user