alphax/app/db/market_db.py
2026-05-18 15:40:59 +08:00

89 lines
2.7 KiB
Python

"""Market overview snapshot persistence."""
import json
from datetime import datetime
from app.db.schema import get_conn
SNAPSHOT_TYPE = "crypto_market"
def _now():
return datetime.now().isoformat(timespec="seconds")
def save_market_snapshot(data, *, status="success", error_message=""):
payload = data if isinstance(data, dict) else {}
snapshot_time = str(payload.get("updated_at") or _now())
source = str(payload.get("source") or "binance_spot_usdt_market")
conn = get_conn()
try:
row = conn.execute(
"""
INSERT INTO market_snapshots (
snapshot_type, source, snapshot_time, data_json, status, error_message, created_at
) VALUES (%s, %s, %s, %s, %s, %s, %s)
RETURNING id
""",
(
SNAPSHOT_TYPE,
source,
snapshot_time,
json.dumps(payload, ensure_ascii=False, default=str),
status,
str(error_message or "")[:1000],
_now(),
),
).fetchone()
conn.commit()
return int(row["id"] if row else 0)
except Exception:
conn.rollback()
raise
finally:
conn.close()
def get_latest_market_snapshot(max_age_seconds=None):
conn = get_conn()
try:
row = conn.execute(
"""
SELECT *
FROM market_snapshots
WHERE snapshot_type=%s AND status='success'
ORDER BY snapshot_time DESC, id DESC
LIMIT 1
""",
(SNAPSHOT_TYPE,),
).fetchone()
finally:
conn.close()
if not row:
return None
item = dict(row)
try:
data = json.loads(item.get("data_json") or "{}")
except Exception:
data = {}
if not isinstance(data, dict):
data = {}
data.setdefault("updated_at", item.get("snapshot_time") or "")
data.setdefault("source", item.get("source") or "binance_spot_usdt_market")
if max_age_seconds:
try:
ts = datetime.fromisoformat(str(item.get("snapshot_time") or data.get("updated_at")))
data["snapshot_age_seconds"] = max(0, round((datetime.now() - ts).total_seconds()))
data["snapshot_stale"] = data["snapshot_age_seconds"] > int(max_age_seconds)
except Exception:
data["snapshot_age_seconds"] = None
data["snapshot_stale"] = True
return data
def save_market_error(error_message, data=None):
payload = data if isinstance(data, dict) else {"updated_at": _now(), "source": "binance_spot_usdt_market"}
return save_market_snapshot(payload, status="error", error_message=error_message)