Commit c972cbc1 authored by George Papathanail's avatar George Papathanail
Browse files

fix mypy

parent 4b39543b
Loading
Loading
Loading
Loading
+27 −3
Changes for src/open_exposure_gateway/application/services/traffic_influence_service.py: 27 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ from open_exposure_gateway.application.mappers.traffic_influence_mapper import (
    build_traffic_influence_response,
)
from open_exposure_gateway.core.exceptions import (
    BadRequestException,
    ConflictException,
    DownstreamServiceException,
    NotFoundException,
@@ -65,6 +66,17 @@ _TERMINAL_OPERATION_STATUSES = frozenset(
# CallbackRegistration.api_family discriminator for Traffic Influence's subscriptionRequest.
_API_FAMILY = "traffic_influence"

# Blocks re-deleting an already-terminal resource (same purpose as QoD's _TERMINAL_STATES
# guard on delete_session). GET intentionally does NOT use this -- TI's own CAMARA spec
# documents 'deletion in progress'/'deleted' as visible GET states, unlike QoD.
_TERMINAL_STATES = frozenset(
    {
        RecordTrafficInfluenceState.DELETION_IN_PROGRESS,
        RecordTrafficInfluenceState.DELETED,
        RecordTrafficInfluenceState.ERROR,
    }
)


class TrafficInfluenceService:
    def __init__(
@@ -81,6 +93,14 @@ class TrafficInfluenceService:
        self._traffic_influence_repo = traffic_influence_repo
        self._callback_registration_repo = callback_registration_repo

    def _parse_traffic_influence_id(self, traffic_influence_id: str) -> UUID:
        try:
            return UUID(traffic_influence_id)
        except ValueError as exc:
            raise BadRequestException(
                message=f"Malformed traffic influence ID: {traffic_influence_id}"
            ) from exc

    def _new_operation_metadata(self, x_correlator: Optional[str]) -> tuple[UUID, str, str]:
        operation_id = uuid4()
        correlation_id = x_correlator or str(uuid4())
@@ -394,7 +414,9 @@ class TrafficInfluenceService:
        if self._traffic_influence_repo is None:
            raise RuntimeError("TrafficInfluence repository is not available")

        traffic_influence = await self._traffic_influence_repo.get_by_id(UUID(traffic_influence_id))
        traffic_influence = await self._traffic_influence_repo.get_by_id(
            self._parse_traffic_influence_id(traffic_influence_id)
        )
        if traffic_influence is None:
            raise NotFoundException(message=f"Traffic influence {traffic_influence_id} not found")

@@ -451,8 +473,10 @@ class TrafficInfluenceService:
        if self._operation_repo is None or self._traffic_influence_repo is None:
            raise RuntimeError("Operation/TrafficInfluence repositories are not available")

        traffic_influence = await self._traffic_influence_repo.get_by_id(UUID(traffic_influence_id))
        if traffic_influence is None:
        traffic_influence = await self._traffic_influence_repo.get_by_id(
            self._parse_traffic_influence_id(traffic_influence_id)
        )
        if traffic_influence is None or traffic_influence.state in _TERMINAL_STATES:
            raise NotFoundException(message=f"Traffic influence {traffic_influence_id} not found")

        operation_id, correlation_id, requested_at = self._new_operation_metadata(x_correlator)
+27 −0
Changes for tests/unit/test_traffic_influence_flows.py: 27 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -252,6 +252,12 @@ class TestTrafficInfluenceGetFlow:
        response = api_client.get(f"{TI_BASE}/traffic-influences/{uuid4()}")
        assert response.status_code == 404

    def test_get_traffic_influence_returns_400_for_malformed_id(
        self, api_client: TestClient
    ) -> None:
        response = api_client.get(f"{TI_BASE}/traffic-influences/not-a-uuid")
        assert response.status_code == 400

    def test_list_traffic_influences_returns_empty_by_default(self, api_client: TestClient) -> None:
        response = api_client.get(f"{TI_BASE}/traffic-influences")
        assert response.status_code == 200
@@ -281,6 +287,27 @@ class TestTrafficInfluenceDeleteFlow:
        response = api_client.delete(f"{TI_BASE}/traffic-influences/{uuid4()}")
        assert response.status_code == 404

    def test_delete_returns_400_for_malformed_id(self, api_client: TestClient) -> None:
        response = api_client.delete(f"{TI_BASE}/traffic-influences/not-a-uuid")
        assert response.status_code == 400

    def test_delete_returns_404_when_already_in_progress(
        self, api_client: TestClient, fake_bus: FakeDataBus
    ) -> None:
        """A repeat DELETE on a resource already being torn down must not re-publish
        another deactivate command (same guard as QoD's delete_session)."""
        traffic_influence_id = api_client.post(
            f"{TI_BASE}/traffic-influences", json=TI_BODY
        ).json()["trafficInfluenceID"]
        first = api_client.delete(f"{TI_BASE}/traffic-influences/{traffic_influence_id}")
        assert first.status_code == 202

        second = api_client.delete(f"{TI_BASE}/traffic-influences/{traffic_influence_id}")

        assert second.status_code == 404
        deactivates = [p for s, p in fake_bus.published if s == Subject.TASK_DEACTIVATE]
        assert len(deactivates) == 1

    async def test_delete_publishes_deactivate_command_once_available(
        self,
        api_client: TestClient,