feat(ai-studio): make original downloads nonblocking
This commit is contained in:
+91
-9
@@ -5,6 +5,7 @@ from __future__ import annotations
|
||||
import datetime as _dt
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
|
||||
from .. import image_studio, image_studio_export, image_studio_generation, image_studio_images
|
||||
from .widgets import *
|
||||
@@ -110,22 +111,103 @@ class ImageStudioPullImagesWorker(BaseWorker):
|
||||
class ImageStudioDownloadOriginalWorker(BaseWorker):
|
||||
"""Download one remote original image into the project pool."""
|
||||
|
||||
def __init__(self, asset_id, *, db_path=None, config=None, open_after=False):
|
||||
def __init__(
|
||||
self,
|
||||
asset_id,
|
||||
*,
|
||||
db_path=None,
|
||||
config=None,
|
||||
open_after=False,
|
||||
max_retries=2,
|
||||
retry_delays=(1, 2),
|
||||
):
|
||||
super().__init__()
|
||||
self.asset_id = int(asset_id)
|
||||
self.db_path = db_path
|
||||
self.config = config
|
||||
self.open_after = bool(open_after)
|
||||
self.max_retries = max(0, int(max_retries or 0))
|
||||
self.retry_delays = tuple(float(delay) for delay in (retry_delays or ()))
|
||||
|
||||
def execute(self):
|
||||
self.log.emit("[AI工场] 下载原图:开始")
|
||||
asset = image_studio_images.download_original_asset(
|
||||
self.asset_id,
|
||||
path=self.db_path,
|
||||
config=self.config,
|
||||
)
|
||||
self.log.emit("[AI工场] 下载原图:成功")
|
||||
return {"asset": asset, "open_after": self.open_after}
|
||||
attempts = self.max_retries + 1
|
||||
for attempt in range(1, attempts + 1):
|
||||
if self.should_cancel():
|
||||
return {"asset_id": self.asset_id, "cancelled": True}
|
||||
self.progress.emit(
|
||||
{
|
||||
"asset_id": self.asset_id,
|
||||
"state": "start",
|
||||
"attempt": attempt,
|
||||
"attempts": attempts,
|
||||
}
|
||||
)
|
||||
self.log.emit(f"[AI工场] 下载蝦皮原主图 #{self.asset_id}:开始")
|
||||
try:
|
||||
asset = image_studio_images.download_original_asset(
|
||||
self.asset_id,
|
||||
path=self.db_path,
|
||||
config=self.config,
|
||||
)
|
||||
except Exception:
|
||||
retry = attempt
|
||||
if attempt >= attempts:
|
||||
self.progress.emit(
|
||||
{
|
||||
"asset_id": self.asset_id,
|
||||
"state": "failed",
|
||||
"attempt": attempt,
|
||||
"attempts": attempts,
|
||||
}
|
||||
)
|
||||
self.log.emit(f"[AI工场] 下载蝦皮原主图 #{self.asset_id}:最终失败")
|
||||
return {
|
||||
"ok": False,
|
||||
"asset_id": self.asset_id,
|
||||
"open_after": self.open_after,
|
||||
"error": "蝦皮原主图下载失败,请稍后再次点击图片重试。",
|
||||
}
|
||||
delay = self._retry_delay(retry)
|
||||
self.progress.emit(
|
||||
{
|
||||
"asset_id": self.asset_id,
|
||||
"state": "retry",
|
||||
"retry": retry,
|
||||
"max_retries": self.max_retries,
|
||||
"delay_seconds": delay,
|
||||
}
|
||||
)
|
||||
self.log.emit(
|
||||
f"[AI工场] 下载蝦皮原主图 #{self.asset_id}:失败,准备重试 {retry}/{self.max_retries}"
|
||||
)
|
||||
if not self._wait_for_retry(delay):
|
||||
return {"asset_id": self.asset_id, "cancelled": True}
|
||||
continue
|
||||
self.progress.emit(
|
||||
{
|
||||
"asset_id": self.asset_id,
|
||||
"state": "success",
|
||||
"attempt": attempt,
|
||||
"attempts": attempts,
|
||||
}
|
||||
)
|
||||
self.log.emit(f"[AI工场] 下载蝦皮原主图 #{self.asset_id}:成功")
|
||||
return {"asset": asset, "asset_id": self.asset_id, "open_after": self.open_after}
|
||||
return {"asset_id": self.asset_id, "cancelled": True}
|
||||
|
||||
def _retry_delay(self, retry):
|
||||
if retry <= 0:
|
||||
return 0.0
|
||||
index = min(retry - 1, len(self.retry_delays) - 1)
|
||||
return self.retry_delays[index] if index >= 0 else 0.0
|
||||
|
||||
def _wait_for_retry(self, delay_seconds):
|
||||
deadline = time.monotonic() + max(0.0, float(delay_seconds or 0))
|
||||
while time.monotonic() < deadline:
|
||||
if self.should_cancel():
|
||||
return False
|
||||
time.sleep(min(0.1, max(0.0, deadline - time.monotonic())))
|
||||
return not self.should_cancel()
|
||||
|
||||
|
||||
class ImageStudioGenerateJobsWorker(BaseWorker):
|
||||
|
||||
Reference in New Issue
Block a user