feat: stabilize multi-region runtime sync and worker orchestration
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from math import ceil
|
||||
|
||||
from app.core.db import get_db
|
||||
@@ -113,6 +114,8 @@ def _build_step_details(row: tuple) -> list[dict]:
|
||||
_normalize_step_detail("时光机", row[21]),
|
||||
_normalize_step_detail("站长之家", row[22]),
|
||||
_normalize_step_detail("爱站网", row[23]),
|
||||
_normalize_step_detail("桔子SEO", row[24]),
|
||||
_normalize_step_detail("聚查", row[25]),
|
||||
]
|
||||
|
||||
|
||||
@@ -152,6 +155,28 @@ def _normalize_detection_update(value) -> bool | None:
|
||||
raise ValueError("检测结果字段仅支持“是”或“否”")
|
||||
|
||||
|
||||
def _now_text() -> str:
|
||||
return datetime.now().isoformat(sep=" ", timespec="seconds")
|
||||
|
||||
|
||||
def _merge_detection_step_update(field: str, value: bool, existing_payload) -> dict | bool:
|
||||
if field == "is_chinese_title":
|
||||
return bool(value)
|
||||
|
||||
existing = dict(existing_payload or {}) if isinstance(existing_payload, dict) else {}
|
||||
previous_status = existing.get("status") if isinstance(existing.get("status"), bool) else None
|
||||
merged = dict(existing)
|
||||
merged["status"] = bool(value)
|
||||
merged["state"] = "passed" if bool(value) else "failed"
|
||||
merged["step"] = str(merged.get("step") or field)
|
||||
if previous_status != bool(value) or not str(merged.get("message") or "").strip():
|
||||
merged["message"] = "人工批量更新"
|
||||
if previous_status != bool(value) or not str(merged.get("checked_at") or "").strip():
|
||||
merged["checked_at"] = _now_text()
|
||||
merged["manual_override"] = True
|
||||
return merged
|
||||
|
||||
|
||||
def _build_domain_query_parts(filters: dict | None = None) -> tuple[str, str, list[object]]:
|
||||
filters = filters or {}
|
||||
conditions: list[str] = []
|
||||
@@ -190,8 +215,9 @@ def _build_domain_query_parts(filters: dict | None = None) -> tuple[str, str, li
|
||||
if filters.get("source_type") is not None:
|
||||
conditions.append("d.source_type = %s")
|
||||
params.append(int(filters["source_type"]))
|
||||
if filters.get("backlink_gt_10"):
|
||||
conditions.append("coalesce(dd.backlink_count_gt_10, false) = true")
|
||||
if filters.get("backlink_gt_10") is not None:
|
||||
conditions.append("coalesce(dd.backlink_count_gt_10, false) = %s")
|
||||
params.append(bool(filters["backlink_gt_10"]))
|
||||
|
||||
from_clause = """
|
||||
from domains d
|
||||
@@ -264,7 +290,9 @@ def fetch_domains(
|
||||
dd.google_site,
|
||||
dd.wayback_info,
|
||||
dd.chinaz_info,
|
||||
dd.aizhan_info
|
||||
dd.aizhan_info,
|
||||
dd.juziseo_info,
|
||||
dd.jucha_info
|
||||
{from_clause}
|
||||
{where_clause}
|
||||
order by d.id desc
|
||||
@@ -360,26 +388,7 @@ def fetch_domain_detail(domain_id: int) -> dict | None:
|
||||
if not row:
|
||||
return None
|
||||
|
||||
step_details = [
|
||||
_normalize_step_detail("百度历史收录", row[16]),
|
||||
_normalize_step_detail("百度Site收录", row[17]),
|
||||
{
|
||||
"label": "标题为中文",
|
||||
"state": "passed" if bool(row[18]) else "",
|
||||
"status": bool(row[18]),
|
||||
"message": "标题含中文" if bool(row[18]) else "",
|
||||
"checked_at": "",
|
||||
"step": "中文标题",
|
||||
"raw": row[18],
|
||||
},
|
||||
_normalize_step_detail("360 Site收录", row[19]),
|
||||
_normalize_step_detail("Google Site收录", row[20]),
|
||||
_normalize_step_detail("时光机", row[21]),
|
||||
_normalize_step_detail("站长之家", row[22]),
|
||||
_normalize_step_detail("爱站网", row[23]),
|
||||
_normalize_step_detail("桔子SEO", row[24]),
|
||||
_normalize_step_detail("聚查", row[25]),
|
||||
]
|
||||
step_details = _build_step_details(row)
|
||||
step_summary = _summarize_step_details(step_details)
|
||||
return {
|
||||
"id": row[0],
|
||||
@@ -523,6 +532,34 @@ def batch_update_domains(domain_ids: list[int], updates: dict) -> dict:
|
||||
tuple(params),
|
||||
)
|
||||
|
||||
existing_detection_payloads: dict[str, object] = {}
|
||||
existing_detection_row = None
|
||||
if "backlink_count" in payload or detection_fields.intersection(payload.keys()):
|
||||
cur.execute(
|
||||
"""
|
||||
select
|
||||
id,
|
||||
baidu_history,
|
||||
baidu_site,
|
||||
is_chinese_title,
|
||||
qihu360_site,
|
||||
google_site,
|
||||
backlink_count_gt_10
|
||||
from domain_detections
|
||||
where domain_id = %s
|
||||
""",
|
||||
(domain_id,),
|
||||
)
|
||||
existing_detection_row = cur.fetchone()
|
||||
if existing_detection_row:
|
||||
existing_detection_payloads = {
|
||||
"baidu_history": existing_detection_row[1],
|
||||
"baidu_site": existing_detection_row[2],
|
||||
"is_chinese_title": existing_detection_row[3],
|
||||
"qihu360_site": existing_detection_row[4],
|
||||
"google_site": existing_detection_row[5],
|
||||
}
|
||||
|
||||
detection_payload: dict[str, object] = {}
|
||||
for field in detection_fields:
|
||||
if field not in payload:
|
||||
@@ -530,15 +567,15 @@ def batch_update_domains(domain_ids: list[int], updates: dict) -> dict:
|
||||
normalized = _normalize_detection_update(payload[field])
|
||||
if normalized is None:
|
||||
continue
|
||||
if field == "is_chinese_title":
|
||||
detection_payload[field] = normalized
|
||||
else:
|
||||
detection_payload[field] = {"status": normalized}
|
||||
detection_payload[field] = _merge_detection_step_update(
|
||||
field,
|
||||
normalized,
|
||||
existing_detection_payloads.get(field),
|
||||
)
|
||||
|
||||
if "backlink_count" in payload:
|
||||
backlink_gt_10 = int(payload["backlink_count"]) > 10
|
||||
cur.execute("select id from domain_detections where domain_id = %s", (domain_id,))
|
||||
if cur.fetchone():
|
||||
if existing_detection_row:
|
||||
cur.execute(
|
||||
"update domain_detections set backlink_count_gt_10 = %s, update_time = now() where domain_id = %s",
|
||||
(backlink_gt_10, domain_id),
|
||||
@@ -553,9 +590,7 @@ def batch_update_domains(domain_ids: list[int], updates: dict) -> dict:
|
||||
)
|
||||
|
||||
if detection_payload:
|
||||
cur.execute("select id from domain_detections where domain_id = %s", (domain_id,))
|
||||
existing_detection = cur.fetchone()
|
||||
if existing_detection:
|
||||
if existing_detection_row:
|
||||
detection_set_parts: list[str] = []
|
||||
detection_params: list[object] = []
|
||||
for field, value in detection_payload.items():
|
||||
|
||||
Reference in New Issue
Block a user