fix(portfolio): order_event_store 连接显式 close(M9 defer 清账) [vps]
CI/CD / test (push) Successful in 29s
CI/CD / nas-deploy (push) Successful in 11s
CI/CD / nas-verify (push) Successful in 8s

with _connect(...) 只 commit 不 close——sqlite 连接靠 GC 回收(已知坑)。
最小修:新增 _conn contextmanager(内层 with conn 保留事务语义 commit/rollback,
finally 显式 close);append_events/replay_order_states 两处换用。
_connect 本身保留(幂等建表职责不变)。行为零变化,不新增测试;
全量 tests/portfolio 730 passed / 2 skipped 不变。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-26 20:12:10 +08:00
parent cd1793c7c3
commit 77e006e4d7
+15 -2
View File
@@ -14,6 +14,7 @@
from __future__ import annotations
import sqlite3
from contextlib import contextmanager
from typing import Any
EVENT_TYPES = ("submitted", "ack", "partial", "fill", "cancel", "reject", "expire")
@@ -58,11 +59,23 @@ def _connect(db_path: str) -> sqlite3.Connection:
return conn
@contextmanager
def _conn(db_path: str):
"""连接生命周期显式 close(M9 defer 清账:with _connect(...) 只 commit 不
close,sqlite 连接靠 GC 回收;事务语义由内层 with conn 保留 commit/rollback)。"""
conn = _connect(db_path)
try:
with conn: # 事务语义保留(commit/rollback)
yield conn
finally:
conn.close()
def append_events(db_path: str, events: list[dict[str, Any]]) -> int:
"""幂等追加;返回新插入行数(重复 (order_key,event_seq) 静默跳过)。"""
if not events:
return 0
with _connect(db_path) as conn:
with _conn(db_path) as conn:
before = conn.total_changes
conn.executemany(
f"INSERT OR IGNORE INTO order_events({', '.join(_EVENT_COLS)}) "
@@ -77,7 +90,7 @@ def replay_order_states(db_path: str, day: str | None = None) -> dict[str, dict]
status 归并规则:fill 终态标记行/ receipts 累计到量即 fill;partial 在途;
cancel/reject/expire 后到接管;ack 仅在仍 open 时置位。
"""
with _connect(db_path) as conn:
with _conn(db_path) as conn:
if day is None:
rows = conn.execute(
"SELECT * FROM order_events ORDER BY order_key, event_seq"