更新
This commit is contained in:
@@ -495,6 +495,22 @@ async def _conversations_from_logs(
|
||||
return list(seen.values())
|
||||
|
||||
|
||||
async def _release_db_connection(db: AsyncSession) -> None:
|
||||
"""Check this session's pooled connection back in before a long await.
|
||||
|
||||
The whole backend shares a handful of pooled connections (five by default
|
||||
on SQLite). A session left open across credential validation or worker
|
||||
initialization holds one of them for tens of seconds per account, so every
|
||||
unrelated request then waits out ``pool_timeout`` and the panel looks
|
||||
frozen during a bulk start. Committing ends the transaction and returns
|
||||
the connection; ``expire_on_commit=False`` keeps loaded attributes usable.
|
||||
"""
|
||||
try:
|
||||
await db.commit()
|
||||
except Exception:
|
||||
logger.debug("Releasing the database connection failed", exc_info=True)
|
||||
|
||||
|
||||
async def _reset_account_credentials(account_id: int, db: AsyncSession) -> Account:
|
||||
"""清除账号 Cookie、IM 会话等登录数据,并停止托管。"""
|
||||
await manager.stop_worker(account_id)
|
||||
@@ -1931,6 +1947,7 @@ async def update_account_cookie(
|
||||
# are committed so no worker can start in the stop/commit gap.
|
||||
async with manager.preparation_lock(account_id):
|
||||
account = await get_owned_account(db, user, account_id, write=True)
|
||||
await _release_db_connection(db)
|
||||
await batch_start_queue.cancel_account(account_id)
|
||||
await manager.stop_worker(account_id)
|
||||
|
||||
@@ -1970,6 +1987,7 @@ async def delete_account_cookie(
|
||||
# before the cleared credentials are committed.
|
||||
async with manager.preparation_lock(account_id):
|
||||
account = await get_owned_account(db, user, account_id, write=True)
|
||||
await _release_db_connection(db)
|
||||
await batch_start_queue.cancel_account(account_id)
|
||||
await manager.stop_worker(account_id)
|
||||
|
||||
@@ -2033,6 +2051,7 @@ async def delete_account(
|
||||
):
|
||||
await get_owned_account(db, user, account_id, write=True)
|
||||
# 停止运行中的任务
|
||||
await _release_db_connection(db)
|
||||
await batch_start_queue.cancel_account(account_id)
|
||||
await manager.stop_worker(account_id)
|
||||
clear_cookie_file(account_id)
|
||||
@@ -2066,6 +2085,7 @@ async def reset_account_credentials(
|
||||
user: User = Depends(require_write),
|
||||
):
|
||||
await get_owned_account(db, user, account_id, write=True)
|
||||
await _release_db_connection(db)
|
||||
await batch_start_queue.cancel_account(account_id)
|
||||
account = await _reset_account_credentials(account_id, db)
|
||||
return {
|
||||
@@ -2087,6 +2107,9 @@ async def _start_account_rpa_impl(
|
||||
return {"status": "running", "message": "RPA worker is already running."}
|
||||
|
||||
cookie_data = _get_account_cookie_data(account)
|
||||
# Credential assessment issues real network requests to Douyin, and a bulk
|
||||
# start runs it for every queued account. Release the connection first.
|
||||
await _release_db_connection(db)
|
||||
assessment = await assess_account_credential(
|
||||
cookie_data,
|
||||
account.im_session_data,
|
||||
@@ -2136,6 +2159,10 @@ async def _start_account_rpa_impl(
|
||||
account.qr_code_base64 = None
|
||||
account.error_message = None
|
||||
await db.commit()
|
||||
else:
|
||||
# Nothing to persist, but the reads above may still hold a pooled
|
||||
# connection, and waiting for readiness below takes seconds.
|
||||
await _release_db_connection(db)
|
||||
|
||||
try:
|
||||
started = await manager.start_worker(
|
||||
@@ -2213,6 +2240,10 @@ async def start_account_rpa(
|
||||
user: User = Depends(require_write),
|
||||
):
|
||||
account = await get_owned_account(db, user, account_id, write=True)
|
||||
# Cancelling waits for an in-flight queued start, and the preparation lock
|
||||
# waits for whichever start owns this account. Neither may keep a pooled
|
||||
# connection checked out while it waits.
|
||||
await _release_db_connection(db)
|
||||
await batch_start_queue.cancel_account(account_id)
|
||||
async with manager.preparation_lock(account_id):
|
||||
return await _start_account_rpa_impl(account, db, body.login_mode)
|
||||
@@ -2290,6 +2321,9 @@ async def stop_account_rpa(
|
||||
):
|
||||
account = await get_owned_account(db, user, account_id, write=True)
|
||||
|
||||
# Cancelling drains an in-flight queued start, which can take as long as
|
||||
# the batch per-account deadline. Do not hold a pooled connection for it.
|
||||
await _release_db_connection(db)
|
||||
await batch_start_queue.cancel_account(account_id)
|
||||
stopped = await manager.stop_worker(account_id)
|
||||
# 强制将数据库中的状态重置为 offline
|
||||
|
||||
Reference in New Issue
Block a user