FastAPI特有の落とし穴
FastAPI特有の落とし穴
Section titled “FastAPI特有の落とし穴”FastAPI特有の落とし穴と、他言語との違いを詳しく解説します。
1. トランザクション境界は明示的か?
Section titled “1. トランザクション境界は明示的か?”FastAPIのトランザクション管理
Section titled “FastAPIのトランザクション管理”特徴:
# FastAPI: 明示的なトランザクション境界from sqlalchemy.orm import Session
async def create_order(db: Session, order_data: OrderData) -> Order: order = Order(**order_data.dict()) db.add(order) db.commit() # 明示的なコミット return order他言語との比較:
// Java: 宣言的トランザクション管理@Transactionalpublic Order createOrder(OrderData orderData) { Order order = orderRepository.save(new Order(orderData)); return order;}落とし穴:
- トランザクションの見落とし: トランザクションを忘れると、データの整合性が保たれない
- 手動ロールバック: エラー時に手動でロールバックする必要がある
2. 非同期は信頼できるか?
Section titled “2. 非同期は信頼できるか?”FastAPIの非同期処理
Section titled “FastAPIの非同期処理”特徴:
# FastAPI: async/awaitによる非同期処理@app.post("/orders")async def create_order(order_data: OrderData): async with httpx.AsyncClient() as client: response = await client.post("https://api.example.com/charge", json=order_data.dict()) return response.json()他言語との比較:
// Node.js: Promise/async-awaitasync function createOrder(orderData: OrderData) { const response = await fetch('https://api.example.com/charge', { method: 'POST', body: JSON.stringify(orderData), }); return await response.json();}落とし穴:
- 同期処理の混在: 非同期関数内で同期I/O操作を使用すると、イベントループがブロックされる
- エラーハンドリング: 適切なエラーハンドリングが必要
3. 再実行される前提か?
Section titled “3. 再実行される前提か?”FastAPIの再実行
Section titled “FastAPIの再実行”特徴:
# FastAPI: 再実行は手動で実装する必要があるfrom tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))async def charge_payment(order_id: int, amount: float): async with httpx.AsyncClient() as client: response = await client.post("https://payment-api.example.com/charge", json={ "orderId": order_id, "amount": amount, }) return response.json()他言語との比較:
// Java: @Retryableアノテーションで自動リトライ@Retryable(maxAttempts = 3)public PaymentResult chargePayment(Long orderId) { return paymentApiClient.chargePayment(orderId);}落とし穴:
- 再実行の実装漏れ: 再実行ロジックを実装し忘れると、一時的なエラーで処理が失敗する
- 冪等性の確保: 再実行時に冪等性を確保する必要がある
4. after_commit的な逃げ道があるか?
Section titled “4. after_commit的な逃げ道があるか?”FastAPIのトランザクションコミット後処理
Section titled “FastAPIのトランザクションコミット後処理”特徴:
# FastAPI: トランザクションコミット後の処理は手動で実装from sqlalchemy.orm import Sessionfrom sqlalchemy import event
async def create_order(db: Session, order_data: OrderData) -> Order: order = Order(**order_data.dict()) db.add(order) db.commit()
# トランザクションコミット後に外部APIを呼ぶ asyncio.create_task(charge_payment(order.id, order_data.amount))
return order他言語との比較:
# Ruby (Rails): after_commitコールバックclass Order < ApplicationRecord after_commit :call_external_api
def call_external_api ExternalApi.call(self.id) endend落とし穴:
- トランザクションコミット後の処理: トランザクションコミット後の処理が失敗した場合、ロールバックできない
- 一貫性の保証: トランザクションコミット後の処理が失敗した場合、データの不整合が発生する可能性がある
FastAPI特有の落とし穴のポイント:
- トランザクション境界: 明示的なトランザクション境界、見落としに注意
- 非同期処理: async/awaitによる非同期処理、同期処理の混在に注意
- 再実行: 手動で実装する必要がある、冪等性の確保が必要
- after_commit的な逃げ道: トランザクションコミット後の処理は手動で実装、一貫性の保証が必要
これらの落とし穴を理解することで、より安全なFastAPIアプリケーションを構築できます。