mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-06-11 18:50:59 +08:00
feat(workflow): enhance workflow execution and context management
This commit is contained in:
@@ -63,9 +63,18 @@ class WorkFlowManager(metaclass=Singleton):
|
||||
"""
|
||||
停止
|
||||
"""
|
||||
for event_type_str in list(self._event_workflows.keys()):
|
||||
self.remove_workflow_event(event_type_str=event_type_str)
|
||||
self._actions = {}
|
||||
self._event_workflows = {}
|
||||
|
||||
def execute(self, workflow_id: int, action: Action,
|
||||
context: ActionContext = None) -> Tuple[bool, str, ActionContext]:
|
||||
"""
|
||||
执行工作流动作
|
||||
"""
|
||||
return self.excute(workflow_id=workflow_id, action=action, context=context)
|
||||
|
||||
def excute(self, workflow_id: int, action: Action,
|
||||
context: ActionContext = None) -> Tuple[bool, str, ActionContext]:
|
||||
"""
|
||||
@@ -126,8 +135,8 @@ class WorkFlowManager(metaclass=Singleton):
|
||||
"""
|
||||
更新工作流事件触发器
|
||||
"""
|
||||
# 确保先移除旧的事件监听器
|
||||
self.remove_workflow_event(workflow_id=workflow.id, event_type_str=workflow.event_type)
|
||||
# 工作流可能切换触发事件,先按工作流ID从所有事件映射中移除。
|
||||
self.remove_workflow_event(workflow_id=workflow.id)
|
||||
# 如果工作流是事件触发类型且未被禁用
|
||||
if workflow.trigger_type == "event" and workflow.state != 'P':
|
||||
# 注册事件触发器
|
||||
@@ -154,41 +163,46 @@ class WorkFlowManager(metaclass=Singleton):
|
||||
"""
|
||||
注册工作流事件触发器
|
||||
"""
|
||||
if not event_type_str:
|
||||
return
|
||||
try:
|
||||
event_type = EventType(event_type_str)
|
||||
except ValueError:
|
||||
logger.error(f"无效的事件类型: {event_type_str}")
|
||||
return
|
||||
if event_type in EventType:
|
||||
# 确保先移除旧的事件监听器
|
||||
self.remove_workflow_event(workflow_id, event_type.value)
|
||||
with self._lock:
|
||||
# 添加新的事件监听器
|
||||
eventmanager.add_event_listener(event_type, self._handle_event)
|
||||
# 记录工作流事件触发器
|
||||
if event_type.value not in self._event_workflows:
|
||||
self._event_workflows[event_type.value] = []
|
||||
self._event_workflows[event_type.value].append(workflow_id)
|
||||
eventmanager.add_event_listener(event_type, self._handle_event)
|
||||
# 记录工作流事件触发器
|
||||
if workflow_id not in self._event_workflows[event_type.value]:
|
||||
self._event_workflows[event_type.value].append(workflow_id)
|
||||
logger.info(f"已注册工作流 {workflow_id} 事件触发器: {event_type.value}")
|
||||
|
||||
def remove_workflow_event(self, workflow_id: int, event_type_str: str):
|
||||
def remove_workflow_event(self, workflow_id: Optional[int] = None, event_type_str: Optional[str] = None):
|
||||
"""
|
||||
移除工作流事件触发器
|
||||
"""
|
||||
try:
|
||||
event_type = EventType(event_type_str)
|
||||
except ValueError:
|
||||
logger.error(f"无效的事件类型: {event_type_str}")
|
||||
return
|
||||
if event_type in EventType:
|
||||
event_type_values = [event_type_str] if event_type_str else list(self._event_workflows.keys())
|
||||
for event_type_value in event_type_values:
|
||||
try:
|
||||
event_type = EventType(event_type_value)
|
||||
except ValueError:
|
||||
logger.error(f"无效的事件类型: {event_type_value}")
|
||||
continue
|
||||
with self._lock:
|
||||
eventmanager.remove_event_listener(event_type, self._handle_event)
|
||||
if event_type.value in self._event_workflows:
|
||||
if workflow_id in self._event_workflows[event_type.value]:
|
||||
self._event_workflows[event_type.value].remove(workflow_id)
|
||||
if not self._event_workflows[event_type.value]:
|
||||
del self._event_workflows[event_type.value]
|
||||
logger.info(f"已移除工作流 {workflow_id} 事件触发器")
|
||||
workflow_ids = self._event_workflows.get(event_type.value)
|
||||
if not workflow_ids:
|
||||
continue
|
||||
if workflow_id is None:
|
||||
workflow_ids.clear()
|
||||
elif workflow_id in workflow_ids:
|
||||
workflow_ids.remove(workflow_id)
|
||||
if not workflow_ids:
|
||||
self._event_workflows.pop(event_type.value, None)
|
||||
eventmanager.remove_event_listener(event_type, self._handle_event)
|
||||
logger.info(f"已移除工作流 {workflow_id or ''} 事件触发器")
|
||||
|
||||
def _handle_event(self, event: Event):
|
||||
"""
|
||||
|
||||
@@ -26,6 +26,8 @@ class BaseAction(ABC):
|
||||
|
||||
def __init__(self, action_id: str):
|
||||
self._action_id = action_id
|
||||
self._done_flag = False
|
||||
self._message = ""
|
||||
self.systemconfigoper = SystemConfigOper()
|
||||
|
||||
@classmethod
|
||||
@@ -92,9 +94,12 @@ class BaseAction(ABC):
|
||||
workflow_cache = self.systemconfigoper.get(workflow_key) or {}
|
||||
action_cache = workflow_cache.get(self._action_id) or []
|
||||
if isinstance(data, list):
|
||||
action_cache.extend(data)
|
||||
for item in data:
|
||||
if item not in action_cache:
|
||||
action_cache.append(item)
|
||||
else:
|
||||
action_cache.append(data)
|
||||
if data not in action_cache:
|
||||
action_cache.append(data)
|
||||
workflow_cache[self._action_id] = action_cache
|
||||
self.systemconfigoper.set(workflow_key, workflow_cache)
|
||||
|
||||
|
||||
@@ -43,12 +43,19 @@ class FetchDownloadsAction(BaseAction):
|
||||
"""
|
||||
更新downloads中的下载任务状态
|
||||
"""
|
||||
__all_complete = False
|
||||
self._downloads = context.downloads or []
|
||||
if not self._downloads:
|
||||
self.job_done("无下载任务")
|
||||
return context
|
||||
|
||||
for download in self._downloads:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
logger.info(f"获取下载任务 {download.download_id} 状态 ...")
|
||||
torrents = ActionChain().list_torrents(hashs=[download.download_id])
|
||||
torrents = ActionChain().list_torrents(
|
||||
hashs=[download.download_id],
|
||||
downloader=download.downloader,
|
||||
)
|
||||
if not torrents:
|
||||
download.completed = True
|
||||
continue
|
||||
@@ -61,5 +68,5 @@ class FetchDownloadsAction(BaseAction):
|
||||
logger.info(f"下载任务 {download.download_id} 未完成")
|
||||
download.completed = False
|
||||
if all([d.completed for d in self._downloads]):
|
||||
self.job_done()
|
||||
self.job_done("下载任务已全部完成")
|
||||
return context
|
||||
|
||||
@@ -61,18 +61,18 @@ class ScrapeFileAction(BaseAction):
|
||||
logger.info(f"{fileitem.path} 已刮削过,跳过")
|
||||
continue
|
||||
mediachain = MediaChain()
|
||||
context = mediachain.recognize_by_path(
|
||||
media_context = mediachain.recognize_by_path(
|
||||
fileitem.path,
|
||||
obtain_images=True,
|
||||
)
|
||||
if not context or not context.media_info:
|
||||
if not media_context or not media_context.media_info:
|
||||
_failed_count += 1
|
||||
logger.info(f"{fileitem.path} 未识别到媒体信息,无法刮削")
|
||||
continue
|
||||
mediachain.scrape_metadata(
|
||||
fileitem=fileitem,
|
||||
meta=context.meta_info,
|
||||
mediainfo=context.media_info
|
||||
meta=media_context.meta_info,
|
||||
mediainfo=media_context.media_info
|
||||
)
|
||||
self._scraped_files.append(fileitem)
|
||||
# 保存缓存
|
||||
|
||||
Reference in New Issue
Block a user