Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion templates/eventbridge/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ def handle(self, event: EventBridgeModel) -> ApiResponse:
timeout=settings.api_timeout_seconds,
)
response.raise_for_status()
api_response = ApiResponse.model_validate(response.json())
# Optimize by using Pydantic's Rust-based JSON parser directly on the raw bytes.
# This avoids redundant dictionary creation and improves performance.
api_response = ApiResponse.model_validate_json(response.content)
self._repository.put_item(api_response.model_dump(by_alias=True, exclude_none=True))
metrics.add_metric(name="ApiCallSuccess", unit=MetricUnit.Count, value=1)
logger.info("API call succeeded", extra={"api_message": api_response.message})
Expand Down
4 changes: 3 additions & 1 deletion tests/eventbridge/test_handler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Unit tests for the EventBridge API caller handler"""

from json import dumps

from pydantic import ValidationError
from pytest import fixture, main, raises
from requests import HTTPError
Expand Down Expand Up @@ -51,7 +53,7 @@ def _valid_event() -> dict:

def _mock_response(mocker, json_data: dict, status_code: int = 200):
mock_resp = mocker.MagicMock()
mock_resp.json.return_value = json_data
mock_resp.content = dumps(json_data).encode()
mock_resp.status_code = status_code
mock_resp.raise_for_status.return_value = None
return mock_resp
Expand Down
9 changes: 5 additions & 4 deletions tests/eventbridge/test_properties.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Property-based tests for the EventBridge API caller."""

import sys
from json import dumps
from unittest.mock import MagicMock, patch

from hypothesis import HealthCheck, given
Expand Down Expand Up @@ -59,7 +60,7 @@ def test_valid_event_shapes(mocker, source, detail_type, detail) -> None:

mock_secrets.get.return_value = "test-token"
mock_resp = mocker.MagicMock()
mock_resp.json.return_value = {"id": "test-id", "message": "ok"}
mock_resp.content = dumps({"id": "test-id", "message": "ok"}).encode()
mock_resp.raise_for_status.return_value = None
mock_get.return_value = mock_resp

Expand Down Expand Up @@ -187,7 +188,7 @@ def test_bearer_token_header(mocker, token) -> None:

mock_secrets.get.return_value = token
mock_resp = mocker.MagicMock()
mock_resp.json.return_value = {"id": "test-id", "message": "ok"}
mock_resp.content = dumps({"id": "test-id", "message": "ok"}).encode()
mock_resp.raise_for_status.return_value = None
mock_get.return_value = mock_resp

Expand Down Expand Up @@ -353,7 +354,7 @@ def test_successful_response_persisted(mocker, status) -> None:

mock_secrets.get.return_value = "test-token"
mock_resp = mocker.MagicMock()
mock_resp.json.return_value = {"id": "test-id", "message": status}
mock_resp.content = dumps({"id": "test-id", "message": status}).encode()
mock_resp.raise_for_status.return_value = None
mock_get.return_value = mock_resp

Expand Down Expand Up @@ -397,7 +398,7 @@ def test_dynamodb_write_failure_propagates(mocker, exc) -> None:

mock_secrets.get.return_value = "test-token"
mock_resp = mocker.MagicMock()
mock_resp.json.return_value = {"id": "test-id", "message": "ok"}
mock_resp.content = dumps({"id": "test-id", "message": "ok"}).encode()
mock_resp.raise_for_status.return_value = None
mock_get.return_value = mock_resp
mock_repo.put_item.side_effect = exc
Expand Down