feat(collect): persist product status snapshots
This commit is contained in:
@@ -11,7 +11,7 @@ from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Iterable, Optional
|
||||
|
||||
from . import appconfig
|
||||
from . import appconfig, product_status
|
||||
from .config import make_slug
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ FAILURE_STEP_LABELS = {
|
||||
"open_product": "打开商品页",
|
||||
"wait_ready": "页面就绪",
|
||||
"read_title": "读标题",
|
||||
"read_product_status": "读取商品状态",
|
||||
"read_cover": "读封面",
|
||||
"download_cover": "下载封面",
|
||||
"db_write": "写库",
|
||||
@@ -135,6 +136,9 @@ class Task:
|
||||
account_name: Optional[str]
|
||||
alias: str
|
||||
item_id: str
|
||||
product_status: Optional[str]
|
||||
product_status_note: Optional[str]
|
||||
product_status_at: Optional[str]
|
||||
old_title: Optional[str]
|
||||
old_cover_path: Optional[str]
|
||||
new_title: Optional[str]
|
||||
@@ -232,6 +236,9 @@ CREATE TABLE IF NOT EXISTS tasks (
|
||||
account_name TEXT,
|
||||
alias TEXT NOT NULL,
|
||||
item_id TEXT NOT NULL,
|
||||
product_status TEXT,
|
||||
product_status_note TEXT,
|
||||
product_status_at TEXT,
|
||||
old_title TEXT,
|
||||
old_cover_path TEXT,
|
||||
new_title TEXT,
|
||||
@@ -485,6 +492,7 @@ def init_db(path=None, conn=None) -> None:
|
||||
_ensure_batch_delete_columns(database)
|
||||
_ensure_task_image_task_columns(database)
|
||||
_ensure_task_cover_reset_columns(database)
|
||||
_ensure_task_product_status_columns(database)
|
||||
_ensure_image_studio_project_suite_columns(database)
|
||||
_ensure_image_studio_project_draft_columns(database)
|
||||
_ensure_image_studio_job_recovery_columns(database)
|
||||
@@ -516,6 +524,16 @@ def _ensure_task_cover_reset_columns(database):
|
||||
database.execute("ALTER TABLE tasks ADD COLUMN cover_reset_at TEXT")
|
||||
|
||||
|
||||
def _ensure_task_product_status_columns(database):
|
||||
columns = {row["name"] for row in database.execute("PRAGMA table_info(tasks)").fetchall()}
|
||||
if "product_status" not in columns:
|
||||
database.execute("ALTER TABLE tasks ADD COLUMN product_status TEXT")
|
||||
if "product_status_note" not in columns:
|
||||
database.execute("ALTER TABLE tasks ADD COLUMN product_status_note TEXT")
|
||||
if "product_status_at" not in columns:
|
||||
database.execute("ALTER TABLE tasks ADD COLUMN product_status_at TEXT")
|
||||
|
||||
|
||||
def _ensure_image_studio_project_suite_columns(database):
|
||||
columns = {
|
||||
row["name"]
|
||||
@@ -1021,8 +1039,53 @@ def clear_image_task(task_id, path=None, conn=None) -> None:
|
||||
)
|
||||
|
||||
|
||||
def set_collected(task_id, old_title, old_cover_path, path=None, conn=None) -> None:
|
||||
def set_product_status(
|
||||
task_id,
|
||||
product_status_value,
|
||||
product_status_note=None,
|
||||
product_status_at=None,
|
||||
path=None,
|
||||
conn=None,
|
||||
) -> None:
|
||||
"""Persist a status snapshot without changing the collection lifecycle."""
|
||||
|
||||
now = _now()
|
||||
detected_at = product_status_at or now
|
||||
with _connection(conn, path) as database:
|
||||
with database:
|
||||
database.execute(
|
||||
"""
|
||||
UPDATE tasks
|
||||
SET product_status = ?,
|
||||
product_status_note = ?,
|
||||
product_status_at = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
""",
|
||||
(
|
||||
product_status.normalize_status(product_status_value),
|
||||
str(product_status_note or "")[:2000] or None,
|
||||
detected_at,
|
||||
now,
|
||||
int(task_id),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def set_collected(
|
||||
task_id,
|
||||
old_title,
|
||||
old_cover_path,
|
||||
path=None,
|
||||
conn=None,
|
||||
*,
|
||||
product_status_value=None,
|
||||
product_status_note=None,
|
||||
product_status_at=None,
|
||||
) -> None:
|
||||
now = _now()
|
||||
has_status_snapshot = product_status_value is not None
|
||||
detected_at = product_status_at or now
|
||||
with _connection(conn, path) as database:
|
||||
with database:
|
||||
database.execute(
|
||||
@@ -1035,10 +1098,25 @@ def set_collected(task_id, old_title, old_cover_path, path=None, conn=None) -> N
|
||||
last_error = NULL,
|
||||
collect_attempts = collect_attempts + 1,
|
||||
collected_at = ?,
|
||||
product_status = CASE WHEN ? THEN ? ELSE product_status END,
|
||||
product_status_note = CASE WHEN ? THEN ? ELSE product_status_note END,
|
||||
product_status_at = CASE WHEN ? THEN ? ELSE product_status_at END,
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
""",
|
||||
(old_title, old_cover_path, now, now, int(task_id)),
|
||||
(
|
||||
old_title,
|
||||
old_cover_path,
|
||||
now,
|
||||
int(has_status_snapshot),
|
||||
product_status.normalize_status(product_status_value),
|
||||
int(has_status_snapshot),
|
||||
str(product_status_note or "")[:2000] or None,
|
||||
int(has_status_snapshot),
|
||||
detected_at,
|
||||
now,
|
||||
int(task_id),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user