fix shudown

This commit is contained in:
jxxghp
2024-10-15 13:42:41 +08:00
parent 810e3c98f9
commit 8af37a0adc
15 changed files with 88 additions and 16 deletions
+3 -3
View File
@@ -232,7 +232,7 @@ def get_progress(process_type: str, _: schemas.TokenPayload = Depends(verify_res
def event_generator(): def event_generator():
while True: while True:
if global_vars.is_system_stopped(): if global_vars.is_system_stopped:
break break
detail = progress.get(process_type) detail = progress.get(process_type)
yield 'data: %s\n\n' % json.dumps(detail) yield 'data: %s\n\n' % json.dumps(detail)
@@ -281,7 +281,7 @@ def get_message(role: str = "system", _: schemas.TokenPayload = Depends(verify_r
def event_generator(): def event_generator():
while True: while True:
if global_vars.is_system_stopped(): if global_vars.is_system_stopped:
break break
detail = message.get(role) detail = message.get(role)
yield 'data: %s\n\n' % (detail or '') yield 'data: %s\n\n' % (detail or '')
@@ -312,7 +312,7 @@ def get_logging(length: int = 50, logfile: str = "moviepilot.log",
for line in f.readlines()[-max(length, 50):]: for line in f.readlines()[-max(length, 50):]:
yield 'data: %s\n\n' % line yield 'data: %s\n\n' % line
while True: while True:
if global_vars.is_system_stopped(): if global_vars.is_system_stopped:
break break
for t in tailer.follow(open(log_path, 'r', encoding='utf-8')): for t in tailer.follow(open(log_path, 'r', encoding='utf-8')):
yield 'data: %s\n\n' % (t or '') yield 'data: %s\n\n' % (t or '')
+9 -1
View File
@@ -8,7 +8,7 @@ from typing import List, Optional, Tuple, Set, Dict, Union
from app import schemas from app import schemas
from app.chain import ChainBase from app.chain import ChainBase
from app.core.config import settings from app.core.config import settings, global_vars
from app.core.context import MediaInfo, TorrentInfo, Context from app.core.context import MediaInfo, TorrentInfo, Context
from app.core.event import eventmanager, Event from app.core.event import eventmanager, Event
from app.core.meta import MetaBase from app.core.meta import MetaBase
@@ -463,6 +463,8 @@ class DownloadChain(ChainBase):
# 如果是电影,直接下载 # 如果是电影,直接下载
for context in contexts: for context in contexts:
if global_vars.is_system_stopped:
break
if context.media_info.type == MediaType.MOVIE: if context.media_info.type == MediaType.MOVIE:
logger.info(f"开始下载电影 {context.torrent_info.title} ...") logger.info(f"开始下载电影 {context.torrent_info.title} ...")
if self.download_single(context, save_path=save_path, channel=channel, if self.download_single(context, save_path=save_path, channel=channel,
@@ -491,6 +493,8 @@ class DownloadChain(ChainBase):
for need_mid, need_season in need_seasons.items(): for need_mid, need_season in need_seasons.items():
# 循环种子 # 循环种子
for context in contexts: for context in contexts:
if global_vars.is_system_stopped:
break
# 媒体信息 # 媒体信息
media = context.media_info media = context.media_info
# 识别元数据 # 识别元数据
@@ -598,6 +602,8 @@ class DownloadChain(ChainBase):
need_episodes = list(range(start_episode, total_episode + 1)) need_episodes = list(range(start_episode, total_episode + 1))
# 循环种子 # 循环种子
for context in contexts: for context in contexts:
if global_vars.is_system_stopped:
break
# 媒体信息 # 媒体信息
media = context.media_info media = context.media_info
# 识别元数据 # 识别元数据
@@ -664,6 +670,8 @@ class DownloadChain(ChainBase):
continue continue
# 循环种子 # 循环种子
for context in contexts: for context in contexts:
if global_vars.is_system_stopped:
break
# 媒体信息 # 媒体信息
media = context.media_info media = context.media_info
# 识别元数据 # 识别元数据
+5
View File
@@ -6,6 +6,7 @@ from typing import Dict
from typing import List, Optional from typing import List, Optional
from app.chain import ChainBase from app.chain import ChainBase
from app.core.config import global_vars
from app.core.context import Context from app.core.context import Context
from app.core.context import MediaInfo, TorrentInfo from app.core.context import MediaInfo, TorrentInfo
from app.core.event import eventmanager, Event from app.core.event import eventmanager, Event
@@ -210,6 +211,8 @@ class SearchChain(ChainBase):
logger.info(f"开始匹配结果 标题:{mediainfo.title},原标题:{mediainfo.original_title},别名:{mediainfo.names}") logger.info(f"开始匹配结果 标题:{mediainfo.title},原标题:{mediainfo.original_title},别名:{mediainfo.names}")
self.progress.update(value=51, text=f'开始匹配,总 {_total} 个资源 ...', key=ProgressKey.Search) self.progress.update(value=51, text=f'开始匹配,总 {_total} 个资源 ...', key=ProgressKey.Search)
for torrent in torrents: for torrent in torrents:
if global_vars.is_system_stopped:
break
_count += 1 _count += 1
self.progress.update(value=(_count / _total) * 96, self.progress.update(value=(_count / _total) * 96,
text=f'正在匹配 {torrent.site_name},已完成 {_count} / {_total} ...', text=f'正在匹配 {torrent.site_name},已完成 {_count} / {_total} ...',
@@ -333,6 +336,8 @@ class SearchChain(ChainBase):
# 结果集 # 结果集
results = [] results = []
for future in as_completed(all_task): for future in as_completed(all_task):
if global_vars.is_system_stopped:
break
finish_count += 1 finish_count += 1
result = future.result() result = future.result()
if result: if result:
+3 -1
View File
@@ -9,7 +9,7 @@ from lxml import etree
from ruamel.yaml import CommentedMap from ruamel.yaml import CommentedMap
from app.chain import ChainBase from app.chain import ChainBase
from app.core.config import settings from app.core.config import settings, global_vars
from app.core.event import eventmanager, Event, EventManager from app.core.event import eventmanager, Event, EventManager
from app.db.models.site import Site from app.db.models.site import Site
from app.db.site_oper import SiteOper from app.db.site_oper import SiteOper
@@ -74,6 +74,8 @@ class SiteChain(ChainBase):
""" """
sites = self.siteshelper.get_indexers() sites = self.siteshelper.get_indexers()
for site in sites: for site in sites:
if global_vars.is_system_stopped:
break
if site.get("is_active"): if site.get("is_active"):
self.refresh_userdata(site) self.refresh_userdata(site)
+9 -1
View File
@@ -10,7 +10,7 @@ from app.chain.media import MediaChain
from app.chain.search import SearchChain from app.chain.search import SearchChain
from app.chain.tmdb import TmdbChain from app.chain.tmdb import TmdbChain
from app.chain.torrents import TorrentsChain from app.chain.torrents import TorrentsChain
from app.core.config import settings from app.core.config import settings, global_vars
from app.core.context import TorrentInfo, Context, MediaInfo from app.core.context import TorrentInfo, Context, MediaInfo
from app.core.event import eventmanager, Event, EventManager from app.core.event import eventmanager, Event, EventManager
from app.core.meta import MetaBase from app.core.meta import MetaBase
@@ -242,6 +242,8 @@ class SubscribeChain(ChainBase):
subscribes = self.subscribeoper.list(state) subscribes = self.subscribeoper.list(state)
# 遍历订阅 # 遍历订阅
for subscribe in subscribes: for subscribe in subscribes:
if global_vars.is_system_stopped:
break
mediakey = subscribe.tmdbid or subscribe.doubanid mediakey = subscribe.tmdbid or subscribe.doubanid
custom_word_list = subscribe.custom_words.split("\n") if subscribe.custom_words else None custom_word_list = subscribe.custom_words.split("\n") if subscribe.custom_words else None
# 校验当前时间减订阅创建时间是否大于1分钟,否则跳过先,留出编辑订阅的时间 # 校验当前时间减订阅创建时间是否大于1分钟,否则跳过先,留出编辑订阅的时间
@@ -530,6 +532,8 @@ class SubscribeChain(ChainBase):
subscribes = self.subscribeoper.list('R') subscribes = self.subscribeoper.list('R')
# 遍历订阅 # 遍历订阅
for subscribe in subscribes: for subscribe in subscribes:
if global_vars.is_system_stopped:
break
logger.info(f'开始匹配订阅,标题:{subscribe.name} ...') logger.info(f'开始匹配订阅,标题:{subscribe.name} ...')
mediakey = subscribe.tmdbid or subscribe.doubanid mediakey = subscribe.tmdbid or subscribe.doubanid
# 生成元数据 # 生成元数据
@@ -606,6 +610,8 @@ class SubscribeChain(ChainBase):
# 遍历缓存种子 # 遍历缓存种子
_match_context = [] _match_context = []
for domain, contexts in torrents.items(): for domain, contexts in torrents.items():
if global_vars.is_system_stopped:
break
if domains and domain not in domains: if domains and domain not in domains:
continue continue
logger.debug(f'开始匹配站点:{domain},共缓存了 {len(contexts)} 个种子...') logger.debug(f'开始匹配站点:{domain},共缓存了 {len(contexts)} 个种子...')
@@ -776,6 +782,8 @@ class SubscribeChain(ChainBase):
return return
# 遍历订阅 # 遍历订阅
for subscribe in subscribes: for subscribe in subscribes:
if global_vars.is_system_stopped:
break
logger.info(f'开始更新订阅元数据:{subscribe.name} ...') logger.info(f'开始更新订阅元数据:{subscribe.name} ...')
# 生成元数据 # 生成元数据
meta = MetaInfo(subscribe.name) meta = MetaInfo(subscribe.name)
+5 -1
View File
@@ -6,7 +6,7 @@ from cachetools import cached, TTLCache
from app.chain import ChainBase from app.chain import ChainBase
from app.chain.media import MediaChain from app.chain.media import MediaChain
from app.core.config import settings from app.core.config import settings, global_vars
from app.core.context import TorrentInfo, Context, MediaInfo from app.core.context import TorrentInfo, Context, MediaInfo
from app.core.metainfo import MetaInfo from app.core.metainfo import MetaInfo
from app.db.site_oper import SiteOper from app.db.site_oper import SiteOper
@@ -158,6 +158,8 @@ class TorrentsChain(ChainBase, metaclass=Singleton):
domains = [] domains = []
# 遍历站点缓存资源 # 遍历站点缓存资源
for indexer in indexers: for indexer in indexers:
if global_vars.is_system_stopped:
break
# 未开启的站点不刷新 # 未开启的站点不刷新
if sites and indexer.get("id") not in sites: if sites and indexer.get("id") not in sites:
continue continue
@@ -185,6 +187,8 @@ class TorrentsChain(ChainBase, metaclass=Singleton):
logger.info(f'{indexer.get("name")} 没有新种子') logger.info(f'{indexer.get("name")} 没有新种子')
continue continue
for torrent in torrents: for torrent in torrents:
if global_vars.is_system_stopped:
break
logger.info(f'处理资源:{torrent.title} ...') logger.info(f'处理资源:{torrent.title} ...')
# 识别 # 识别
meta = MetaInfo(title=torrent.title, subtitle=torrent.description) meta = MetaInfo(title=torrent.title, subtitle=torrent.description)
+5 -1
View File
@@ -7,7 +7,7 @@ from app.chain import ChainBase
from app.chain.media import MediaChain from app.chain.media import MediaChain
from app.chain.storage import StorageChain from app.chain.storage import StorageChain
from app.chain.tmdb import TmdbChain from app.chain.tmdb import TmdbChain
from app.core.config import settings from app.core.config import settings, global_vars
from app.core.context import MediaInfo from app.core.context import MediaInfo
from app.core.meta import MetaBase from app.core.meta import MetaBase
from app.core.metainfo import MetaInfoPath from app.core.metainfo import MetaInfoPath
@@ -84,6 +84,8 @@ class TransferChain(ChainBase):
logger.info(f"获取到 {len(torrents)} 个已完成的下载任务") logger.info(f"获取到 {len(torrents)} 个已完成的下载任务")
for torrent in torrents: for torrent in torrents:
if global_vars.is_system_stopped:
break
# 文件路径 # 文件路径
file_path = torrent.path file_path = torrent.path
if not file_path.exists(): if not file_path.exists():
@@ -243,6 +245,8 @@ class TransferChain(ChainBase):
# 整理所有文件 # 整理所有文件
for file_item in file_items: for file_item in file_items:
if global_vars.is_system_stopped:
break
file_path = Path(file_item.path) file_path = Path(file_item.path)
# 回收站及隐藏的文件不处理 # 回收站及隐藏的文件不处理
if file_item.path.find('/@Recycle/') != -1 \ if file_item.path.find('/@Recycle/') != -1 \
+1
View File
@@ -510,6 +510,7 @@ class GlobalVar(object):
""" """
self.STOP_EVENT.set() self.STOP_EVENT.set()
@property
def is_system_stopped(self): def is_system_stopped(self):
""" """
是否停止 是否停止
+1 -1
View File
@@ -61,7 +61,7 @@ class ModuleManager(metaclass=Singleton):
logger.info(f"Moudle Stoped{module_id}") logger.info(f"Moudle Stoped{module_id}")
except Exception as err: except Exception as err:
logger.error(f"Stop Moudle Error{module_id}{str(err)} - {traceback.format_exc()}", exc_info=True) logger.error(f"Stop Moudle Error{module_id}{str(err)} - {traceback.format_exc()}", exc_info=True)
logger.info("模块停止完成") logger.info("所有模块停止完成")
def reload(self): def reload(self):
""" """
+7
View File
@@ -41,6 +41,13 @@ def get_db() -> Generator:
db.close() db.close()
def close_database():
"""
关闭所有数据库连接
"""
Engine.dispose()
def get_args_db(args: tuple, kwargs: dict) -> Optional[Session]: def get_args_db(args: tuple, kwargs: dict) -> Optional[Session]:
""" """
从参数中获取数据库Session对象 从参数中获取数据库Session对象
+3 -3
View File
@@ -9,14 +9,14 @@ def create_app() -> FastAPI:
""" """
创建并配置 FastAPI 应用实例 创建并配置 FastAPI 应用实例
""" """
app = FastAPI( _app = FastAPI(
title=settings.PROJECT_NAME, title=settings.PROJECT_NAME,
openapi_url=f"{settings.API_V1_STR}/openapi.json", openapi_url=f"{settings.API_V1_STR}/openapi.json",
lifespan=lifespan lifespan=lifespan
) )
# 配置 CORS 中间件 # 配置 CORS 中间件
app.add_middleware( _app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=settings.ALLOWED_HOSTS, allow_origins=settings.ALLOWED_HOSTS,
allow_credentials=True, allow_credentials=True,
@@ -24,7 +24,7 @@ def create_app() -> FastAPI:
allow_headers=["*"], allow_headers=["*"],
) )
return app return _app
# 创建 FastAPI 应用实例 # 创建 FastAPI 应用实例
+4
View File
@@ -6,6 +6,7 @@ from app.utils.system import SystemUtils
import os import os
class DisplayHelper(metaclass=Singleton): class DisplayHelper(metaclass=Singleton):
_display: Display = None _display: Display = None
@@ -20,4 +21,7 @@ class DisplayHelper(metaclass=Singleton):
def stop(self): def stop(self):
if self._display: if self._display:
logger.info("正在停止虚拟显示...")
self._display.stop() self._display.stop()
logger.info("虚拟显示已停止")
+2
View File
@@ -463,8 +463,10 @@ class Monitor(metaclass=Singleton):
if self._observers: if self._observers:
for observer in self._observers: for observer in self._observers:
try: try:
logger.info(f"正在停止目录监控服务:{observer}...")
observer.stop() observer.stop()
observer.join() observer.join()
logger.info(f"{observer} 目录监控已停止")
except Exception as e: except Exception as e:
logger.error(f"停止目录监控服务出现了错误:{e}") logger.error(f"停止目录监控服务出现了错误:{e}")
self._observers = [] self._observers = []
+13 -2
View File
@@ -26,6 +26,7 @@ from app.scheduler import Scheduler
from app.monitor import Monitor from app.monitor import Monitor
from app.command import Command, CommandChian from app.command import Command, CommandChian
from app.schemas import Notification, NotificationType from app.schemas import Notification, NotificationType
from app.db import close_database
def start_frontend(): def start_frontend():
@@ -63,6 +64,14 @@ def stop_frontend():
subprocess.Popen(f"taskkill /f /im nginx.exe", shell=True) subprocess.Popen(f"taskkill /f /im nginx.exe", shell=True)
def clear_temp():
"""
清理临时目录中3天前的文件
"""
# 清理3天前的文件
SystemUtils.clear(settings.TEMP_PATH, days=3)
def check_auth(): def check_auth():
""" """
检查认证状态 检查认证状态
@@ -97,7 +106,7 @@ def singal_handle():
signal.signal(signal.SIGINT, stop_event) signal.signal(signal.SIGINT, stop_event)
def shutdown_modules(app: FastAPI): def shutdown_modules(_: FastAPI):
""" """
服务关闭 服务关闭
""" """
@@ -116,11 +125,13 @@ def shutdown_modules(app: FastAPI):
Monitor().stop() Monitor().stop()
# 停止线程池 # 停止线程池
ThreadHelper().shutdown() ThreadHelper().shutdown()
# 停止数据库连接
close_database()
# 停止前端服务 # 停止前端服务
stop_frontend() stop_frontend()
def start_modules(app: FastAPI): def start_modules(_: FastAPI):
""" """
启动模块 启动模块
""" """
+18 -2
View File
@@ -163,7 +163,8 @@ class SystemUtils:
return -1, str(err) return -1, str(err)
@staticmethod @staticmethod
def list_files(directory: Path, extensions: list, min_filesize: int = 0, recursive: bool = True) -> List[Path]: def list_files(directory: Path, extensions: list = None,
min_filesize: int = 0, recursive: bool = True) -> List[Path]:
""" """
获取目录下所有指定扩展名的文件包括子目录 获取目录下所有指定扩展名的文件包括子目录
:param directory: 指定的父目录 :param directory: 指定的父目录
@@ -186,7 +187,10 @@ class SystemUtils:
min_filesize = 0 min_filesize = 0
files = [] files = []
pattern = r".*(" + "|".join(extensions) + ")$" if extensions:
pattern = r".*(" + "|".join(extensions) + ")$"
else:
pattern = r".*"
# 遍历目录及子目录 # 遍历目录及子目录
for matched_glob in glob(str(directory / '**'), recursive=recursive, include_hidden=True): for matched_glob in glob(str(directory / '**'), recursive=recursive, include_hidden=True):
@@ -529,3 +533,15 @@ class SystemUtils:
获取配置路径 获取配置路径
""" """
return SystemUtils.get_config_path() / "app.env" return SystemUtils.get_config_path() / "app.env"
@staticmethod
def clear(temp_path: Path, days: int):
"""
清理临时目录中指定天数前的文件
"""
if not temp_path.exists():
return
for file in temp_path.glob('*'):
if file.is_file() \
and (datetime.datetime.now() - datetime.datetime.fromtimestamp(file.stat().st_mtime)).days > days:
file.unlink()