AWS SQS FIFO + Lambda による Prepare-Challenge パターン実装ガイド

# AWS SQS FIFO + Lambda による Prepare-Challenge パターン実装ガイド

## 1. 概要

非同期処理を確実に完了させるPrepare-Challengeパターンを、AWS SQS FIFO（First-In-First-Out）キューとLambdaを使って実装するためのガイドです。

### 1.1 パターンの目的

- 外部システムとの非同期処理を確実に完了
- 処理の順序性を保証
- システム負荷の制御
- 処理状態の追跡容易性

### 1.2 AWS サービスの選定理由

- **SQS FIFO**
  - メッセージの厳密な順序保証
  - 重複排除機能
  - メッセージグループによる並列処理の制御
  - デッドレターキュー（DLQ）によるエラー処理

- **Lambda**
  - サーバーレスでの柔軟なスケーリング
  - SQSとの統合が容易
  - コスト効率の良い実行環境
  - 監視・ログ収集の容易さ

## 2. キュー設計パターン

### 2.1 優先度別キューの構成

#### 高優先度キュー
```typescript
const highPriorityQueue = new sqs.Queue(this, 'HighPriorityQueue', {
  fifo: true,
  contentBasedDeduplication: true,
  retentionPeriod: Duration.minutes(15),
  visibilityTimeout: Duration.seconds(30)
});
```
- 即時処理が必要な重要な業務処理用
- 短い保持期間と可視性タイムアウト
- 1メッセージずつの即時処理

#### 標準優先度キュー
```typescript
const standardPriorityQueue = new sqs.Queue(this, 'StandardPriorityQueue', {
  fifo: true,
  contentBasedDeduplication: true,
  retentionPeriod: Duration.hours(1),
  visibilityTimeout: Duration.seconds(30)
});
```
- 通常の業務処理用
- 適度な保持期間
- バッチサイズによる効率的な処理

#### 低優先度キュー
```typescript
const lowPriorityQueue = new sqs.Queue(this, 'LowPriorityQueue', {
  fifo: true,
  contentBasedDeduplication: true,
  retentionPeriod: Duration.hours(2),
  visibilityTimeout: Duration.seconds(60)
});
```
- バッチ処理など、時間的余裕のある処理用
- 長めの保持期間と可視性タイムアウト
- 大きめのバッチサイズでの処理

### 2.2 共通の設定ポイント

1. **コンテンツベースの重複排除**
   - `contentBasedDeduplication: true`
   - メッセージ本体に基づく自動的な重複排除
   - 5分間の重複排除ウィンドウ

2. **デッドレターキュー（DLQ）**
   ```typescript
   deadLetterQueue: {
     queue: dlqQueue,
     maxReceiveCount: 3
   }
   ```
   - 失敗メッセージの分離
   - 再処理ポリシーの設定
   - 長期の保持期間設定

3. **メッセージグループID**
   - 同一処理グループ内での順序保証
   - 業務単位での並列処理制御

## 3. Lambda Trigger設定

### 3.1 基本設定

```typescript
const eventSource = new lambdaEventSources.SqsEventSource(queue, {
  batchSize: 10,
  maxBatchingWindow: Duration.seconds(5),
  reportBatchItemFailures: true
});
```

### 3.2 優先度別の設定例

#### 高優先度キューのトリガー
```typescript
{
  batchSize: 1,
  maxBatchingWindow: Duration.seconds(0),
  reportBatchItemFailures: true
}
```

#### 標準優先度キューのトリガー
```typescript
{
  batchSize: 5,
  maxBatchingWindow: Duration.seconds(5),
  reportBatchItemFailures: true
}
```

#### 低優先度キューのトリガー
```typescript
{
  batchSize: 10,
  maxBatchingWindow: Duration.seconds(10),
  reportBatchItemFailures: true
}
```

## 4. メッセージ送信パターン

### 4.1 基本的なメッセージ構造

```typescript
interface PrepareChallengeMessage {
  processType: string;
  priority: 'HIGH' | 'STANDARD' | 'LOW';
  requestId: string;
  timestamp: string;
  payload: {
    [key: string]: any;
  };
  metadata?: {
    retryCount?: number;
    originalTimestamp?: string;
  };
}
```

### 4.2 送信パラメーター例

```typescript
const sendParams = {
  QueueUrl: queueUrl,
  MessageBody: JSON.stringify(message),
  MessageGroupId: groupId,
  MessageDeduplicationId: deduplicationId
};
```

### 4.3 メッセージグループIDの設定パターン

1. **注文処理の場合**
   ```typescript
   MessageGroupId: `ORDER_${orderId}`
   ```
   - 同一注文の順序性保証

2. **顧客単位の処理の場合**
   ```typescript
   MessageGroupId: `CUSTOMER_${customerId}`
   ```
   - 同一顧客の処理順序保証

3. **バッチ処理の場合**
   ```typescript
   MessageGroupId: `BATCH_${batchType}`
   ```
   - 同種バッチの順序性保証

## 5. エラーハンドリング

### 5.1 Lambda側の実装

```typescript
export const handler = async (event: SQSEvent) => {
  const batchItemFailures: { itemIdentifier: string }[] = [];

  for (const record of event.Records) {
    try {
      const success = await processMessage(record);
      if (!success) {
        batchItemFailures.push({ 
          itemIdentifier: record.messageId 
        });
      }
    } catch (error) {
      batchItemFailures.push({ 
        itemIdentifier: record.messageId 
      });
    }
  }

  return { batchItemFailures };
};
```

### 5.2 再処理戦略

1. **Prepare Phase失敗時**
   - 同一キューの後方に再エンキュー
   - バックオフ時間の設定
   - 最大再試行回数の管理

2. **Challenge Phase失敗時**
   - DLQへの移動
   - アラート通知
   - 手動再処理の検討

## 6. モニタリングと運用

### 6.1 CloudWatchメトリクス

- キューの深さ
- 処理遅延時間
- エラー率
- DLQメッセージ数

### 6.2 アラート設定

```typescript
new cloudwatch.Alarm(this, 'DLQAlarm', {
  metric: dlqQueue.metricApproximateNumberOfMessagesVisible(),
  threshold: 1,
  evaluationPeriods: 1,
  alarmDescription: 'Messages in DLQ detected'
});
```

### 6.3 運用上の注意点

1. **キャパシティ管理**
   - FIFOキューの制限（1秒あたり300メッセージ）
   - Lambda同時実行数の制限
   - メモリ使用量の監視

2. **コスト最適化**
   - バッチサイズの適切な設定
   - Lambda実行時間の最適化
   - 保持期間の適切な設定

3. **メンテナンス性**
   - ログレベルの適切な設定
   - エラーメッセージの明確化
   - デバッグ情報の充実

## 7. ベストプラクティス

1. **設計原則**
   - 単一責任の原則を守る
   - 疎結合な設計を心がける
   - 監視可能性を確保する

2. **実装のポイント**
   - メッセージの冪等性確保
   - タイムアウト値の適切な設定
   - エラーハンドリングの徹底

3. **運用面での推奨事項**
   - 定期的なDLQの確認
   - パフォーマンスメトリクスの監視
   - キャパシティプランニングの実施