fix: busy_timeout补丁回归——conn未定义改db/_conn等实际变量(18文件,知微卡t_62624130/t_f244e050发现)

This commit is contained in:
xxm
2026-08-28 14:59:41 +08:00
parent 139633d743
commit d04d9d5052
18 changed files with 28 additions and 28 deletions
@@ -155,7 +155,7 @@ def main():
try:
import sqlite3
_db = sqlite3.connect("/home/hmo/MoFin/data/mofin.db")
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
_db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
for row in _db.execute("SELECT DISTINCT code FROM holdings WHERE is_active=1").fetchall():
if row[0]: codes.add(row[0])
for row in _db.execute("SELECT DISTINCT code FROM holding_strategies WHERE status='active' AND decision_type='自选策略'").fetchall():
+1 -1
View File
@@ -98,7 +98,7 @@ def main():
try:
import sqlite3
_conn = sqlite3.connect("/home/hmo/web-dashboard/data/mofin.db")
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
_conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
_actionable = _conn.execute(
"SELECT hs.code, lp.price, hs.entry_low, hs.entry_high FROM holding_strategies hs "
"LEFT JOIN live_prices lp ON hs.code = lp.code "
+1 -1
View File
@@ -51,7 +51,7 @@ def main():
return
notified = _load_state()
db = sqlite3.connect(KANBAN_DB)
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
rows = db.execute(
"SELECT id, title, assignee, created_by FROM tasks "
"WHERE status='ready' AND assignee IN (%s) ORDER BY created_at"
+1 -1
View File
@@ -41,7 +41,7 @@ def scan_leaders():
return []
c = sqlite3.connect(DB)
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
c.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
# 最新交易日
row = c.execute("SELECT MAX(date) FROM stock_indicators").fetchone()
if not row or not row[0]:
@@ -59,7 +59,7 @@ def get_existing_codes():
try:
import sqlite3
db = sqlite3.connect(str(MOFIN_DATA / "mofin.db"))
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
for row in db.execute("SELECT code FROM watchlist_stocks WHERE is_active=1"):
codes.add(str(row[0]).strip())
for row in db.execute("SELECT code FROM holdings"):
+2 -2
View File
@@ -23,7 +23,7 @@ SCRIPT_DIR = Path('/home/hmo/MoFin/scripts')
def _get_db():
db = sqlite3.connect(DB_PATH)
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
return db
@@ -288,7 +288,7 @@ def write_cash_log(cash_before, cash_after, frozen_before, frozen_after,
"""记录现金变更到 cash_log 表。"""
change_amount = round(cash_after - cash_before, 2) if cash_after is not None and cash_before is not None else 0
db = sqlite3.connect(DB_PATH)
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
try:
cur = db.execute(
"""INSERT INTO cash_log
+2 -2
View File
@@ -1119,7 +1119,7 @@ def get_price_from_db(code: str) -> tuple[float | None, float | None]:
"""
try:
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
row = db.execute(
"SELECT price, change_pct FROM holdings WHERE code=? AND is_active=1", (str(code),)
@@ -1143,7 +1143,7 @@ def get_prices_batch_from_db(codes: list[str]) -> dict:
return results
try:
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
for code in codes:
row = db.execute(
@@ -807,7 +807,7 @@ def main():
# 保存历史到DB
try:
conn_hist = sqlite3.connect(str(DB_PATH))
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
conn_hist.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
details = json.dumps([e for e in ctx["report"] if e["level"] in ("critical", "error")])
conn_hist.execute(
"INSERT INTO health_check_log (ok_count, warn_count, error_count, critical_count, duration_s, details) "
@@ -838,7 +838,7 @@ def main():
# 检查是否有执行器升级来的TODO(通知失败挂起的)
try:
conn2 = sqlite3.connect(str(DB_PATH))
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
conn2.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
needs_llm = conn2.execute(
"SELECT id, title, priority, created_at, note FROM todos "
"WHERE status='needs_llm' "
+4 -4
View File
@@ -273,7 +273,7 @@ def main():
# 不在 decisions 中的自选股 → 从 holding_strategies 构建entry
import sqlite3
_db = sqlite3.connect('/home/hmo/MoFin/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
_db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
_db.row_factory = sqlite3.Row
_wl = _db.execute("SELECT * FROM holding_strategies WHERE code=? AND status='active' AND decision_type='自选策略'", (code,)).fetchone()
_db.close()
@@ -308,7 +308,7 @@ def main():
price = 0
import sqlite3
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
row = db.execute("SELECT price FROM holdings WHERE code=? AND is_active=1", (code_raw,)).fetchone()
if not row:
@@ -562,7 +562,7 @@ def main():
from datetime import datetime as _dt
import sqlite3
_db2 = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
_db2.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
for _code in codes:
_entry = decisions_map.get(_code)
if _entry and _entry.get("is_watchlist"):
@@ -626,7 +626,7 @@ def scan_watchlist_stocks():
DB = '/home/hmo/web-dashboard/data/mofin.db'
db = sqlite3.connect(DB)
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
rows = db.execute(
+1 -1
View File
@@ -67,7 +67,7 @@ def check_data_freshness():
try:
import sqlite3
c = sqlite3.connect(str(WEB_DATA / "mofin.db"))
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
c.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
row = c.execute("SELECT MAX(updated_at) FROM holding_strategies WHERE status IN ('active','updated')").fetchone()
c.close()
if row and row[0]:
@@ -23,7 +23,7 @@ SCRIPTS_DIR = os.path.dirname(os.path.abspath(__file__))
def get_stock_info(code):
"""从数据库获取股票信息"""
db = sqlite3.connect(DB_PATH)
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
try:
# 检查持仓
+2 -2
View File
@@ -94,7 +94,7 @@ test("frozen_cash 已清零", pf.get('frozen_cash', 0) < 1, f"frozen_cash={pf.ge
print("\n--- 6. P&L ---")
import sqlite3
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
rows = db.execute("SELECT code, name, cost, price, shares, currency FROM holdings WHERE is_active=1 AND shares>0").fetchall()
pnl_issues = []
for r in rows:
@@ -112,7 +112,7 @@ db.close()
# ── 7. DB 完整性 ──
print("\n--- 7. DB 完整性 ---")
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
n_holds = db.execute("SELECT COUNT(*) FROM holdings WHERE is_active=1").fetchone()[0]
n_strat = db.execute("SELECT COUNT(*) FROM holding_strategies WHERE status IN ('active','updated')").fetchone()[0]
n_wl = db.execute("SELECT COUNT(*) FROM watchlist_stocks WHERE is_active=1").fetchone()[0]
+3 -3
View File
@@ -84,7 +84,7 @@ def main():
try:
import sqlite3
db = sqlite3.connect('/home/hmo/MoFin/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
wl_rows = db.execute(
"SELECT code, name, entry_low, entry_high, stop_loss, take_profit, rr_ratio, timing_signal, action "
@@ -125,7 +125,7 @@ def main():
try:
import subprocess, sqlite3
db = sqlite3.connect('/home/hmo/MoFin/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
wl_stocks = db.execute(
"SELECT code, name, entry_low, entry_high "
@@ -184,7 +184,7 @@ def main():
to_check = [d for d in decisions_list if (d.get("entry_low") is not None or d.get("entry_high") is not None) and d.get("status") not in EXCLUDED_STATUSES]
# 重新合并自选(从 holding_strategies 读)
db2 = sqlite3.connect('/home/hmo/MoFin/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db2.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db2.row_factory = sqlite3.Row
wl_rows2 = db2.execute(
"SELECT code, name, entry_low, entry_high, stop_loss, take_profit, rr_ratio, timing_signal, action "
+1 -1
View File
@@ -303,7 +303,7 @@ def _get_name_from_cache(code):
try:
import sqlite3
_db = sqlite3.connect(str(DATA_DIR / "mofin.db"))
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
_db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
_db.row_factory = sqlite3.Row
row = _db.execute("SELECT name FROM watchlist_stocks WHERE code=? AND is_active=1", (code,)).fetchone()
_db.close()
+1 -1
View File
@@ -37,7 +37,7 @@ ORANGE_PNL_RATIO = 0.5 # 盈亏比 < 0.5(赚的越来越少亏的越来越
def rolling_stats(version, days=60):
"""从 strategy_research 提取该策略近期交易的滚动胜率/盈亏比"""
c = sqlite3.connect(DB)
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
c.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
rows = c.execute(
"SELECT results_json FROM strategy_research WHERE version=? ORDER BY period_tag DESC LIMIT 1",
(version,)
+2 -2
View File
@@ -749,7 +749,7 @@ def batch_fetch_prices(codes):
try:
import sqlite3
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
for raw_code in codes:
raw_code = str(raw_code).split('_')[0]
@@ -819,7 +819,7 @@ def get_price_tencent(code):
try:
import sqlite3
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
db.row_factory = sqlite3.Row
row = db.execute("SELECT price FROM holdings WHERE code=? AND is_active=1", (raw_code,)).fetchone()
if not row:
+1 -1
View File
@@ -23,7 +23,7 @@ for db_path in DBS:
size_before = os.path.getsize(db_path) / 1024 / 1024
try:
c = sqlite3.connect(db_path)
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
c.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
c.execute("PRAGMA auto_vacuum=2")
# 只做incremental vacuum,不做full vacuum(耗时太长)
c.execute("PRAGMA incremental_vacuum(50000)")
@@ -81,7 +81,7 @@ def check_cron_jobs():
continue
try:
c = sqlite3.connect(str(db_path))
conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
c.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训)
for row in c.execute("""
SELECT id, name, last_status, last_run_at, enabled
FROM cron_jobs WHERE enabled=1