fix(ai-studio): keep worker thread alive until finished

This commit is contained in:
chengma
2026-07-11 15:13:09 +08:00
parent 2dd90580ea
commit 150d6ce22d
3 changed files with 145 additions and 21 deletions
+96
View File
@@ -702,6 +702,102 @@ class GuiTests(TempDirMixin, unittest.TestCase):
self.assert_removed(temp_dir)
def test_image_studio_worker_thread_is_kept_until_thread_finished(self):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_dir)
tab = ImageStudioTab(config=cfg, db_path=cfg["db_path"])
self.addCleanup(tab.close)
worker = SimpleNamespace()
fake_thread = FakeThread()
with mock.patch("app.gui.tabs.image_studio.run_worker", return_value=fake_thread) as run_worker:
tab._start_worker(worker, "AI工场测试线程")
run_worker.assert_called_once_with(worker, thread_name="AI工场测试线程", start=False)
self.assertIs(tab._running_worker, worker)
self.assertIs(tab._running_thread, fake_thread)
self.assertTrue(fake_thread.started)
self.assertFalse(tab.pull_images_button.isEnabled())
tab._finish_worker()
self.assertIs(tab._running_worker, worker)
self.assertIs(tab._running_thread, fake_thread)
self.assertTrue(tab.pull_images_button.isEnabled())
fake_thread.finished.emit()
self.assertIsNone(tab._running_worker)
self.assertIsNone(tab._running_thread)
self.assert_removed(temp_dir)
def test_image_studio_worker_failure_is_handled_once(self):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_dir)
tab = ImageStudioTab(config=cfg, db_path=cfg["db_path"])
self.addCleanup(tab.close)
messages = []
tab._message = lambda title, text: messages.append((title, text))
worker = SimpleNamespace()
fake_thread = FakeThread()
with mock.patch("app.gui.tabs.image_studio.run_worker", return_value=fake_thread):
tab._start_worker(worker, "AI工场测试线程")
tab._on_worker_failed(-1, "第一次失败")
tab._on_pull_finished({"ok": False, "error": "第二次失败"})
self.assertEqual([("AI工场任务失败", "第一次失败")], messages)
log_text = tab.log_view.toPlainText()
self.assertEqual(1, log_text.count("[AI工场] 失败"))
self.assertIn("第一次失败", log_text)
self.assertNotIn("第二次失败", log_text)
self.assert_removed(temp_dir)
def test_image_studio_pull_main_images_uses_current_item_input(self):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_dir)
accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg)
old_project = image_studio.create_or_get_project(
account_alias="alias-a",
account_slug="alias_a",
item_id="11111111111",
path=cfg["db_path"],
)
tab = ImageStudioTab(config=cfg, db_path=cfg["db_path"])
self.addCleanup(tab.close)
tab._select_project(old_project.id)
tab.item_id_edit.setText("22222222222")
class FakePullWorker:
instances = []
def __init__(self, account_alias, item_id, *, db_path=None, config=None):
self.account_alias = account_alias
self.item_id = item_id
self.db_path = db_path
self.config = config
self.log = DummySignal()
self.finished = DummySignal()
self.failed = DummySignal()
FakePullWorker.instances.append(self)
fake_thread = FakeThread()
with mock.patch(
"app.gui.tabs.image_studio.ImageStudioPullImagesWorker",
FakePullWorker,
), mock.patch("app.gui.tabs.image_studio.run_worker", return_value=fake_thread):
tab.pull_main_images()
self.assertEqual(1, len(FakePullWorker.instances))
worker = FakePullWorker.instances[0]
self.assertEqual("alias-a", worker.account_alias)
self.assertEqual("22222222222", worker.item_id)
self.assertEqual("11111111111", old_project.item_id)
self.assertTrue(fake_thread.started)
self.assert_removed(temp_dir)
def test_image_studio_event_log_hides_provider_urls(self):
message = gui_workers._format_image_studio_event(
{