feat: strengthen module contracts and shared WebUI runtime

This commit is contained in:
2026-07-29 14:16:28 +02:00
parent 53e947935a
commit 68328f3d8e
57 changed files with 4358 additions and 371 deletions

View File

@@ -19,10 +19,25 @@ from govoplan_core.core.change_sequence import (
sequence_watermark_is_expired,
)
from govoplan_core.core.events import EventActorRef, EventBus, EventObjectRef, EventTenantRef, PlatformEvent, event_bus_context
from govoplan_core.core.runtime import (
clear_runtime,
configure_runtime,
get_runtime_context,
)
from govoplan_core.db.base import Base
class ChangeSequenceTests(unittest.TestCase):
def setUp(self) -> None:
self._runtime_context = get_runtime_context()
clear_runtime()
def tearDown(self) -> None:
if self._runtime_context is not None:
configure_runtime(self._runtime_context)
else:
clear_runtime()
def test_records_changes_and_returns_entries_after_watermark(self) -> None:
engine = create_engine("sqlite:///:memory:")
SessionLocal = sessionmaker(bind=engine)
@@ -93,6 +108,8 @@ class ChangeSequenceTests(unittest.TestCase):
actor_id="user-1",
payload={"scope_type": "tenant"},
)
self.assertEqual([], seen)
session.commit()
self.assertEqual([case[-1] for case in cases], [event.type for event in seen])
event = seen[1]
@@ -105,6 +122,36 @@ class ChangeSequenceTests(unittest.TestCase):
finally:
engine.dispose()
def test_record_change_discards_event_when_transaction_rolls_back(self) -> None:
engine = create_engine("sqlite:///:memory:")
SessionLocal = sessionmaker(bind=engine)
try:
Base.metadata.create_all(
bind=engine,
tables=[
ChangeSequenceEntry.__table__,
ChangeSequenceRetentionFloor.__table__,
],
)
seen: list[PlatformEvent] = []
bus = EventBus()
bus.subscribe("*", seen.append)
with SessionLocal() as session, event_bus_context(bus):
record_change(
session,
tenant_id="tenant-1",
module_id="files",
collection="files.assets",
resource_type="file",
resource_id="file-1",
operation="created",
)
session.rollback()
self.assertEqual([], seen)
finally:
engine.dispose()
def test_pruning_records_retention_floor_for_stale_watermarks(self) -> None:
engine = create_engine("sqlite:///:memory:")
SessionLocal = sessionmaker(bind=engine)