refactor(db)!: finalize pooled WNDB v2 migration
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import asyncio
|
||||
from contextlib import contextmanager
|
||||
from contextlib import asynccontextmanager, contextmanager
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from app.infra.db.timescaledb.repositories.realtime import RealtimeRepository
|
||||
@@ -71,12 +71,23 @@ def test_get_nodes_by_time_range_normalizes_inputs_to_utc():
|
||||
class _SyncTransactionConnection:
|
||||
def __init__(self):
|
||||
self.transactions = 0
|
||||
self.calls: list[tuple[str, tuple]] = []
|
||||
|
||||
@contextmanager
|
||||
def transaction(self):
|
||||
self.transactions += 1
|
||||
yield
|
||||
|
||||
@contextmanager
|
||||
def cursor(self):
|
||||
connection = self
|
||||
|
||||
class Cursor:
|
||||
def execute(self, query, params):
|
||||
connection.calls.append((query, params))
|
||||
|
||||
yield Cursor()
|
||||
|
||||
|
||||
def test_realtime_node_and_link_replacement_share_outer_transaction(monkeypatch):
|
||||
conn = _SyncTransactionConnection()
|
||||
@@ -101,3 +112,65 @@ def test_realtime_node_and_link_replacement_share_outer_transaction(monkeypatch)
|
||||
|
||||
assert conn.transactions == 1
|
||||
assert calls == ["nodes", "links"]
|
||||
assert [query for query, _params in conn.calls] == [
|
||||
"SELECT pg_advisory_xact_lock(hashtextextended(%s::text, 1))",
|
||||
"DELETE FROM realtime.node_results WHERE time = %s",
|
||||
"DELETE FROM realtime.link_results WHERE time = %s",
|
||||
]
|
||||
|
||||
|
||||
def test_realtime_batch_rejects_multiple_timestamps_before_writing():
|
||||
data = [
|
||||
{"time": "2026-06-01T00:00:00Z", "id": "N1"},
|
||||
{"time": "2026-06-01T00:15:00Z", "id": "N2"},
|
||||
]
|
||||
|
||||
try:
|
||||
RealtimeRepository.insert_nodes_batch_sync(object(), data)
|
||||
except ValueError as exc:
|
||||
assert str(exc) == "Realtime batch must contain exactly one timestamp"
|
||||
else:
|
||||
raise AssertionError("multiple realtime timestamps were accepted")
|
||||
|
||||
|
||||
class _AsyncEmptySnapshotConnection:
|
||||
def __init__(self):
|
||||
self.calls: list[tuple[str, tuple]] = []
|
||||
|
||||
@asynccontextmanager
|
||||
async def transaction(self):
|
||||
yield
|
||||
|
||||
def cursor(self):
|
||||
connection = self
|
||||
|
||||
class Cursor:
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *_args):
|
||||
return False
|
||||
|
||||
async def execute(self, query, params):
|
||||
connection.calls.append((query, params))
|
||||
|
||||
return Cursor()
|
||||
|
||||
|
||||
def test_empty_realtime_side_is_deleted_as_part_of_snapshot_replacement():
|
||||
conn = _AsyncEmptySnapshotConnection()
|
||||
|
||||
asyncio.run(
|
||||
RealtimeRepository.store_realtime_simulation_result(
|
||||
conn,
|
||||
node_result_list=[],
|
||||
link_result_list=[],
|
||||
result_start_time="2026-06-01T00:00:00Z",
|
||||
)
|
||||
)
|
||||
|
||||
assert [query for query, _params in conn.calls] == [
|
||||
"SELECT pg_advisory_xact_lock(hashtextextended(%s::text, 1))",
|
||||
"DELETE FROM realtime.node_results WHERE time = %s",
|
||||
"DELETE FROM realtime.link_results WHERE time = %s",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user