Persist durable event consumer delivery state
This commit is contained in:
@@ -10,7 +10,12 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from govoplan_core.auth import ApiPrincipal, has_scope, require_any_scope
|
||||
from govoplan_audit.backend.db.models import AuditLog
|
||||
from govoplan_core.audit.logging import AUDIT_MODULE_ID, AUDIT_SYSTEM_EVENTS_COLLECTION, AUDIT_TENANT_EVENTS_COLLECTION
|
||||
from govoplan_core.audit.logging import (
|
||||
AUDIT_MODULE_ID,
|
||||
AUDIT_SYSTEM_EVENTS_COLLECTION,
|
||||
AUDIT_TENANT_EVENTS_COLLECTION,
|
||||
audit_from_principal,
|
||||
)
|
||||
from govoplan_core.core.access import CAPABILITY_ACCESS_ADMINISTRATION, AccessAdministration
|
||||
from govoplan_core.core.change_sequence import decode_sequence_watermark, encode_sequence_watermark, max_sequence_id, sequence_entries_since, sequence_watermark_is_expired
|
||||
from govoplan_core.core.pagination import KeysetCursorError, decode_keyset_cursor, encode_keyset_cursor, keyset_query_fingerprint
|
||||
@@ -18,7 +23,18 @@ from govoplan_core.core.runtime import get_registry
|
||||
from govoplan_core.db.session import get_session
|
||||
from govoplan_core.tenancy.scope import Tenant
|
||||
|
||||
from .schemas import AuditAdminDeltaResponse, AuditAdminItem, AuditAdminListResponse, AuditLogItemResponse, AuditLogListResponse
|
||||
from govoplan_core.core.events import platform_event_outbox
|
||||
|
||||
from .schemas import (
|
||||
AuditAdminDeltaResponse,
|
||||
AuditAdminItem,
|
||||
AuditAdminListResponse,
|
||||
AuditLogItemResponse,
|
||||
AuditLogListResponse,
|
||||
EventDeliveryMetricsResponse,
|
||||
EventDeliveryReplayRequest,
|
||||
EventDeliveryReplayResponse,
|
||||
)
|
||||
|
||||
router = APIRouter(tags=["audit"])
|
||||
|
||||
@@ -633,3 +649,78 @@ def list_audit_log(
|
||||
query = query.filter(AuditLog.object_id == object_id)
|
||||
items = query.order_by(AuditLog.created_at.desc()).offset(offset).limit(limit).all()
|
||||
return AuditLogListResponse(items=[AuditLogItemResponse.model_validate(item) for item in items])
|
||||
|
||||
|
||||
@router.get(
|
||||
"/admin/audit/event-delivery/metrics",
|
||||
response_model=EventDeliveryMetricsResponse,
|
||||
)
|
||||
def event_delivery_metrics(
|
||||
session: Session = Depends(get_session),
|
||||
_principal: ApiPrincipal = Depends(
|
||||
require_any_scope("system:audit:read")
|
||||
),
|
||||
):
|
||||
outbox = platform_event_outbox(get_registry())
|
||||
if outbox is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="Durable platform event delivery is not configured",
|
||||
)
|
||||
return EventDeliveryMetricsResponse.model_validate(
|
||||
outbox.delivery_metrics(session)
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/admin/audit/event-deliveries/{event_id}/{consumer_id}/replay",
|
||||
response_model=EventDeliveryReplayResponse,
|
||||
)
|
||||
def replay_event_delivery(
|
||||
event_id: str,
|
||||
consumer_id: str,
|
||||
payload: EventDeliveryReplayRequest,
|
||||
session: Session = Depends(get_session),
|
||||
principal: ApiPrincipal = Depends(
|
||||
require_any_scope("system:governance:write")
|
||||
),
|
||||
):
|
||||
outbox = platform_event_outbox(get_registry())
|
||||
if outbox is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="Durable platform event delivery is not configured",
|
||||
)
|
||||
try:
|
||||
result = outbox.replay_delivery(
|
||||
session,
|
||||
event_id=event_id,
|
||||
consumer_id=consumer_id,
|
||||
operator_id=principal.account_id,
|
||||
reason=payload.reason,
|
||||
)
|
||||
except LookupError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=str(exc),
|
||||
) from exc
|
||||
except ValueError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail=str(exc),
|
||||
) from exc
|
||||
audit_from_principal(
|
||||
session,
|
||||
principal,
|
||||
action="platform_event.delivery_replayed",
|
||||
scope="system",
|
||||
object_type="platform_event_delivery",
|
||||
object_id=f"{event_id}:{consumer_id}",
|
||||
details={
|
||||
"event_id": event_id,
|
||||
"consumer_id": consumer_id,
|
||||
"reason": payload.reason,
|
||||
},
|
||||
)
|
||||
session.commit()
|
||||
return EventDeliveryReplayResponse.model_validate(result)
|
||||
|
||||
Reference in New Issue
Block a user