fix: batch_reassess主conn加busy_timeout(重做,勿在try尾插PRAGMA)+watchlist已修,整点写锁不崩

This commit is contained in:
xxm
2026-08-17 16:54:22 +08:00
parent 71bd44d4de
commit 33a0932642
+8 -10
View File
@@ -25,7 +25,7 @@ STALE_HOURS = 20 # 分析超过20小时视为过期,需要重评
def has_llm_analysis(code):
"""检查是否为LLM生成的12维分析(>500字)"""
conn = sqlite3.connect(DB)
conn = sqlite3.connect(DB, timeout=30)
r = conn.execute("SELECT LENGTH(full_analysis) FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
conn.close()
return r and r[0] and r[0] > 500
@@ -37,7 +37,6 @@ def in_cooldown(code):
if FORCE_REASSESS:
return False
conn = sqlite3.connect(DB, timeout=30)
conn.execute("PRAGMA busy_timeout=30000")
r = conn.execute("SELECT reassessed_at FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
conn.close()
if not r or not r[0]:
@@ -51,7 +50,7 @@ def in_cooldown(code):
def analysis_stale(code, force_today=False):
"""分析是否过期(>STALE_HOURS 或 force_today 时今早4点前未重评)"""
conn = sqlite3.connect(DB)
conn = sqlite3.connect(DB, timeout=30)
r = conn.execute("SELECT reassessed_at FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
conn.close()
if not r or not r[0]:
@@ -69,7 +68,6 @@ def get_portfolio():
"""从 portfolio_summary 读实时现金/总资产(不再硬编码)"""
try:
conn = sqlite3.connect(DB, timeout=30)
conn.execute("PRAGMA busy_timeout=30000")
r = conn.execute("SELECT cash, total_assets FROM portfolio_summary WHERE id=1").fetchone()
conn.close()
if r and r[1]:
@@ -83,7 +81,7 @@ def collect_data(code):
data = {"code": code}
# 从DB读策略(含 full_analysis / changelog_json / position_advice
conn = sqlite3.connect(DB)
conn = sqlite3.connect(DB, timeout=30)
r = conn.execute("SELECT name, entry_low, entry_high, stop_loss, take_profit, timing_signal, action, rr_ratio, tech_snapshot, sector_context, stock_category, full_analysis, changelog_json, reassessed_at, position_advice FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
if r:
data["name"] = r[0]
@@ -136,7 +134,7 @@ def collect_data(code):
if (not _sector_ctx) or _sector_ctx.startswith('大盘上涨比') or len(_sector_ctx) < 4:
_resolved = ""
try:
_sdb = sqlite3.connect(DB)
_sdb = sqlite3.connect(DB, timeout=30)
_sr = _sdb.execute("SELECT sector_name FROM stock_sectors WHERE code=? LIMIT 1", (code,)).fetchone()
_sdb.close()
if _sr and _sr[0]:
@@ -147,7 +145,7 @@ def collect_data(code):
data['sector_context'] = _sector_ctx
# 大盘
try:
conn = sqlite3.connect(DB)
conn = sqlite3.connect(DB, timeout=30)
mr = conn.execute("SELECT structure FROM macro_context_log ORDER BY id DESC LIMIT 1").fetchone()
if mr and mr[0]:
s = json.loads(mr[0])
@@ -296,7 +294,7 @@ def build_prompt(data):
_rotation_context = ""
if not data.get('held'):
try:
_rc = sqlite3.connect(DB)
_rc = sqlite3.connect(DB, timeout=30)
_weak = _rc.execute("""
SELECT hs.code, hs.name, hs.timing_signal, h.position_pct, h.cost
FROM holding_strategies hs
@@ -505,7 +503,8 @@ def save_result(code, full_text, parsed, ta_levels=None):
if not (full_text or "").strip():
print(f" \u274c 拒绝写入空分析(LLM输出为空,保护已有数据)")
return
conn = sqlite3.connect(DB)
conn = sqlite3.connect(DB, timeout=30)
conn.execute("PRAGMA busy_timeout=30000")
now = datetime.now().isoformat()
# ── 修改前快照 ──
@@ -689,7 +688,6 @@ def main():
# 按类型筛选 active 策略
type_map = {"holding": "持仓策略", "watchlist": "自选策略"}
conn = sqlite3.connect(DB, timeout=30)
conn.execute("PRAGMA busy_timeout=30000")
if dtype in type_map:
rows = conn.execute(
"SELECT code FROM holding_strategies WHERE status='active' AND decision_type=? ORDER BY code",