nacho commited on
Commit
f249601
·
1 Parent(s): f7df793

refactor: prelogin retry loop — 8 concurrent, 3min retry, infinite until all online

Browse files
Files changed (1) hide show
  1. main.py +51 -38
main.py CHANGED
@@ -381,24 +381,8 @@ async def import_accounts(request: Request, admin_key: str = Header(...)):
381
  _save_settings(saved)
382
 
383
  # 异步触发新导入账号的并行预登录
384
- async def prelogin_new_accounts():
385
- sem = asyncio.Semaphore(10) # 最多同时 10 个登录,避免浏览器启动过载
386
- async def _login_one(account):
387
- async with sem:
388
- try:
389
- logger.info("Pre-logging in newly imported account %s...", account.email)
390
- await manager.get_or_create_browser_with_retry(
391
- account, headless=config.browser.headless
392
- )
393
- logger.info("Pre-login OK: %s", account.email)
394
- except Exception as e:
395
- logger.error("Pre-login FAILED for %s: %s", account.email, e)
396
- tasks = [_login_one(a) for a in new_accounts]
397
- if tasks:
398
- await asyncio.gather(*tasks, return_exceptions=True)
399
-
400
  if new_accounts:
401
- asyncio.create_task(prelogin_new_accounts())
402
 
403
  return {"success": True, "imported": imported, "total": len(manager.accounts)}
404
 
@@ -724,29 +708,58 @@ async def startup():
724
  asyncio.create_task(_prelogin_all())
725
 
726
 
727
- async def _prelogin_all():
728
- """并行登录全部账号,信号量控制并发避免打崩服务器"""
729
- sem = asyncio.Semaphore(10) # 最多同时 10 个登录,避免浏览器启动过载
 
 
 
 
730
  total = len(manager.accounts)
731
- done = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
732
 
733
- async def _login_one(email: str, account):
734
- nonlocal done
735
- async with sem:
736
- try:
737
- logger.info("[prelogin %d/%d] %s ...", done + 1, total, email)
738
- await manager.get_or_create_browser_with_retry(
739
- account, headless=config.browser.headless
740
- )
741
- logger.info("[prelogin OK %d/%d] %s (muted=%s)", done + 1, total, email, account.is_muted)
742
- except Exception as e:
743
- logger.error("[prelogin FAIL %d/%d] %s: %s", done + 1, total, email, e)
744
- done += 1
745
-
746
- tasks = [_login_one(email, acc) for email, acc in manager.accounts.items()]
747
- if tasks:
748
- await asyncio.gather(*tasks, return_exceptions=True)
749
- logger.info("Pre-login complete: %d/%d accounts ready", sum(1 for a in manager.accounts.values() if a.logged_in), total)
 
 
 
750
 
751
 
752
  def main():
 
381
  _save_settings(saved)
382
 
383
  # 异步触发新导入账号的并行预登录
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
384
  if new_accounts:
385
+ asyncio.create_task(_prelogin_loop(sem_size=8, retry_delay=180))
386
 
387
  return {"success": True, "imported": imported, "total": len(manager.accounts)}
388
 
 
708
  asyncio.create_task(_prelogin_all())
709
 
710
 
711
+ async def _prelogin_loop(sem_size=8, retry_delay=180):
712
+ """通用预登录循环:并行登录一批账号,失败的在 delay 秒后重试,直到全部成功或错误过多
713
+
714
+ 参数:
715
+ sem_size: 最大同时登录数(默认 8)
716
+ retry_delay: 失败后重试等待秒数(默认 180 = 3 分钟)
717
+ """
718
  total = len(manager.accounts)
719
+ while True:
720
+ pending = [
721
+ (email, acc) for email, acc in manager.accounts.items()
722
+ if not acc.logged_in and acc.error_count < 5
723
+ ]
724
+ if not pending:
725
+ logger.info("[prelogin] All accounts ready or max retries exhausted")
726
+ return
727
+
728
+ logger.info("[prelogin] %d/%d accounts pending, starting batch (concurrency=%d)...",
729
+ len(pending), total, sem_size)
730
+ sem = asyncio.Semaphore(sem_size)
731
+
732
+ async def _login_one(email, account):
733
+ async with sem:
734
+ try:
735
+ logger.info("[prelogin] %s ...", email)
736
+ await manager.get_or_create_browser_with_retry(
737
+ account, headless=config.browser.headless
738
+ )
739
+ logger.info("[prelogin OK] %s (muted=%s)", email, account.is_muted)
740
+ except Exception as e:
741
+ logger.error("[prelogin FAIL] %s: %s", email, e)
742
 
743
+ tasks = [_login_one(email, acc) for email, acc in pending]
744
+ if tasks:
745
+ await asyncio.gather(*tasks, return_exceptions=True)
746
+
747
+ still_pending = sum(
748
+ 1 for a in manager.accounts.values()
749
+ if not a.logged_in and a.error_count < 5
750
+ )
751
+ if still_pending == 0:
752
+ logger.info("[prelogin] All done")
753
+ return
754
+
755
+ logger.info("[prelogin] %d accounts still pending, retrying in %ds...",
756
+ still_pending, retry_delay)
757
+ await asyncio.sleep(retry_delay)
758
+
759
+
760
+ async def _prelogin_all():
761
+ """启动时后台预登录:同时 8 个,失败 3 分钟后重试,无限循环直到全部在线。"""
762
+ await _prelogin_loop(sem_size=8, retry_delay=180)
763
 
764
 
765
  def main():