Skip to content

Commit 91ab132

Browse files
committed
perf: 优化延迟、优化冗余代码
1 parent 47d9131 commit 91ab132

File tree

6 files changed

+86
-54
lines changed

6 files changed

+86
-54
lines changed

src/browser/operations.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,44 @@
44
import os
55
import re
66
import logging
7-
from typing import Optional, Any, List, Dict, Callable, Set
7+
import functools
8+
from typing import Optional, Any, List, Dict, Callable, Set, TypeVar
89
from playwright.async_api import Page as AsyncPage, Locator, Error as PlaywrightAsyncError
910
from config import *
1011
from models import ClientDisconnectedError, ElementClickError
1112
logger = logging.getLogger('AIStudioProxyServer')
1213

14+
T = TypeVar('T')
15+
16+
def check_disconnect(check_client_disconnected: Callable, stage: str, req_id: str):
17+
if check_client_disconnected and check_client_disconnected(stage):
18+
raise ClientDisconnectedError(f'[{req_id}] Client disconnected at stage: {stage}')
19+
20+
async def retry_async(
21+
func: Callable,
22+
max_retries: int = 3,
23+
delay: float = 0.15,
24+
req_id: str = 'unknown',
25+
operation_name: str = 'operation',
26+
check_client_disconnected: Callable = None
27+
) -> Any:
28+
last_error = None
29+
for attempt in range(1, max_retries + 1):
30+
try:
31+
if check_client_disconnected:
32+
check_disconnect(check_client_disconnected, f'{operation_name} - 尝试 {attempt}', req_id)
33+
return await func()
34+
except ClientDisconnectedError:
35+
raise
36+
except Exception as e:
37+
last_error = e
38+
if attempt < max_retries:
39+
logger.warning(f'[{req_id}] {operation_name} 失败 (尝试 {attempt}): {e}')
40+
await asyncio.sleep(delay)
41+
logger.error(f'[{req_id}] {operation_name} 最终失败,已重试 {max_retries} 次')
42+
raise last_error if last_error else Exception(f'{operation_name} failed')
43+
44+
1345
async def get_model_name_from_page_parallel(page: AsyncPage, selectors: list, timeout: int = 2000, req_id: str = 'unknown', expected_model_name: str = None) -> Optional[str]:
1446
if not selectors:
1547
return None

src/browser/page_controller.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,9 +795,9 @@ async def _upload_images_via_file_input(self, images: List[Dict[str, str]], chec
795795
await file_input.set_input_files(tf.name)
796796
uploaded_count += 1
797797

798-
await asyncio.sleep(0.8)
798+
await asyncio.sleep(0.2)
799799
await self.page.keyboard.press('Escape')
800-
await asyncio.sleep(0.3)
800+
await asyncio.sleep(0.1)
801801

802802
asyncio.create_task(self._cleanup_temp_files(temp_files))
803803

src/media/imagen_controller.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@ async def set_number_of_images(self, count: int, check_client_disconnected: Call
5959
self.logger.warning(f'[{self.req_id}] 未找到数量输入框')
6060
return
6161
await input_locator.fill(str(count))
62-
await asyncio.sleep(0.2)
62+
await asyncio.sleep(0.1)
6363
self.logger.info(f'[{self.req_id}] ✅ 图片数量已设置: {count}')
6464
return
6565
except Exception as e:
6666
if isinstance(e, ClientDisconnectedError):
6767
raise
6868
self.logger.warning(f'[{self.req_id}] 设置数量失败 (尝试 {attempt}): {e}')
6969
if attempt < max_retries:
70-
await asyncio.sleep(0.3)
70+
await asyncio.sleep(0.15)
7171

7272
async def set_aspect_ratio(self, aspect_ratio: str, check_client_disconnected: Callable):
7373
self.logger.info(f'[{self.req_id}] 设置宽高比: {aspect_ratio}')
@@ -87,7 +87,7 @@ async def set_aspect_ratio(self, aspect_ratio: str, check_client_disconnected: C
8787
raise
8888
self.logger.warning(f'[{self.req_id}] 设置宽高比失败 (尝试 {attempt}): {e}')
8989
if attempt < max_retries:
90-
await asyncio.sleep(0.3)
90+
await asyncio.sleep(0.15)
9191

9292
async def set_negative_prompt(self, negative_prompt: str, check_client_disconnected: Callable):
9393
if not negative_prompt:
@@ -101,35 +101,35 @@ async def set_negative_prompt(self, negative_prompt: str, check_client_disconnec
101101
self.logger.warning(f'[{self.req_id}] 未找到负面提示词输入框')
102102
return
103103
await textarea.fill(negative_prompt)
104-
await asyncio.sleep(0.2)
104+
await asyncio.sleep(0.1)
105105
self.logger.info(f'[{self.req_id}] ✅ 负面提示词已设置')
106106
return
107107
except Exception as e:
108108
if isinstance(e, ClientDisconnectedError):
109109
raise
110110
self.logger.warning(f'[{self.req_id}] 设置负面提示词失败 (尝试 {attempt}): {e}')
111111
if attempt < max_retries:
112-
await asyncio.sleep(0.3)
112+
await asyncio.sleep(0.15)
113113

114114
async def fill_prompt(self, prompt: str, check_client_disconnected: Callable):
115115
self.logger.info(f'[{self.req_id}] 填充提示词 ({len(prompt)} chars)')
116116
max_retries = 3
117117
for attempt in range(1, max_retries + 1):
118118
try:
119119
await self.page.keyboard.press('Escape')
120-
await asyncio.sleep(0.3)
120+
await asyncio.sleep(0.15)
121121
text_input = self.page.locator(IMAGEN_PROMPT_INPUT_SELECTOR)
122122
await safe_click(text_input, '输入框', self.req_id)
123123
await text_input.fill(prompt)
124-
await asyncio.sleep(0.2)
124+
await asyncio.sleep(0.1)
125125
self.logger.info(f'[{self.req_id}] ✅ 提示词已填充')
126126
return
127127
except Exception as e:
128128
if isinstance(e, ClientDisconnectedError):
129129
raise
130130
self.logger.warning(f'[{self.req_id}] 填充提示词失败 (尝试 {attempt}): {e}')
131131
if attempt < max_retries:
132-
await asyncio.sleep(0.3)
132+
await asyncio.sleep(0.15)
133133
raise Exception('填充提示词失败')
134134

135135
async def run_generation(self, check_client_disconnected: Callable):
@@ -138,7 +138,7 @@ async def run_generation(self, check_client_disconnected: Callable):
138138
for attempt in range(1, max_retries + 1):
139139
try:
140140
await self.page.keyboard.press('Escape')
141-
await asyncio.sleep(0.3)
141+
await asyncio.sleep(0.15)
142142
run_btn = self.page.locator(IMAGEN_RUN_BUTTON_SELECTOR)
143143
await expect_async(run_btn).to_be_visible(timeout=5000)
144144
await expect_async(run_btn).to_be_enabled(timeout=5000)
@@ -154,7 +154,7 @@ async def run_generation(self, check_client_disconnected: Callable):
154154
raise
155155
self.logger.warning(f'[{self.req_id}] 点击 Run 失败 (尝试 {attempt}): {e}')
156156
if attempt < max_retries:
157-
await asyncio.sleep(0.3)
157+
await asyncio.sleep(0.15)
158158
raise Exception('点击 Run 按钮失败')
159159

160160
async def wait_for_images(self, expected_count: int, check_client_disconnected: Callable, timeout_seconds: int = 180) -> List[GeneratedImage]:
@@ -191,4 +191,4 @@ async def wait_for_images(self, expected_count: int, check_client_disconnected:
191191
except Exception as e:
192192
self.logger.warning(f'[{self.req_id}] 检查图片时出错: {e}')
193193

194-
await asyncio.sleep(2)
194+
await asyncio.sleep(1)

src/media/nano_controller.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ async def set_aspect_ratio(self, aspect_ratio: str, check_client_disconnected: C
6161
return
6262
if not await safe_click(dropdown, '宽高比下拉框', self.req_id):
6363
continue
64-
await asyncio.sleep(0.3)
64+
await asyncio.sleep(0.15)
6565
option = self.page.locator(f'mat-option:has-text("{aspect_ratio}")')
6666
if await option.count() > 0:
6767
if await safe_click(option.first, f'宽高比选项 {aspect_ratio}', self.req_id):
@@ -76,7 +76,7 @@ async def set_aspect_ratio(self, aspect_ratio: str, check_client_disconnected: C
7676
raise
7777
self.logger.warning(f'[{self.req_id}] 设置宽高比失败 (尝试 {attempt}): {e}')
7878
if attempt < max_retries:
79-
await asyncio.sleep(0.3)
79+
await asyncio.sleep(0.15)
8080
self.logger.warning(f'[{self.req_id}] 宽高比设置失败,使用默认值')
8181

8282
async def upload_image(self, image_bytes: bytes, mime_type: str, check_client_disconnected: Callable):
@@ -92,7 +92,7 @@ async def upload_image(self, image_bytes: bytes, mime_type: str, check_client_di
9292
if attempt < max_retries:
9393
continue
9494
return
95-
await asyncio.sleep(0.5)
95+
await asyncio.sleep(0.25)
9696
await self._check_disconnect(check_client_disconnected, '插入菜单展开后')
9797

9898
ext = 'png' if 'png' in mime_type else 'jpg'
@@ -102,29 +102,29 @@ async def upload_image(self, image_bytes: bytes, mime_type: str, check_client_di
102102
'mimeType': mime_type,
103103
'buffer': image_bytes
104104
})
105-
await asyncio.sleep(1.5)
105+
await asyncio.sleep(0.8)
106106
await self.page.keyboard.press('Escape')
107-
await asyncio.sleep(0.5)
107+
await asyncio.sleep(0.25)
108108
self.logger.info(f'[{self.req_id}] ✅ 图片已上传')
109109
return
110110
except Exception as e:
111111
if isinstance(e, ClientDisconnectedError):
112112
raise
113113
self.logger.warning(f'[{self.req_id}] 上传图片失败 (尝试 {attempt}): {e}')
114114
if attempt < max_retries:
115-
await asyncio.sleep(0.5)
115+
await asyncio.sleep(0.25)
116116

117117
async def fill_prompt(self, prompt: str, check_client_disconnected: Callable):
118118
self.logger.info(f'[{self.req_id}] 填充提示词 ({len(prompt)} chars)')
119119
max_retries = 3
120120
for attempt in range(1, max_retries + 1):
121121
try:
122122
await self.page.keyboard.press('Escape')
123-
await asyncio.sleep(0.3)
123+
await asyncio.sleep(0.15)
124124
text_input = self.page.locator(PROMPT_TEXTAREA_SELECTOR)
125125
await safe_click(text_input, '输入框', self.req_id)
126126
await text_input.fill(prompt)
127-
await asyncio.sleep(0.2)
127+
await asyncio.sleep(0.1)
128128
actual = await text_input.input_value()
129129
if prompt in actual or actual in prompt:
130130
self.logger.info(f'[{self.req_id}] ✅ 提示词已填充')
@@ -135,7 +135,7 @@ async def fill_prompt(self, prompt: str, check_client_disconnected: Callable):
135135
raise
136136
self.logger.warning(f'[{self.req_id}] 填充提示词失败 (尝试 {attempt}): {e}')
137137
if attempt < max_retries:
138-
await asyncio.sleep(0.3)
138+
await asyncio.sleep(0.15)
139139
raise Exception('填充提示词失败')
140140

141141
async def run_generation(self, check_client_disconnected: Callable):
@@ -144,7 +144,7 @@ async def run_generation(self, check_client_disconnected: Callable):
144144
for attempt in range(1, max_retries + 1):
145145
try:
146146
await self.page.keyboard.press('Escape')
147-
await asyncio.sleep(0.3)
147+
await asyncio.sleep(0.15)
148148
run_btn = self.page.locator(SUBMIT_BUTTON_SELECTOR)
149149
await expect_async(run_btn).to_be_visible(timeout=5000)
150150
await expect_async(run_btn).to_be_enabled(timeout=5000)
@@ -160,7 +160,7 @@ async def run_generation(self, check_client_disconnected: Callable):
160160
raise
161161
self.logger.warning(f'[{self.req_id}] 点击 Run 失败 (尝试 {attempt}): {e}')
162162
if attempt < max_retries:
163-
await asyncio.sleep(0.3)
163+
await asyncio.sleep(0.15)
164164
raise Exception('点击 Run 按钮失败')
165165

166166
async def wait_for_content(self, check_client_disconnected: Callable, timeout_seconds: int = 120) -> GeneratedContent:
@@ -229,7 +229,7 @@ async def wait_for_content(self, check_client_disconnected: Callable, timeout_se
229229
except Exception as e:
230230
self.logger.warning(f'[{self.req_id}] 检查内容时出错: {e}')
231231

232-
await asyncio.sleep(0.5)
232+
await asyncio.sleep(0.25)
233233

234234
async def _extract_images_via_download(self, count: int) -> List[GeneratedImage]:
235235
import tempfile
@@ -244,9 +244,9 @@ async def _extract_images_via_download(self, count: int) -> List[GeneratedImage]
244244
img = chunk.locator('img')
245245
if await img.count() > 0:
246246
await img.first.hover()
247-
await asyncio.sleep(0.5)
247+
await asyncio.sleep(0.25)
248248
await chunk.evaluate('el => el.dispatchEvent(new MouseEvent("mouseenter", {bubbles: true}))')
249-
await asyncio.sleep(0.3)
249+
await asyncio.sleep(0.15)
250250

251251
download_btn = chunk.locator('button[aria-label="Download"]')
252252
if await download_btn.count() == 0:

0 commit comments

Comments
 (0)