feat(product-suite): complete multi-source recovery

This commit is contained in:
chengma
2026-07-20 18:50:08 +08:00
parent 2e6b93d7e0
commit b803a2a15a
7 changed files with 310 additions and 17 deletions
+159
View File
@@ -181,6 +181,21 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
path=config["db_path"],
)
image_studio.set_job_submitted(job.id, "cmhub-task-1", path=config["db_path"])
direct_job = image_studio.create_job(
project.id,
source_asset_id=assets[0].id,
job_type="场景图",
prompt="直连失败图片",
generation_source=image_studio.GENERATION_SOURCE_DIRECT,
provider=image_studio.PROVIDER_OPENAI_IMAGES_EDITS,
path=config["db_path"],
)
image_studio.update_job_status(
direct_job.id,
"failed",
error="程序中断,无法确认生成结果,请手动重新生成",
path=config["db_path"],
)
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
self.addCleanup(tab.close)
@@ -196,6 +211,10 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
self.assertFalse(tab.ai_write_button.isEnabled())
self.assertFalse(tab.resume_submitted_button.isHidden())
self.assertTrue(tab.resume_submitted_button.isEnabled())
self.assertEqual(
[job.id],
[resumable.id for resumable in tab._resumable_default_gateway_jobs(state)],
)
self.assertIn("不计点数", tab.generate_button.toolTip())
self.assert_removed(temp_dir)
@@ -287,6 +306,146 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
self.assert_removed(temp_dir)
def test_direct_failed_job_retry_requires_repeat_billing_confirmation(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)
project, assets = self._create_project_with_assets(temp_dir, config, 1)
self._configure_direct_image_gateway(config)
failed_job = image_studio.create_job(
project.id,
source_asset_id=assets[0].id,
job_type="白底图",
prompt="重新生成测试",
generation_source=image_studio.GENERATION_SOURCE_DIRECT,
provider=image_studio.PROVIDER_OPENAI_IMAGES_EDITS,
path=config["db_path"],
)
failed_job = image_studio.update_job_status(
failed_job.id,
"failed",
error="程序中断,无法确认生成结果,请手动重新生成",
path=config["db_path"],
)
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
self.addCleanup(tab.close)
state = tab._displayed_state
state.account_alias = "alias-a"
state.item_id = project.item_id
state.project_id = project.id
state.project_binding_state = project.binding_state
tab._load_state(state)
confirmations = []
tab._confirm = lambda title, message, **kwargs: confirmations.append(
(title, message, kwargs)
) and False
with mock.patch.object(tab, "_start_generation_worker") as start_worker:
tab.retry_job(failed_job)
self.assertEqual(1, len(confirmations))
self.assertEqual("确认重新生成商品套图", confirmations[0][0])
self.assertIn("可能对上次未确认请求已计费", confirmations[0][1])
self.assertIn("本次重新生成可能再次收费", confirmations[0][1])
self.assertIn("生成来源:自定义网关", confirmations[0][1])
self.assertTrue(confirmations[0][2]["default_cancel"])
start_worker.assert_not_called()
tab._confirm = lambda *args, **kwargs: True
with mock.patch.object(tab, "_start_generation_worker", return_value=True) as start_worker:
tab.retry_job(failed_job)
self.assertTrue(start_worker.called)
self.assertTrue(start_worker.call_args.kwargs["retrying"])
self.assertEqual(failed_job.id, start_worker.call_args.kwargs["retry_job_id"])
self.assert_removed(temp_dir)
def test_generation_source_labels_are_persisted_for_results_and_history(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)
project, assets = self._create_project_with_assets(temp_dir, config, 1)
cmhub_job = image_studio.create_job(
project.id,
source_asset_id=assets[0].id,
job_type="白底图",
prompt="默认网关图片",
generation_source=image_studio.GENERATION_SOURCE_CMHUB,
provider=image_studio.PROVIDER_CMHUB,
path=config["db_path"],
)
cmhub_job = image_studio.update_job_status(
cmhub_job.id,
"failed",
error="默认网关失败",
path=config["db_path"],
)
direct_job = image_studio.create_job(
project.id,
source_asset_id=assets[0].id,
job_type="场景图",
prompt="自定义网关图片",
generation_source=image_studio.GENERATION_SOURCE_DIRECT,
provider=image_studio.PROVIDER_OPENAI_IMAGES_EDITS,
path=config["db_path"],
)
direct_job = image_studio.update_job_status(
direct_job.id,
"failed",
error="程序中断,无法确认生成结果,请手动重新生成",
path=config["db_path"],
)
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
self.addCleanup(tab.close)
state = tab._displayed_state
state.account_alias = "alias-a"
state.item_id = project.item_id
state.project_id = project.id
state.project_binding_state = project.binding_state
state.current_job_ids = [cmhub_job.id, direct_job.id]
tab._load_state(state)
tab._refresh_results(state)
result_sources = {
card.job.id: card.findChild(QLabel, "suiteResultCardSource").text()
for card in tab.findChildren(SuiteResultCard)
}
self.assertEqual("默认网关", result_sources[cmhub_job.id])
self.assertEqual("自定义网关", result_sources[direct_job.id])
self._configure_direct_image_gateway(config)
tab.refresh_gateway_state()
result_sources_after_switch = {
card.job.id: card.findChild(QLabel, "suiteResultCardSource").text()
for card in tab.findChildren(SuiteResultCard)
}
self.assertEqual(result_sources, result_sources_after_switch)
history = ProductSuiteHistoryDialog(project.id, db_path=config["db_path"], parent=tab)
self.addCleanup(history.close)
self.assertTrue(
any(
label.text() == "来源:默认网关、自定义网关"
for label in history.findChildren(QLabel, "suiteHistoryRoundSource")
)
)
history_cards = {
card.job.id: card.toolTip()
for card in history.findChildren(SuiteHistoryImageCard)
}
self.assertIn("生成来源:默认网关", history_cards[cmhub_job.id])
self.assertIn("生成来源:自定义网关", history_cards[direct_job.id])
global_history = ProductSuiteGlobalHistoryDialog(db_path=config["db_path"], parent=tab)
self.addCleanup(global_history.close)
self.assertTrue(
any(
label.text() == "来源:默认网关、自定义网关"
for label in global_history.findChildren(QLabel, "suiteGlobalHistorySource")
)
)
self.assert_removed(temp_dir)
def test_tab_builds_suite_controls_without_old_detail_workspace(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)