Skip to content

Commit

Permalink
Async for gathering product info, OrdersNotFound exception for empty …
Browse files Browse the repository at this point in the history
…case
  • Loading branch information
Winston-Hsiao committed Nov 18, 2024
1 parent 3153354 commit 3e77df8
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 19 deletions.
4 changes: 2 additions & 2 deletions frontend/src/components/pages/Orders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import ROUTES from "@/lib/types/routes";
const OrdersPage: React.FC = () => {
const navigate = useNavigate();
const { api, currentUser, isAuthenticated, isLoading } = useAuthentication();
const [orders, setOrders] = useState<OrderWithProduct[] | null>(null);
const [orders, setOrders] = useState<OrderWithProduct[]>([]);
const [loadingOrders, setLoadingOrders] = useState(true);
const { addErrorAlert } = useAlertQueue();

Expand Down Expand Up @@ -65,7 +65,7 @@ const OrdersPage: React.FC = () => {
<div className="flex justify-center items-center p-4 md:p-10 rounded-lg max-w-md mx-auto">
<Spinner className="p-1" />
</div>
) : orders && orders.length > 0 ? (
) : orders.length > 0 ? (
<div className="grid gap-2 md:gap-6 md:grid-cols-1 lg:grid-cols-2">
{orders.map((orderWithProduct: OrderWithProduct) => (
<OrderCard
Expand Down
10 changes: 2 additions & 8 deletions frontend/src/gen/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -869,10 +869,7 @@ export interface paths {
};
get?: never;
put?: never;
/**
* Stripe Webhook
* @description Handle direct account webhooks (non-Connect events).
*/
/** Stripe Webhook */
post: operations["stripe_webhook_stripe_webhook_post"];
delete?: never;
options?: never;
Expand All @@ -889,10 +886,7 @@ export interface paths {
};
get?: never;
put?: never;
/**
* Stripe Connect Webhook
* @description Handle Connect account webhooks.
*/
/** Stripe Connect Webhook */
post: operations["stripe_connect_webhook_stripe_connect_webhook_post"];
delete?: never;
options?: never;
Expand Down
8 changes: 7 additions & 1 deletion store/app/crud/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ class OrderDataUpdate(TypedDict):
shipping_country: NotRequired[str]


class OrdersNotFoundError(ItemNotFoundError):
"""Raised when no orders are found for a user."""

pass


class OrdersCrud(BaseCrud):
"""CRUD operations for Orders."""

Expand All @@ -63,7 +69,7 @@ async def create_order(self, order_data: OrderDataCreate) -> Order:
async def get_orders_by_user_id(self, user_id: str) -> list[Order]:
orders = await self._get_items_from_secondary_index("user_id", user_id, Order)
if not orders:
raise ItemNotFoundError("No orders found for this user")
raise OrdersNotFoundError(f"No orders found for user {user_id}")
return orders

async def get_orders_by_stripe_connect_account_id(self, stripe_connect_account_id: str) -> list[Order]:
Expand Down
1 change: 0 additions & 1 deletion store/app/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,6 @@ def create(cls, user_id: str, listing_id: str, is_upvote: bool) -> Self:
class Order(StoreBaseModel):
"""Tracks completed user orders through Stripe."""

id: str
user_id: str
listing_id: str
user_email: str
Expand Down
26 changes: 19 additions & 7 deletions store/app/routers/orders.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""Defines the router endpoints for handling Orders."""

import asyncio
from logging import getLogger

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel

from store.app.crud.base import ItemNotFoundError
from store.app.crud.orders import OrderDataUpdate
from store.app.crud.orders import OrderDataUpdate, OrdersNotFoundError
from store.app.db import Crud
from store.app.model import Order, User
from store.app.routers import stripe
Expand Down Expand Up @@ -82,18 +82,30 @@ async def get_product_info(order: Order) -> OrderWithProduct:
)
return OrderWithProduct(order=order, product=product_info)
except Exception as e:
logger.error("Error processing order", extra={"order_id": order.id, "error": str(e), "user_id": user.id})
logger.error(
"Error getting product info for order",
extra={"order_id": order.id, "error": str(e), "user_id": user.id},
)
return OrderWithProduct(order=order, product=None)

try:
orders = await crud.get_orders_by_user_id(user.id)
return [await get_product_info(order) for order in orders]
except ItemNotFoundError:
return await asyncio.gather(*[get_product_info(order) for order in orders])
except OrdersNotFoundError:
return []
except asyncio.TimeoutError:
logger.error("Timeout while fetching orders", extra={"user_id": user.id})
raise HTTPException(
status_code=status.HTTP_504_GATEWAY_TIMEOUT, detail="Request timed out while fetching orders"
)
except Exception as e:
logger.error("Error fetching user orders", extra={"user_id": user.id, "error": str(e)})
logger.error(
"Unexpected error fetching user orders",
extra={"user_id": user.id, "error": str(e), "error_type": type(e).__name__},
)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Error fetching orders: {str(e)}"
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="An unexpected error occurred while fetching orders",
)


Expand Down

0 comments on commit 3e77df8

Please sign in to comment.