fix: price_monitor DB写锁死锁根治 + mofin_db.py reassessed_at同步
1. price_monitor.py: 统一BEGIN IMMEDIATE包裹所有DB写操作, 5次重试+指数退避(1→2→4→8→16s),重试耗尽后自动 emergency WAL checkpoint,try/finally确保conn释放 2. 补充进程锁:防止cron每2分钟触发但脚本跑3分钟时的并发 3. mofin_db.py: 同步cron版本的reassessed_at列处理逻辑
This commit is contained in:
@@ -37,6 +37,11 @@ def get_conn() -> sqlite3.Connection:
|
||||
conn.execute("PRAGMA foreign_keys=ON")
|
||||
conn.execute("PRAGMA busy_timeout=30000")
|
||||
conn.execute("PRAGMA synchronous=NORMAL")
|
||||
# 每次连接时清理WAL:防止被kill的进程留下残留事务导致后续全部卡死
|
||||
try:
|
||||
conn.execute("PRAGMA wal_checkpoint(TRUNCATE)")
|
||||
except Exception:
|
||||
pass
|
||||
return conn
|
||||
|
||||
|
||||
|
||||
@@ -387,6 +387,21 @@ def get_trigger_zones(trigger):
|
||||
|
||||
def run_once(round_label=""):
|
||||
"""执行一轮完整的监控流程"""
|
||||
import os # 必须在开头import,否则os变量会被后面的局部import绑定覆盖
|
||||
# ── 进程锁:同一时间只跑一个实例 ──
|
||||
_lk = "/tmp/price_monitor.lock"
|
||||
_pid = None
|
||||
try:
|
||||
with open(_lk) as _f:
|
||||
_pid = int(_f.read().strip())
|
||||
os.kill(_pid, 0)
|
||||
print(f"[LOCK] 已有实例(PID {_pid})在运行,跳过本轮", file=sys.stderr, flush=True)
|
||||
return
|
||||
except (FileNotFoundError, ProcessLookupError, ValueError):
|
||||
pass
|
||||
with open(_lk, "w") as _f:
|
||||
_f.write(str(os.getpid()))
|
||||
|
||||
label = f" [{round_label}]" if round_label else ""
|
||||
start = time.time()
|
||||
|
||||
@@ -659,6 +674,12 @@ def run_once(round_label=""):
|
||||
# 输出耗时
|
||||
print(f"⏱{label} {elapsed:.1f}s", flush=True)
|
||||
|
||||
# 清理进程锁
|
||||
try:
|
||||
os.remove("/tmp/price_monitor.lock")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
"""每cron触发跑一轮"""
|
||||
|
||||
Reference in New Issue
Block a user