mirror of
https://github.com/hanxi/xiaomusic.git
synced 2026-03-15 08:13:16 +08:00
fix: 修复nodejs进程无限重启的问题 see #728
This commit is contained in:
@@ -34,6 +34,12 @@ class JSPluginManager:
|
|||||||
self.pending_requests = {}
|
self.pending_requests = {}
|
||||||
self._is_shutting_down = False # 添加关闭标志
|
self._is_shutting_down = False # 添加关闭标志
|
||||||
|
|
||||||
|
# 进程重启控制
|
||||||
|
self._restart_count = 0 # 重启计数器
|
||||||
|
self._last_restart_time = 0 # 上次重启时间戳
|
||||||
|
self._restart_window = 60 # 重启时间窗口(秒)
|
||||||
|
self._max_restarts_in_window = 1 # 时间窗口内最大重启次数
|
||||||
|
|
||||||
# ... 配置文件相关 ...
|
# ... 配置文件相关 ...
|
||||||
self._config_cache = None
|
self._config_cache = None
|
||||||
self._config_cache_time = 0
|
self._config_cache_time = 0
|
||||||
@@ -80,10 +86,43 @@ class JSPluginManager:
|
|||||||
break
|
break
|
||||||
if self.node_process and self.node_process.poll() is not None:
|
if self.node_process and self.node_process.poll() is not None:
|
||||||
if not self._is_shutting_down:
|
if not self._is_shutting_down:
|
||||||
self.log.warning("Node.js process died, restarting...")
|
self._attempt_restart_node_process()
|
||||||
self._start_node_process()
|
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
|
def _attempt_restart_node_process(self):
|
||||||
|
"""尝试重启 Node.js 进程,带有限制机制"""
|
||||||
|
current_time = time.time()
|
||||||
|
|
||||||
|
# 检查是否在重启时间窗口内
|
||||||
|
if current_time - self._last_restart_time < self._restart_window:
|
||||||
|
# 在时间窗口内,检查重启次数
|
||||||
|
if self._restart_count >= self._max_restarts_in_window:
|
||||||
|
self.log.error(
|
||||||
|
f"Node.js process restart limit exceeded: {self._restart_count} restarts in {self._restart_window} seconds. "
|
||||||
|
"Manual intervention required."
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
# 超出时间窗口,重置计数器
|
||||||
|
self._restart_count = 0
|
||||||
|
|
||||||
|
# 执行重启
|
||||||
|
self._restart_count += 1
|
||||||
|
self._last_restart_time = current_time
|
||||||
|
|
||||||
|
remaining_attempts = self._max_restarts_in_window - self._restart_count
|
||||||
|
self.log.warning(
|
||||||
|
f"Node.js process died, attempting restart ({self._restart_count}/{self._max_restarts_in_window}). "
|
||||||
|
f"Remaining attempts in current window: {remaining_attempts}"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._start_node_process()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
self.log.error(f"Failed to restart Node.js process: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def _start_message_handler(self):
|
def _start_message_handler(self):
|
||||||
"""启动消息处理线程"""
|
"""启动消息处理线程"""
|
||||||
|
|
||||||
@@ -126,8 +165,23 @@ class JSPluginManager:
|
|||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""发送消息到 Node.js 子进程"""
|
"""发送消息到 Node.js 子进程"""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
# 检查进程状态,必要时尝试重启
|
||||||
if not self.node_process or self.node_process.poll() is not None:
|
if not self.node_process or self.node_process.poll() is not None:
|
||||||
raise Exception("Node.js process not available")
|
self.log.warning(
|
||||||
|
"Node.js process not available, checking restart possibility..."
|
||||||
|
)
|
||||||
|
# 尝试重启进程
|
||||||
|
if not self._attempt_restart_node_process():
|
||||||
|
raise Exception("Node.js process not available and restart failed")
|
||||||
|
|
||||||
|
# 等待进程稳定
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# 再次检查进程状态
|
||||||
|
if not self.node_process or self.node_process.poll() is not None:
|
||||||
|
raise Exception(
|
||||||
|
"Node.js process not available after restart attempt"
|
||||||
|
)
|
||||||
|
|
||||||
message_id = f"msg_{int(time.time() * 1000)}"
|
message_id = f"msg_{int(time.time() * 1000)}"
|
||||||
message["id"] = message_id
|
message["id"] = message_id
|
||||||
@@ -1357,6 +1411,30 @@ class JSPluginManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.error(f"Failed to update plugin config: {e}")
|
self.log.error(f"Failed to update plugin config: {e}")
|
||||||
|
|
||||||
|
def reset_restart_limit(self):
|
||||||
|
"""重置重启限制计数器,允许重新开始重启尝试"""
|
||||||
|
self._restart_count = 0
|
||||||
|
self._last_restart_time = 0
|
||||||
|
self.log.info("Node.js process restart limit has been reset")
|
||||||
|
|
||||||
|
def get_restart_status(self) -> dict[str, Any]:
|
||||||
|
"""获取重启状态信息"""
|
||||||
|
current_time = time.time()
|
||||||
|
time_since_last_restart = (
|
||||||
|
current_time - self._last_restart_time if self._last_restart_time > 0 else 0
|
||||||
|
)
|
||||||
|
time_until_reset = max(0, self._restart_window - time_since_last_restart)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"restart_count": self._restart_count,
|
||||||
|
"max_restarts_in_window": self._max_restarts_in_window,
|
||||||
|
"restart_window": self._restart_window,
|
||||||
|
"time_since_last_restart": time_since_last_restart,
|
||||||
|
"time_until_reset": time_until_reset,
|
||||||
|
"can_restart": self._restart_count < self._max_restarts_in_window
|
||||||
|
or time_since_last_restart >= self._restart_window,
|
||||||
|
}
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
"""关闭插件管理器"""
|
"""关闭插件管理器"""
|
||||||
if self.node_process:
|
if self.node_process:
|
||||||
|
|||||||
Reference in New Issue
Block a user