fix: busy_timeout补丁回归——conn未定义改db/_conn等实际变量(18文件,知微卡t_62624130/t_f244e050发现)
This commit is contained in:
@@ -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():
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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' "
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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:
|
||||
# 检查持仓
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user