Skip to content

Commit

Permalink
(PC-32546)[API] feat: catch timeout on cinema providers
Browse files Browse the repository at this point in the history
  • Loading branch information
tconte-pass committed Nov 22, 2024
1 parent 53a6e25 commit 1ed207e
Show file tree
Hide file tree
Showing 8 changed files with 29 additions and 6 deletions.
6 changes: 4 additions & 2 deletions api/src/pcapi/core/bookings/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,11 @@ def _book_cinema_external_ticket(booking: Booking, stock: Stock, beneficiary: Us
booking=booking,
beneficiary=beneficiary,
)
except external_bookings_exceptions.ExternalBookingSoldOutError as exc:
except external_bookings_exceptions.ExternalBookingSoldOutError:
logger.exception("Could not book this offer as it's sold out.")
raise exc
raise
except external_bookings_exceptions.ExternalBookingTimeoutException:
raise
except Exception as exc:
logger.exception("Could not book external ticket: %s", exc)
raise external_bookings_exceptions.ExternalBookingException
Expand Down
2 changes: 2 additions & 0 deletions api/src/pcapi/core/external_bookings/boost/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pcapi.connectors.serialization import boost_serializers
import pcapi.core.bookings.constants as bookings_constants
import pcapi.core.bookings.models as bookings_models
from pcapi.core.external_bookings.decorators import catch_cinema_provider_request_timeout
import pcapi.core.external_bookings.models as external_bookings_models
import pcapi.core.users.models as users_models
from pcapi.utils.queue import add_to_queue
Expand Down Expand Up @@ -73,6 +74,7 @@ def cancel_booking(self, barcodes: list[str]) -> None:
request_timeout=self.request_timeout,
)

@catch_cinema_provider_request_timeout
def book_ticket(
self, show_id: int, booking: bookings_models.Booking, beneficiary: users_models.User
) -> list[external_bookings_models.Ticket]:
Expand Down
2 changes: 2 additions & 0 deletions api/src/pcapi/core/external_bookings/cds/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import pcapi.core.bookings.models as bookings_models
import pcapi.core.external_bookings.cds.constants as cds_constants
import pcapi.core.external_bookings.cds.exceptions as cds_exceptions
from pcapi.core.external_bookings.decorators import catch_cinema_provider_request_timeout
import pcapi.core.external_bookings.models as external_bookings_models
from pcapi.core.external_bookings.models import Ticket
import pcapi.core.users.models as users_models
Expand Down Expand Up @@ -289,6 +290,7 @@ def cancel_booking(self, barcodes: list[str]) -> None:
f"Error while canceling bookings :{sep}{sep.join([f'{barcode} : {error_msg}' for barcode, error_msg in cancel_errors.__root__.items()])}"
)

@catch_cinema_provider_request_timeout
def book_ticket(
self, show_id: int, booking: bookings_models.Booking, beneficiary: users_models.User
) -> list[Ticket]:
Expand Down
2 changes: 2 additions & 0 deletions api/src/pcapi/core/external_bookings/ems/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pcapi.core.bookings import models as booking_models
from pcapi.core.bookings import repository as bookings_repository
from pcapi.core.external_bookings import models as external_bookings_models
from pcapi.core.external_bookings.decorators import catch_cinema_provider_request_timeout
from pcapi.core.external_bookings.exceptions import ExternalBookingSoldOutError
from pcapi.core.users import models as users_models
from pcapi.models.feature import FeatureToggle
Expand Down Expand Up @@ -46,6 +47,7 @@ def get_ticket(self, token: str) -> list[external_bookings_models.Ticket]:
for ticket in content.billets
]

@catch_cinema_provider_request_timeout
def book_ticket(
self, show_id: int, booking: booking_models.Booking, beneficiary: users_models.User
) -> list[external_bookings_models.Ticket]:
Expand Down
2 changes: 1 addition & 1 deletion api/src/pcapi/core/offers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,7 @@ def get_shows_remaining_places_from_provider(provider_class: str | None, offer:

def _should_try_to_update_offer_stock_quantity(offer: models.Offer) -> bool:
# The offer is to update only if it is a cinema offer, and if the venue has a cinema provider
if not offer.subcategory.id == subcategories.SEANCE_CINE.id:
if offer.subcategory.id != subcategories.SEANCE_CINE.id:
return False

if not offer.lastProviderId: # Manual offer
Expand Down
2 changes: 2 additions & 0 deletions api/src/pcapi/routes/native/v1/bookings.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ def book_offer(user: User, body: BookOfferRequest) -> BookOfferResponse:
extra={"offer_id": stock.offer.id, "provider_id": stock.offer.lastProviderId},
)
raise ApiErrors({"code": "CINEMA_PROVIDER_INACTIVE"})
except external_bookings_exceptions.ExternalBookingTimeoutException:
raise ApiErrors({"code": "PROVIDER_BOOKING_TIMEOUT"})
except external_bookings_exceptions.ExternalBookingException as error:
if stock.offer.lastProvider.hasProviderEnableCharlie:
logger.info(
Expand Down
6 changes: 3 additions & 3 deletions api/tests/core/bookings/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ def test_timeout_during_ems_external_booking_trigger_a_cancel_call(
url = EMSBookingConnector()._build_url("VENTE", payload)
booking_adapter = requests_mock.post(url=re.compile(rf"{url}"), exc=exception)

with pytest.raises(external_bookings_exceptions.ExternalBookingException):
with pytest.raises(external_bookings_exceptions.ExternalBookingTimeoutException):
api.book_offer(beneficiary=beneficiary, stock_id=stock.id, quantity=1)

assert not Booking.query.all()
Expand Down Expand Up @@ -700,7 +700,7 @@ def test_we_dont_cancel_too_early_failing_booking(
url = EMSBookingConnector()._build_url("VENTE", payload)
booking_adapter = requests_mock.post(url=re.compile(rf"{url}"), exc=exception)

with pytest.raises(external_bookings_exceptions.ExternalBookingException):
with pytest.raises(external_bookings_exceptions.ExternalBookingTimeoutException):
api.book_offer(beneficiary=beneficiary, stock_id=stock.id, quantity=1)

assert not Booking.query.all()
Expand Down Expand Up @@ -781,7 +781,7 @@ def test_timeout_during_ems_external_booking_dont_do_anything_if_ff_deactivated(
url = EMSBookingConnector()._build_url("VENTE", payload)
booking_adapter = requests_mock.post(url=re.compile(rf"{url}"), exc=exception)

with pytest.raises(external_bookings_exceptions.ExternalBookingException):
with pytest.raises(external_bookings_exceptions.ExternalBookingTimeoutException):
api.book_offer(beneficiary=beneficiary, stock_id=stock.id, quantity=1)

assert not Booking.query.all()
Expand Down
13 changes: 13 additions & 0 deletions api/tests/routes/native/v1/bookings_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from pcapi.core.bookings.models import BookingCancellationReasons
from pcapi.core.bookings.models import BookingStatus
from pcapi.core.categories import subcategories_v2 as subcategories
from pcapi.core.external_bookings.exceptions import ExternalBookingTimeoutException
from pcapi.core.external_bookings.factories import ExternalBookingFactory
from pcapi.core.finance import utils as finance_utils
from pcapi.core.geography.factories import AddressFactory
Expand Down Expand Up @@ -124,6 +125,18 @@ def test_inactive_provider(self, mocked_book_offer, client):
assert response.status_code == 400
assert response.json["code"] == "CINEMA_PROVIDER_INACTIVE"

@patch("pcapi.core.bookings.api.book_offer")
def test_provider_timeout(self, mocked_book_offer, client):
users_factories.BeneficiaryGrant18Factory(email=self.identifier)
stock = offers_factories.EventStockFactory()
mocked_book_offer.side_effect = ExternalBookingTimeoutException()

client = client.with_token(self.identifier)
response = client.post("/native/v1/bookings", json={"stockId": stock.id, "quantity": 1})

assert response.status_code == 400
assert response.json["code"] == "PROVIDER_BOOKING_TIMEOUT"

@pytest.mark.parametrize(
"subcategoryId,price",
[(subcategoryId, 0) for subcategoryId in offer_models.Stock.AUTOMATICALLY_USED_SUBCATEGORIES],
Expand Down

0 comments on commit 1ed207e

Please sign in to comment.