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