Add module event producer coverage
Some checks failed
Dependency Audit / dependency-audit (push) Has been cancelled
Module Matrix / module-matrix (push) Has been cancelled

This commit is contained in:
2026-07-10 18:40:38 +02:00
parent 83784ea19d
commit c61abe154c
10 changed files with 332 additions and 26 deletions

View File

@@ -6,6 +6,7 @@ from typing import Any, Iterable, Sequence
from sqlalchemy import BigInteger, DateTime, Index, Integer, JSON, String, UniqueConstraint, func
from sqlalchemy.orm import Mapped, Session, mapped_column
from govoplan_core.core.events import EventActorRef, EventObjectRef, EventTenantRef, PlatformEvent, publish_platform_event
from govoplan_core.db.base import Base, utcnow
WATERMARK_PREFIX = "seq:"
@@ -95,9 +96,42 @@ def record_change(
payload=payload or {},
)
session.add(entry)
_publish_change_event(entry)
return entry
def _publish_change_event(entry: ChangeSequenceEntry) -> None:
event_type = _change_event_type(entry.module_id, entry.resource_type, entry.operation)
publish_platform_event(
PlatformEvent(
type=event_type,
module_id=entry.module_id,
payload={
"collection": entry.collection,
"operation": entry.operation,
"payload": dict(entry.payload or {}),
},
actor=EventActorRef(type=entry.actor_type, id=entry.actor_id) if entry.actor_type else None,
tenant=EventTenantRef(id=entry.tenant_id) if entry.tenant_id else None,
resource=EventObjectRef(type=entry.resource_type, id=entry.resource_id),
classification="internal",
)
)
def _change_event_type(module_id: str, resource_type: str, operation: str) -> str:
resource = _event_segment(resource_type)
module = _event_segment(module_id)
if resource.startswith(f"{module}."):
resource = resource[len(module) + 1:]
return ".".join(item for item in (module, resource, _event_segment(operation)) if item)
def _event_segment(value: str) -> str:
compact = "".join(character if character.isalnum() else "." for character in value.casefold())
return ".".join(part for part in compact.split(".") if part)
def max_sequence_id(
session: Session,
*,

View File

@@ -168,5 +168,26 @@ class EventBus:
handler(traced)
_default_event_bus = EventBus()
_current_event_bus: ContextVar[EventBus | None] = ContextVar("govoplan_event_bus", default=None)
def platform_event_bus() -> EventBus:
return _current_event_bus.get() or _default_event_bus
@contextmanager
def event_bus_context(bus: EventBus):
token = _current_event_bus.set(bus)
try:
yield bus
finally:
_current_event_bus.reset(token)
def publish_platform_event(event: PlatformEvent) -> None:
platform_event_bus().publish(event)
def _compact_dict(value: Mapping[str, Any]) -> dict[str, Any]:
return {key: item for key, item in value.items() if item is not None}