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 6, 2024
1 parent dec93cf commit 2f6d929
Show file tree
Hide file tree
Showing 8 changed files with 29 additions and 3 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/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from pcapi.core.external_bookings.boost.client import BoostClientAPI
from pcapi.core.external_bookings.cds.client import CineDigitalServiceAPI
from pcapi.core.external_bookings.cgr.client import CGRClientAPI
from pcapi.core.external_bookings.decorators import catch_cinema_provider_request_timeout
from pcapi.core.external_bookings.ems.client import EMSClientAPI
import pcapi.core.external_bookings.models as external_bookings_models
from pcapi.core.external_bookings.models import Ticket
Expand Down Expand Up @@ -103,6 +104,7 @@ def get_active_cinema_venue_provider(venue_id: int) -> providers_models.VenuePro
return cinema_venue_provider


@catch_cinema_provider_request_timeout
def book_event_ticket(
booking: bookings_models.Booking,
stock: offers_models.Stock,
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 @@ -68,6 +69,7 @@ def cancel_booking(self, barcodes: list[str]) -> None:
sale_cancel = boost_serializers.SaleCancel(sales=sale_cancel_items)
boost.put_resource(self.cinema_id, boost.ResourceBoost.CANCEL_ORDER_SALE, sale_cancel)

@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
3 changes: 3 additions & 0 deletions api/src/pcapi/core/external_bookings/cds/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
from pcapi.core.bookings.constants import REDIS_EXTERNAL_BOOKINGS_NAME
from pcapi.core.bookings.constants import RedisExternalBookingType
import pcapi.core.bookings.models as bookings_models
from pcapi.utils.requests import exceptions as requests_exception
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 @@ -242,6 +244,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 @@ -1390,7 +1390,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
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 2f6d929

Please sign in to comment.