feat: DB-first architecture with lock-safe writes

- price_monitor: writes live prices to both JSON and mofin.db (holdings + live_prices + portfolio_summary)
- mofin_db: added execute_with_retry/commit_with_retry with exponential backoff on 'database is locked'
- mofin_db: increased timeout 5s->15s, added PRAGMA busy_timeout=15000
- price_monitor retry loop: fixed break-before-if-ok bug (was not retrying on write failure)
- DB connection: WAL mode + retry decorator for all write operations
- cash sync: preserves DB authoritative cash (JSON cash not pushed to DB)

This is the DB-first version. JSON writes remain for dashboard compatibility.
Next step: remove JSON writes entirely for full DB-only architecture.
This commit is contained in:
知微
2026-07-06 12:02:11 +08:00
parent 687155487d
commit e185b4e4dc
30 changed files with 1856 additions and 2042 deletions
+4 -4
View File
@@ -17,6 +17,8 @@ import urllib.error
from datetime import datetime, date, timedelta
from typing import Optional
from mofin_db import get_conn
DATA_DIR = "/home/hmo/web-dashboard/data"
HISTORY_PATH = os.path.join(DATA_DIR, "price_history.json")
# multi_tf_cache.json 已迁移到 DB (mtf_cache 表)
@@ -91,8 +93,7 @@ def _load_mtf_cache():
if _MTF_CACHE_DATA is not None:
return _MTF_CACHE_DATA
try:
import sqlite3
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
db = get_conn()
rows = db.execute("SELECT code, cache_json FROM mtf_cache").fetchall()
_MTF_CACHE_DATA = {}
for code, json_str in rows:
@@ -112,8 +113,7 @@ def _save_mtf_cache():
if _MTF_CACHE_DATA is None:
return
try:
import sqlite3
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
db = get_conn()
for code, data in _MTF_CACHE_DATA.items():
db.execute(
"INSERT OR REPLACE INTO mtf_cache (code, cache_json, updated_at) VALUES (?,?,datetime('now','localtime'))",