refactor: strengthen architecture CI gates and runtime contracts

This commit is contained in:
jxxghp
2026-08-25 17:02:29 +08:00
parent 605bf8174a
commit b914e8b6e4
123 changed files with 4240 additions and 1342 deletions
+2 -4
View File
@@ -1,11 +1,9 @@
from abc import ABC, abstractmethod
from typing import Any, ClassVar, Union
from app.chain import ChainBase
from app.application.configuration import get_configured_system_config
from app.schemas.workflow import ActionContext
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionResult
from app.chain import ChainBase
from app.schemas.workflow import ActionContext, ActionParams, ActionResult
class ActionChain(ChainBase):
+4 -6
View File
@@ -2,16 +2,14 @@ from typing import Optional
from pydantic import Field
from app.workflow.actions import BaseAction
from app.chain.download import DownloadChain
from app.chain.media import MediaChain
from app.runtime.config import global_vars
from app.domain.metainfo import MetaInfo
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.schemas.workflow import DownloadTask
from app.runtime.stop import runtime_stop_state
from app.schemas.types import MediaType
from app.schemas.workflow import ActionContext, ActionParams, DownloadTask
from app.workflow.actions import BaseAction
class AddDownloadParams(ActionParams):
@@ -55,7 +53,7 @@ class AddDownloadAction(BaseAction):
params = AddDownloadParams(**params)
_started = False
for t in context.torrents:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
# 检查缓存
cache_key = f"{t.torrent_info.site}-{t.torrent_info.title}"
+7 -8
View File
@@ -1,12 +1,11 @@
from app.workflow.actions import BaseAction
from app.chain.subscribe import SubscribeChain
from app.application.configuration import get_chain_runtime_config_snapshot
from app.runtime.config import global_vars
from app.domain.context import MediaInfo
from app.application.chain.data import get_chain_subscribe_port
from app.application.configuration import get_chain_runtime_config_snapshot
from app.chain.subscribe import SubscribeChain
from app.domain.context import MediaInfo
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.runtime.stop import runtime_stop_state
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import BaseAction
class AddSubscribeParams(ActionParams):
@@ -45,7 +44,7 @@ class AddSubscribeAction(BaseAction):
"""
_started = False
for media in context.medias:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
# 检查缓存
cache_key = f"{media.type}-{media.title}-{media.year}-{media.season}"
+4 -5
View File
@@ -1,8 +1,7 @@
from app.workflow.actions import BaseAction, ActionChain
from app.runtime.config import global_vars
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.runtime.log import logger
from app.runtime.stop import runtime_stop_state
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import ActionChain, BaseAction
class FetchDownloadsParams(ActionParams):
@@ -45,7 +44,7 @@ class FetchDownloadsAction(BaseAction):
return context
for download in self._downloads:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
logger.info(f"获取下载任务 {download.download_id} 状态 ...")
torrents = ActionChain().list_torrents(
+6 -8
View File
@@ -2,18 +2,16 @@ from typing import List, Optional
from pydantic import Field
from app.workflow.actions import BaseAction
from app.chain.recommend import RecommendChain
from app.adapters.network.http import RequestUtils
from app.application.configuration import get_chain_runtime_config_snapshot
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.runtime.config import global_vars
from app.chain.recommend import RecommendChain
from app.runtime.events import eventmanager
from app.runtime.log import logger
from app.runtime.stop import runtime_stop_state
from app.schemas.event import RecommendSourceEventData
from app.schemas.workflow import MediaInfo
from app.schemas.types import ChainEventType
from app.adapters.network.http import RequestUtils
from app.schemas.workflow import ActionContext, ActionParams, MediaInfo
from app.workflow.actions import BaseAction
class FetchMediasParams(ActionParams):
@@ -141,7 +139,7 @@ class FetchMediasAction(BaseAction):
try:
if params.source_type == "ranking":
for api_path in params.sources:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
source = self.__get_source(api_path)
if not source:
+6 -7
View File
@@ -2,16 +2,15 @@ from typing import Optional
from pydantic import Field
from app.workflow.actions import BaseAction
from app.chain.media import MediaChain
from app.application.configuration import get_chain_runtime_config_snapshot
from app.runtime.config import global_vars
from app.application.rss import RssHelper
from app.chain.media import MediaChain
from app.domain.context import Context, TorrentInfo
from app.domain.metainfo import MetaInfo
from app.application.rss import RssHelper
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.runtime.stop import runtime_stop_state
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import BaseAction
class FetchRssParams(ActionParams):
@@ -84,7 +83,7 @@ class FetchRssAction(BaseAction):
# 组装种子
for item in rss_items:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
if not item.get("title"):
continue
+6 -7
View File
@@ -1,17 +1,16 @@
import random
import time
from typing import Optional, List
from typing import List, Optional
from pydantic import Field
from app.workflow.actions import BaseAction
from app.chain.media import MediaChain
from app.chain.search import SearchChain
from app.runtime.config import global_vars
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.runtime.stop import runtime_stop_state
from app.schemas.types import MediaType
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import BaseAction
class FetchTorrentsParams(ActionParams):
@@ -59,7 +58,7 @@ class FetchTorrentsAction(BaseAction):
# 按关键字搜索
torrents = searchchain.search_by_title(title=params.name, sites=params.sites)
for torrent in torrents:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
if params.year and torrent.meta_info.year != params.year:
continue
@@ -80,7 +79,7 @@ class FetchTorrentsAction(BaseAction):
else:
# 搜索媒体列表
for media in context.medias:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
torrents = searchchain.search_by_id(
media_source=media.media_source,
+4 -5
View File
@@ -2,11 +2,10 @@ from typing import Optional
from pydantic import Field
from app.workflow.actions import BaseAction
from app.runtime.config import global_vars
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.runtime.stop import runtime_stop_state
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import BaseAction
class FilterMediasParams(ActionParams):
@@ -46,7 +45,7 @@ class FilterMediasAction(BaseAction):
"""
params = FilterMediasParams(**params)
for media in context.medias:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
if params.type and media.type != params.type:
continue
+5 -6
View File
@@ -1,13 +1,12 @@
from typing import Optional, List
from typing import List, Optional
from pydantic import Field
from app.workflow.actions import BaseAction, ActionChain
from app.runtime.config import global_vars
from app.application.torrent import TorrentHelper
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.runtime.stop import runtime_stop_state
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import ActionChain, BaseAction
class FilterTorrentsParams(ActionParams):
@@ -51,7 +50,7 @@ class FilterTorrentsAction(BaseAction):
"""
params = FilterTorrentsParams(**params)
for torrent in context.torrents:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
if TorrentHelper().filter_torrent(
torrent_info=torrent.torrent_info,
+2 -3
View File
@@ -1,10 +1,9 @@
from pydantic import Field
from app.workflow.actions import BaseAction
from app.application.plugin.runtime import get_plugin_manager
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import BaseAction
class InvokePluginParams(ActionParams):
+1 -1
View File
@@ -1,5 +1,5 @@
from app.workflow.actions import BaseAction
from app.schemas.workflow import ActionContext
from app.workflow.actions import BaseAction
class NoteAction(BaseAction):
+5 -6
View File
@@ -3,13 +3,12 @@ from typing import Optional
from pydantic import Field
from app.workflow.actions import BaseAction
from app.chain.storage import StorageChain
from app.application.configuration import get_chain_runtime_config_snapshot
from app.runtime.config import global_vars
from app.chain.storage import StorageChain
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.runtime.stop import runtime_stop_state
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import BaseAction
class ScanFileParams(ActionParams):
@@ -64,7 +63,7 @@ class ScanFileAction(BaseAction):
+ runtime_config.audio_extensions
)
for file in files:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
if not file.extension or f".{file.extension.lower()}" not in media_exts:
continue
+3 -4
View File
@@ -1,10 +1,9 @@
from app.chain.media import MediaChain
from app.chain.scraping import ScrapingChain
from app.chain.storage import StorageChain
from app.runtime.config import global_vars
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.runtime.stop import runtime_stop_state
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import BaseAction
@@ -45,7 +44,7 @@ class ScrapeFileAction(BaseAction):
# 失败次数
_failed_count = 0
for fileitem in context.fileitems:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
if fileitem in self._scraped_files:
continue
+2 -3
View File
@@ -1,8 +1,7 @@
from app.workflow.actions import BaseAction
from app.runtime.events import eventmanager
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.schemas.types import ChainEventType
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import BaseAction
class SendEventParams(ActionParams):
+2 -3
View File
@@ -2,11 +2,10 @@ from typing import List, Optional, Union
from pydantic import Field
from app.workflow.actions import BaseAction, ActionChain
from app.application.configuration import get_chain_runtime_config_snapshot
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.schemas.message import Message
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import ActionChain, BaseAction
class SendMessageParams(ActionParams):
+5 -6
View File
@@ -4,14 +4,13 @@ from typing import Optional
from pydantic import Field
from app.workflow.actions import BaseAction
from app.runtime.config import global_vars
from app.application.chain.data import get_chain_transfer_history_port
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
from app.chain.storage import StorageChain
from app.chain.transfer import TransferChain
from app.runtime.log import logger
from app.runtime.stop import runtime_stop_state
from app.schemas.workflow import ActionContext, ActionParams
from app.workflow.actions import BaseAction
class TransferFileParams(ActionParams):
@@ -58,7 +57,7 @@ class TransferFileAction(BaseAction):
"""
检查是否继续整理文件
"""
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
return False
return True
@@ -71,7 +70,7 @@ class TransferFileAction(BaseAction):
if params.source == "downloads":
# 从下载任务中整理文件
for download in context.downloads:
if global_vars.is_workflow_stopped(workflow_id):
if runtime_stop_state.is_workflow_stopped(workflow_id):
break
if not download.completed:
logger.info(f"下载任务 {download.download_id} 未完成")