账号
This commit is contained in:
@@ -91,6 +91,9 @@ class SiteInteractor:
|
||||
self._browser = None
|
||||
self._context = None # playwright BrowserContext
|
||||
self._per_task_state = {}
|
||||
# 上次 build context 时读到的 storage_state 文件 mtime。
|
||||
# 用于在任务间检测 AuthSession 重登后产生的新 storage_state,触发 context 重建。
|
||||
self._state_mtime: float | None = None
|
||||
|
||||
# ---- 生命周期 ----
|
||||
|
||||
@@ -109,6 +112,8 @@ class SiteInteractor:
|
||||
"登录态文件不存在:site_interactor 以无 cookie 状态启动,"
|
||||
"加购请求会被站点拒认"
|
||||
)
|
||||
else:
|
||||
self._state_mtime = state_path.stat().st_mtime
|
||||
|
||||
self._playwright = await async_playwright().start()
|
||||
self._browser = await self._playwright.chromium.launch(
|
||||
@@ -127,6 +132,41 @@ class SiteInteractor:
|
||||
)
|
||||
logger.info("SiteInteractor 已就绪:storage_state=%s", storage_state or "(none)")
|
||||
|
||||
async def _refresh_context_if_stale(self) -> None:
|
||||
"""检查 storage_state 文件 mtime,变化则重建 context
|
||||
|
||||
AuthSession.try_relogin 成功后会重写 storage_state 文件。本 context 启动时
|
||||
用快照式 storage_state 创建,cookie 不会自动同步——必须关掉旧 context、
|
||||
用新文件重建。在 add_to_cart / verify_cart 开头各调一次,开销可接受
|
||||
(只在 mtime 变了才重建)。
|
||||
"""
|
||||
state_path = self._settings.auth_state_path / auth_site.profile("rakuten").state_filename
|
||||
if not state_path.exists():
|
||||
return
|
||||
mtime = state_path.stat().st_mtime
|
||||
if mtime == self._state_mtime:
|
||||
return
|
||||
|
||||
logger.info(
|
||||
"storage_state 文件变化(mtime %s → %s),重建 context",
|
||||
self._state_mtime, mtime,
|
||||
)
|
||||
if self._context is not None:
|
||||
try:
|
||||
await self._context.close()
|
||||
except Exception:
|
||||
logger.debug("关闭旧 context 失败", exc_info=True)
|
||||
self._context = await self._browser.new_context(
|
||||
storage_state=str(state_path),
|
||||
user_agent=auth_site.RAKUTEN_USER_AGENT,
|
||||
locale="ja-JP",
|
||||
timezone_id="Asia/Tokyo",
|
||||
viewport={"width": 390, "height": 844},
|
||||
is_mobile=True,
|
||||
has_touch=True,
|
||||
)
|
||||
self._state_mtime = mtime
|
||||
|
||||
async def close(self) -> None:
|
||||
"""关闭 context、browser、playwright,吞掉单个 close 异常"""
|
||||
for resource, name in (
|
||||
@@ -171,6 +211,9 @@ class SiteInteractor:
|
||||
|
||||
await self._auth_session.require_logged_in("rakuten")
|
||||
|
||||
# 任务开始前刷新 context:AuthSession 可能刚自动重登过,storage_state 变了
|
||||
await self._refresh_context_if_stale()
|
||||
|
||||
page = await self._context.new_page()
|
||||
try:
|
||||
try:
|
||||
@@ -261,6 +304,9 @@ class SiteInteractor:
|
||||
"""
|
||||
await self._auth_session.require_logged_in("rakuten")
|
||||
|
||||
# 同 add_to_cart:刷新 context 以反映可能的自动重登结果
|
||||
await self._refresh_context_if_stale()
|
||||
|
||||
per_task = self._per_task_state.get(task.task_id, {})
|
||||
item_id = (task.intent or {}).get("item_id") or per_task.get("item_id")
|
||||
if not item_id:
|
||||
|
||||
Reference in New Issue
Block a user