fix: telemetry single persistent connection + lock (kill concurrent write lock)
This commit is contained in:
@@ -146,3 +146,50 @@ async def test_concurrent_writes_no_lock_error(recorder, db_path):
|
||||
count = conn.execute("SELECT COUNT(*) FROM llm_calls").fetchone()[0]
|
||||
conn.close()
|
||||
assert count == 16
|
||||
|
||||
|
||||
def test_high_concurrency_writes_zero_loss(recorder, db_path):
|
||||
"""64 路线程并发直压 _write 应零丢失——复现生产 concurrency 下 database is locked 丢失。
|
||||
|
||||
直接压同步 _write(不经 to_thread 排队),最大化并发连接数以逼出锁竞争;
|
||||
单连接 + threading.Lock 串行化模式下应全部落库、零丢失(对齐 HarnessLog)。
|
||||
"""
|
||||
import concurrent.futures
|
||||
|
||||
n = 64
|
||||
kwargs_list = [_make_call_kwargs() for _ in range(n)]
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=n) as executor:
|
||||
list(executor.map(lambda kw: recorder._write(**kw), kwargs_list))
|
||||
|
||||
conn = sqlite3.connect(str(db_path))
|
||||
count = conn.execute("SELECT COUNT(*) FROM llm_calls").fetchone()[0]
|
||||
conn.close()
|
||||
assert count == n, f"并发写丢失 {n - count} 条(database is locked 降级丢弃): 落库 {count}/{n}"
|
||||
|
||||
|
||||
def test_uses_single_persistent_connection(db_path, monkeypatch):
|
||||
"""对齐 HarnessLog:单持久连接(构造时建一次),写入复用而非每次新建。
|
||||
|
||||
每次写新建连接是并发锁竞争根源(多连接争 SQLite 写锁,撑爆 busy_timeout);
|
||||
单连接 + 进程内 Lock 串行化把并发控制拉到进程内,消除 SQLite 层锁竞争。
|
||||
"""
|
||||
connect_calls = {"n": 0}
|
||||
real_connect = sqlite3.connect
|
||||
|
||||
def _counting_connect(*args, **kwargs):
|
||||
connect_calls["n"] += 1
|
||||
return real_connect(*args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(sqlite3, "connect", _counting_connect)
|
||||
|
||||
recorder = SQLiteTelemetryRecorder(db_path=db_path)
|
||||
after_init = connect_calls["n"]
|
||||
for _ in range(10):
|
||||
recorder._write(**_make_call_kwargs())
|
||||
after_writes = connect_calls["n"]
|
||||
|
||||
assert after_init >= 1, "构造时应建立持久连接(对齐 HarnessLog)"
|
||||
assert after_writes == after_init, (
|
||||
f"写入期间新建了 {after_writes - after_init} 个连接(应复用单持久连接,"
|
||||
"每次新连接是并发锁竞争根源)"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user