mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 15:38:19 +08:00
feat(transfer): enhance job removal methods for thread safety and strict checks
This commit is contained in:
+121
-83
@@ -224,7 +224,7 @@ class JobManager:
|
|||||||
|
|
||||||
def remove_job(self, task: TransferTask) -> Optional[TransferJob]:
|
def remove_job(self, task: TransferTask) -> Optional[TransferJob]:
|
||||||
"""
|
"""
|
||||||
移除任务对应的作业
|
移除任务对应的作业(强制,线程不安全)
|
||||||
"""
|
"""
|
||||||
with job_lock:
|
with job_lock:
|
||||||
__mediaid__ = self.__get_id(task)
|
__mediaid__ = self.__get_id(task)
|
||||||
@@ -235,68 +235,99 @@ class JobManager:
|
|||||||
return self._job_view.pop(__mediaid__)
|
return self._job_view.pop(__mediaid__)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def try_remove_job(self, task: TransferTask):
|
||||||
|
"""
|
||||||
|
尝试移除任务对应的作业(严格检查未完成作业,线程安全)
|
||||||
|
"""
|
||||||
|
with job_lock:
|
||||||
|
__metaid__ = self.__get_meta_id(meta=task.meta, season=task.meta.begin_season)
|
||||||
|
__mediaid__ = self.__get_media_id(media=task.mediainfo, season=task.meta.begin_season)
|
||||||
|
|
||||||
|
meta_done = True
|
||||||
|
if __metaid__ in self._job_view:
|
||||||
|
meta_done = all(
|
||||||
|
t.state in ["completed", "failed"] for t in self._job_view[__metaid__].tasks
|
||||||
|
)
|
||||||
|
|
||||||
|
media_done = True
|
||||||
|
if __mediaid__ in self._job_view:
|
||||||
|
media_done = all(
|
||||||
|
t.state in ["completed", "failed"] for t in self._job_view[__mediaid__].tasks
|
||||||
|
)
|
||||||
|
|
||||||
|
if meta_done and media_done:
|
||||||
|
__id__ = self.__get_id(task)
|
||||||
|
if __id__ in self._job_view:
|
||||||
|
# 移除季集信息
|
||||||
|
if __id__ in self._season_episodes:
|
||||||
|
self._season_episodes.pop(__id__)
|
||||||
|
self._job_view.pop(__id__)
|
||||||
|
|
||||||
def is_done(self, task: TransferTask) -> bool:
|
def is_done(self, task: TransferTask) -> bool:
|
||||||
"""
|
"""
|
||||||
检查任务对应的作业是否整理完成(不管成功还是失败)
|
检查任务对应的作业是否整理完成(不管成功还是失败)
|
||||||
"""
|
"""
|
||||||
__metaid__ = self.__get_meta_id(meta=task.meta, season=task.meta.begin_season)
|
with job_lock:
|
||||||
__mediaid__ = self.__get_media_id(media=task.mediainfo, season=task.meta.begin_season)
|
__metaid__ = self.__get_meta_id(meta=task.meta, season=task.meta.begin_season)
|
||||||
if __metaid__ in self._job_view:
|
__mediaid__ = self.__get_media_id(media=task.mediainfo, season=task.meta.begin_season)
|
||||||
meta_done = all(
|
if __metaid__ in self._job_view:
|
||||||
task.state in ["completed", "failed"] for task in self._job_view[__metaid__].tasks
|
meta_done = all(
|
||||||
)
|
task.state in ["completed", "failed"] for task in self._job_view[__metaid__].tasks
|
||||||
else:
|
)
|
||||||
meta_done = True
|
else:
|
||||||
if __mediaid__ in self._job_view:
|
meta_done = True
|
||||||
media_done = all(
|
if __mediaid__ in self._job_view:
|
||||||
task.state in ["completed", "failed"] for task in self._job_view[__mediaid__].tasks
|
media_done = all(
|
||||||
)
|
task.state in ["completed", "failed"] for task in self._job_view[__mediaid__].tasks
|
||||||
else:
|
)
|
||||||
media_done = True
|
else:
|
||||||
return meta_done and media_done
|
media_done = True
|
||||||
|
return meta_done and media_done
|
||||||
|
|
||||||
def is_finished(self, task: TransferTask) -> bool:
|
def is_finished(self, task: TransferTask) -> bool:
|
||||||
"""
|
"""
|
||||||
检查任务对应的作业是否已完成且有成功的记录
|
检查任务对应的作业是否已完成且有成功的记录
|
||||||
"""
|
"""
|
||||||
__metaid__ = self.__get_meta_id(meta=task.meta, season=task.meta.begin_season)
|
with job_lock:
|
||||||
__mediaid__ = self.__get_media_id(media=task.mediainfo, season=task.meta.begin_season)
|
__metaid__ = self.__get_meta_id(meta=task.meta, season=task.meta.begin_season)
|
||||||
if __metaid__ in self._job_view:
|
__mediaid__ = self.__get_media_id(media=task.mediainfo, season=task.meta.begin_season)
|
||||||
meta_finished = all(
|
if __metaid__ in self._job_view:
|
||||||
task.state in ["completed", "failed"] for task in self._job_view[__metaid__].tasks
|
meta_finished = all(
|
||||||
)
|
task.state in ["completed", "failed"] for task in self._job_view[__metaid__].tasks
|
||||||
else:
|
)
|
||||||
meta_finished = True
|
else:
|
||||||
if __mediaid__ in self._job_view:
|
meta_finished = True
|
||||||
tasks = self._job_view[__mediaid__].tasks
|
if __mediaid__ in self._job_view:
|
||||||
media_finished = all(
|
tasks = self._job_view[__mediaid__].tasks
|
||||||
task.state in ["completed", "failed"] for task in tasks
|
media_finished = all(
|
||||||
) and any(
|
task.state in ["completed", "failed"] for task in tasks
|
||||||
task.state == "completed" for task in tasks
|
) and any(
|
||||||
)
|
task.state == "completed" for task in tasks
|
||||||
else:
|
)
|
||||||
media_finished = True
|
else:
|
||||||
return meta_finished and media_finished
|
media_finished = True
|
||||||
|
return meta_finished and media_finished
|
||||||
|
|
||||||
def is_success(self, task: TransferTask) -> bool:
|
def is_success(self, task: TransferTask) -> bool:
|
||||||
"""
|
"""
|
||||||
检查任务对应的作业是否全部成功
|
检查任务对应的作业是否全部成功
|
||||||
"""
|
"""
|
||||||
__metaid__ = self.__get_meta_id(meta=task.meta, season=task.meta.begin_season)
|
with job_lock:
|
||||||
__mediaid__ = self.__get_media_id(media=task.mediainfo, season=task.meta.begin_season)
|
__metaid__ = self.__get_meta_id(meta=task.meta, season=task.meta.begin_season)
|
||||||
if __metaid__ in self._job_view:
|
__mediaid__ = self.__get_media_id(media=task.mediainfo, season=task.meta.begin_season)
|
||||||
meta_success = all(
|
if __metaid__ in self._job_view:
|
||||||
task.state in ["completed"] for task in self._job_view[__metaid__].tasks
|
meta_success = all(
|
||||||
)
|
task.state in ["completed"] for task in self._job_view[__metaid__].tasks
|
||||||
else:
|
)
|
||||||
meta_success = True
|
else:
|
||||||
if __mediaid__ in self._job_view:
|
meta_success = True
|
||||||
media_success = all(
|
if __mediaid__ in self._job_view:
|
||||||
task.state in ["completed"] for task in self._job_view[__mediaid__].tasks
|
media_success = all(
|
||||||
)
|
task.state in ["completed"] for task in self._job_view[__mediaid__].tasks
|
||||||
else:
|
)
|
||||||
media_success = True
|
else:
|
||||||
return meta_success and media_success
|
media_success = True
|
||||||
|
return meta_success and media_success
|
||||||
|
|
||||||
def get_all_torrent_hashes(self) -> set[str]:
|
def get_all_torrent_hashes(self) -> set[str]:
|
||||||
"""
|
"""
|
||||||
@@ -337,74 +368,82 @@ class JobManager:
|
|||||||
"""
|
"""
|
||||||
判断作业是否还有任务正在处理
|
判断作业是否还有任务正在处理
|
||||||
"""
|
"""
|
||||||
if mediainfo:
|
with job_lock:
|
||||||
__mediaid__ = self.__get_media_id(media=mediainfo, season=season)
|
if mediainfo:
|
||||||
if __mediaid__ in self._job_view:
|
__mediaid__ = self.__get_media_id(media=mediainfo, season=season)
|
||||||
return True
|
if __mediaid__ in self._job_view:
|
||||||
|
return True
|
||||||
|
|
||||||
__metaid__ = self.__get_meta_id(meta=meta, season=season)
|
__metaid__ = self.__get_meta_id(meta=meta, season=season)
|
||||||
return __metaid__ in self._job_view and len(self._job_view[__metaid__].tasks) > 0
|
return __metaid__ in self._job_view and len(self._job_view[__metaid__].tasks) > 0
|
||||||
|
|
||||||
def success_tasks(self, media: MediaInfo, season: Optional[int] = None) -> List[TransferJobTask]:
|
def success_tasks(self, media: MediaInfo, season: Optional[int] = None) -> List[TransferJobTask]:
|
||||||
"""
|
"""
|
||||||
获取作业中所有成功的任务
|
获取作业中所有成功的任务
|
||||||
"""
|
"""
|
||||||
__mediaid__ = self.__get_media_id(media=media, season=season)
|
with job_lock:
|
||||||
if __mediaid__ not in self._job_view:
|
__mediaid__ = self.__get_media_id(media=media, season=season)
|
||||||
return []
|
if __mediaid__ not in self._job_view:
|
||||||
return [task for task in self._job_view[__mediaid__].tasks if task.state == "completed"]
|
return []
|
||||||
|
return [task for task in self._job_view[__mediaid__].tasks if task.state == "completed"]
|
||||||
|
|
||||||
def all_tasks(self, media: MediaInfo, season: Optional[int] = None) -> List[TransferJobTask]:
|
def all_tasks(self, media: MediaInfo, season: Optional[int] = None) -> List[TransferJobTask]:
|
||||||
"""
|
"""
|
||||||
获取作业中全部任务
|
获取作业中全部任务
|
||||||
"""
|
"""
|
||||||
__mediaid__ = self.__get_media_id(media=media, season=season)
|
with job_lock:
|
||||||
if __mediaid__ not in self._job_view:
|
__mediaid__ = self.__get_media_id(media=media, season=season)
|
||||||
return []
|
if __mediaid__ not in self._job_view:
|
||||||
return self._job_view[__mediaid__].tasks
|
return []
|
||||||
|
return self._job_view[__mediaid__].tasks
|
||||||
|
|
||||||
def count(self, media: MediaInfo, season: Optional[int] = None) -> int:
|
def count(self, media: MediaInfo, season: Optional[int] = None) -> int:
|
||||||
"""
|
"""
|
||||||
获取作业中成功总数
|
获取作业中成功总数
|
||||||
"""
|
"""
|
||||||
__mediaid__ = self.__get_media_id(media=media, season=season)
|
with job_lock:
|
||||||
if __mediaid__ not in self._job_view:
|
__mediaid__ = self.__get_media_id(media=media, season=season)
|
||||||
return 0
|
if __mediaid__ not in self._job_view:
|
||||||
return len([task for task in self._job_view[__mediaid__].tasks if task.state == "completed"])
|
return 0
|
||||||
|
return len([task for task in self._job_view[__mediaid__].tasks if task.state == "completed"])
|
||||||
|
|
||||||
def size(self, media: MediaInfo, season: Optional[int] = None) -> int:
|
def size(self, media: MediaInfo, season: Optional[int] = None) -> int:
|
||||||
"""
|
"""
|
||||||
获取作业中所有成功文件总大小
|
获取作业中所有成功文件总大小
|
||||||
"""
|
"""
|
||||||
__mediaid__ = self.__get_media_id(media=media, season=season)
|
with job_lock:
|
||||||
if __mediaid__ not in self._job_view:
|
__mediaid__ = self.__get_media_id(media=media, season=season)
|
||||||
return 0
|
if __mediaid__ not in self._job_view:
|
||||||
return sum([
|
return 0
|
||||||
task.fileitem.size if task.fileitem.size is not None
|
return sum([
|
||||||
else (
|
task.fileitem.size if task.fileitem.size is not None
|
||||||
SystemUtils.get_directory_size(Path(task.fileitem.path)) if task.fileitem.storage == "local" else 0)
|
else (
|
||||||
for task in self._job_view[__mediaid__].tasks
|
SystemUtils.get_directory_size(Path(task.fileitem.path)) if task.fileitem.storage == "local" else 0)
|
||||||
if task.state == "completed"
|
for task in self._job_view[__mediaid__].tasks
|
||||||
])
|
if task.state == "completed"
|
||||||
|
])
|
||||||
|
|
||||||
def total(self) -> int:
|
def total(self) -> int:
|
||||||
"""
|
"""
|
||||||
获取所有任务总数
|
获取所有任务总数
|
||||||
"""
|
"""
|
||||||
return sum([len(job.tasks) for job in self._job_view.values()])
|
with job_lock:
|
||||||
|
return sum([len(job.tasks) for job in self._job_view.values()])
|
||||||
|
|
||||||
def list_jobs(self) -> List[TransferJob]:
|
def list_jobs(self) -> List[TransferJob]:
|
||||||
"""
|
"""
|
||||||
获取所有作业的任务列表
|
获取所有作业的任务列表
|
||||||
"""
|
"""
|
||||||
return list(self._job_view.values())
|
with job_lock:
|
||||||
|
return list(self._job_view.values())
|
||||||
|
|
||||||
def season_episodes(self, media: MediaInfo, season: Optional[int] = None) -> List[int]:
|
def season_episodes(self, media: MediaInfo, season: Optional[int] = None) -> List[int]:
|
||||||
"""
|
"""
|
||||||
获取作业的季集清单
|
获取作业的季集清单
|
||||||
"""
|
"""
|
||||||
__mediaid__ = self.__get_media_id(media=media, season=season)
|
with job_lock:
|
||||||
return self._season_episodes.get(__mediaid__) or []
|
__mediaid__ = self.__get_media_id(media=media, season=season)
|
||||||
|
return self._season_episodes.get(__mediaid__) or []
|
||||||
|
|
||||||
|
|
||||||
class TransferChain(ChainBase, ConfigReloadMixin, metaclass=Singleton):
|
class TransferChain(ChainBase, ConfigReloadMixin, metaclass=Singleton):
|
||||||
@@ -1006,8 +1045,7 @@ class TransferChain(ChainBase, ConfigReloadMixin, metaclass=Singleton):
|
|||||||
|
|
||||||
finally:
|
finally:
|
||||||
# 移除已完成的任务
|
# 移除已完成的任务
|
||||||
if self.jobview.is_done(task):
|
self.jobview.try_remove_job(task)
|
||||||
self.jobview.remove_job(task)
|
|
||||||
|
|
||||||
def get_queue_tasks(self) -> List[TransferJob]:
|
def get_queue_tasks(self) -> List[TransferJob]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user