安全に使えるユースケース
安全に使えるユースケース
Section titled “安全に使えるユースケース”Node.jsで安全に実装できるユースケースを詳しく解説します。
1. トランザクション内でのデータベース操作
Section titled “1. トランザクション内でのデータベース操作”// Prismaでのトランザクション管理async function createOrder(orderData: OrderData): Promise<Order> { return await prisma.$transaction(async (tx) => { // ✅ 安全: トランザクション内でのデータベース操作のみ const order = await tx.order.create({ data: orderData });
// ✅ 安全: 同じトランザクション内での在庫更新 for (const item of orderData.items) { await tx.inventory.update({ where: { productId: item.productId }, data: { stock: { decrement: item.quantity } }, }); }
return order; });}なぜ安全か:
- ACID特性: トランザクションのACID特性が保証される
- ロールバック: エラー時に自動的にロールバック
- 一貫性: データの一貫性が保たれる
2. 短時間の非同期処理
Section titled “2. 短時間の非同期処理”// Express.jsでの実装app.get('/users/:id', async (req, res) => { try { // ✅ 安全: 短時間の非同期処理 const user = await prisma.user.findUnique({ where: { id: parseInt(req.params.id) }, });
if (!user) { return res.status(404).json({ error: 'User not found' }); }
res.json(user); } catch (error) { res.status(500).json({ error: 'Internal server error' }); }});なぜ安全か:
- 実行時間: 短時間で完了する
- リソース使用: リソースを長時間占有しない
- エラーハンドリング: try-catchでエラーを処理できる
3. メッセージキューとの連携
Section titled “3. メッセージキューとの連携”// Bull/BullMQを使用import Queue from 'bull';
const orderQueue = new Queue('order-processing', { redis: { host: process.env.REDIS_HOST, port: parseInt(process.env.REDIS_PORT || '6379'), },});
async function createOrder(orderData: OrderData): Promise<Order> { // ✅ 安全: トランザクション内で注文を作成 const order = await prisma.$transaction(async (tx) => { return await tx.order.create({ data: orderData }); });
// ✅ 安全: トランザクションコミット後にメッセージを送信 await orderQueue.add('process-order', { orderId: order.id, amount: orderData.amount, });
return order;}
// ワーカーで処理orderQueue.process('process-order', async (job) => { const { orderId, amount } = job.data;
// 外部APIを呼ぶ(トランザクション外) await paymentService.chargePayment(orderId, amount);});なぜ安全か:
- トランザクションコミット後: トランザクションがコミットされた後にメッセージを送信
- 一貫性: 注文が確定した後にのみメッセージが送信される
- エラーハンドリング: メッセージキューのエラーハンドリングが可能
4. キャッシュの使用
Section titled “4. キャッシュの使用”import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
async function getProduct(id: number): Promise<Product> { // ✅ 安全: キャッシュから取得を試みる const cached = await redis.get(`product:${id}`); if (cached) { return JSON.parse(cached); }
// キャッシュにない場合はデータベースから取得 const product = await prisma.product.findUnique({ where: { id }, });
if (!product) { throw new Error('Product not found'); }
// キャッシュに保存(TTL: 1時間) await redis.setex(`product:${id}`, 3600, JSON.stringify(product));
return product;}
async function updateProduct(id: number, data: Partial<Product>): Promise<Product> { // ✅ 安全: 更新時にキャッシュを無効化 const product = await prisma.product.update({ where: { id }, data, });
await redis.del(`product:${id}`);
return product;}なぜ安全か:
- 読み取り専用: キャッシュ可能な読み取り専用操作
- キャッシュ無効化: 更新時にキャッシュを無効化
- 一貫性: データの一貫性が保たれる
安全に使えるユースケースのポイント:
- トランザクション内でのデータベース操作: ACID特性が保証される
- 短時間の非同期処理: リソースを長時間占有しない
- メッセージキューとの連携: トランザクションコミット後にメッセージを送信
- キャッシュの使用: 読み取り専用操作、更新時のキャッシュ無効化
適切なユースケースの選択により、安全で信頼性の高いシステムを構築できます。