Improve abnormal account cleanup

This commit is contained in:
SmartUp Developer
2026-07-06 13:48:41 +08:00
parent c26bdb766c
commit a62ee00115
6 changed files with 255 additions and 70 deletions
+101 -17
View File
@@ -239,50 +239,44 @@ def test_cleanup_invalid_preview_and_execute(db_session, monkeypatch):
assert item_k1.test_status == "failed"
item_k2 = next(i for i in items if i.account_id == "acc-k2")
assert item_k2.cleanup_allowed is False
assert item_k2.cleanup_allowed is True
assert item_k2.test_status == "test_passed"
assert item_k2.cleanup_action == "delete_remote_and_clear_marker"
item_orphan = next(i for i in items if i.account_id == "acc-orphan-remote")
assert item_orphan.cleanup_allowed is True
assert item_orphan.test_status == "failed"
assert item_orphan.upstream_key_id == 9999
assert item_orphan.cleanup_action == "delete_remote_account"
# 确认没有调用过删除
assert len(deleted_accounts) == 0
# ── 2. 测试执行 ──
# 重置调用计数
test_calls.clear()
execute_res = execute_cleanup_invalid_accounts(wid=w.id, db=db_session)
assert execute_res.success is True
assert "成功清理 2" in execute_res.message
assert "跳过 1 个" in execute_res.message
assert "成功清理 3" in execute_res.message
# 验证是否重新跑了测试
assert "acc-k1" in test_calls
assert "acc-k2" in test_calls
assert "acc-orphan-remote" in test_calls
# 验证被删除的账号 (只有测试失败/可清理的才删:acc-k1 和 acc-orphan-remote)
assert len(deleted_accounts) == 2
# 验证被删除的账号(所有候选都按 cleanup_action 执行删除)
assert len(deleted_accounts) == 3
assert "acc-k1" in deleted_accounts
assert "acc-k2" in deleted_accounts
assert "acc-orphan-remote" in deleted_accounts
assert "acc-k2" not in deleted_accounts
# 验证本地数据库的 DB key 清空逻辑:
db_session.refresh(k1)
db_session.refresh(k2)
db_session.refresh(k3)
# k1 应该被清空 imported 字段,但保留 status='orphaned' 及原始 error
# k1 应该被清空 imported 字段delete_remote_and_clear_marker,但保留 status='orphaned' 及原始 error
assert k1.imported_website_id is None
assert k1.imported_account_id is None
assert k1.status == "orphaned"
assert k1.error == "original-error-k1"
# k2 由于测试成功跳过删除,DB 不变
assert k2.imported_website_id == w.id
assert k2.imported_account_id == "acc-k2"
# k2 也是 delete_remote_and_clear_marker,删除成功后清空导入标记
assert k2.imported_website_id is None
assert k2.imported_account_id is None
assert k2.status == "orphaned"
@@ -317,3 +311,93 @@ def test_cleanup_list_accounts_failure(db_session, monkeypatch):
assert execute_res.success is False
assert "拉取远端账号列表失败" in execute_res.message
assert len(execute_res.items) == 0
def test_cleanup_missing_remote_account_clear_local_marker(db_session, monkeypatch):
"""status=imported 且本地有 imported_account_id,但远端账号列表已不存在该账号
→ 走 clear_local_marker,不调用 delete_account,只清 SmartUp 本地导入标记。
"""
w = Website(
name="W-clear",
site_type="sub2api",
base_url="http://w-clear",
enabled=True,
auth_config_json="{}",
timeout_seconds=30
)
u = Upstream(name="U-clear", base_url="http://u-clear")
db_session.add_all([w, u])
db_session.commit()
db_session.refresh(w)
db_session.refresh(u)
# 正常 imported 的 Key,关联到远端账号 acc-gone
k = UpstreamGeneratedKey(
upstream_id=u.id,
group_id="G-clear",
group_name="G-Clear-Name",
key_name="Key-Clear",
key_value="sk-clear",
status="imported",
imported_website_id=w.id,
imported_account_id="acc-gone",
imported_target_group_id="tg-1",
imported_target_group_name="Target Group 1",
)
db_session.add(k)
db_session.commit()
deleted_accounts: list[str] = []
class MockClient:
def __init__(self, **kwargs): pass
def __enter__(self): return self
def __exit__(self, *a): pass
def list_accounts(self):
# 远端列表中不包含 acc-gone
return [
{"id": "acc-other", "name": "Other-Acc", "notes": ""},
]
def extract_id(self, val):
return val.get("id") if isinstance(val, dict) else str(val)
def delete_account(self, account_id: str):
deleted_accounts.append(account_id)
return {"status": "deleted", "message": "deleted"}
def test_account(self, account_id: str):
return {"status": "404", "cleanup_allowed": True, "message": "not found"}
monkeypatch.setattr("app.routers.websites._client", lambda row: MockClient())
# ── Preview ──
preview_res = preview_cleanup_invalid_accounts(wid=w.id, db=db_session)
assert preview_res.success is True
assert len(preview_res.items) == 1
item = preview_res.items[0]
assert item.account_id == "acc-gone"
assert item.cleanup_action == "clear_local_marker"
assert item.cleanup_allowed is True
assert item.test_status == "not_needed"
assert item.reason == "目标账号已被手动删除"
# ── Execute ──
execute_res = execute_cleanup_invalid_accounts(wid=w.id, db=db_session)
assert execute_res.success is True
assert "清除本地标记 1 个" in execute_res.message
# 不应调用删除
assert len(deleted_accounts) == 0
# 本地导入标记应被清空
db_session.refresh(k)
assert k.imported_website_id is None
assert k.imported_account_id is None
assert k.imported_at is None
assert k.imported_target_group_id is None
assert k.imported_target_group_name is None
# status 不受影响
assert k.status == "imported"