非同期ジョブ・通知アーキテクチャ設計
本ドキュメントは、TASHIKAプラットフォームの非同期ジョブ基盤、通知配信アーキテクチャ、およびメール配信基盤(SendGrid)の設計を定義します。
→ 満たす要件: DM-902 Notification、DM-903 AsyncJob、DM-904 NotificationTemplate
非同期ジョブ基盤
技術選定
| 項目 | Hangfire + PostgreSQL | Quartz.NET | 自前実装 |
|---|---|---|---|
| セットアップ容易性 | ◎ NuGet + 数行の設定 | ○ やや設定が多い | × フルスクラッチ |
| ダッシュボード | ◎ 組み込み Web UI | × なし(別途構築) | × なし |
| リトライ・DLQ | ◎ 組み込み | ○ 自前設定 | × フルスクラッチ |
| PostgreSQL 対応 | ◎ Hangfire.PostgreSql | ◎ ネイティブ | ○ テーブル設計から |
| ジョブの可視性 | ◎ 状態遷移が明確 | △ ログベース | × 自前実装 |
| コミュニティ | ◎ 活発 | ◎ 活発 | — |
| 選定 | 採用 | — | — |
選定理由: Hangfire は PostgreSQL をバックエンドとして使用でき、追加のインフラ(Redis 等)が不要。組み込みダッシュボードでジョブ監視を低コストで実現できる。
アーキテクチャ構成図
ジョブカテゴリとキュー設計
| キュー名 | ワーカー数 | 用途 | 例 |
|---|---|---|---|
critical | 5 | 即時性が求められる通知 | パスワードリセット、インシデント通知 |
default | 10 | 通常の非同期処理 | リマインドメール、差し戻し通知、承認完了通知 |
bulk | 3 | 大量処理バッチ | PDF 一括生成、一括税額計算、一括メール配信 |
scheduled | 2 | 定期実行ジョブ | リマインドスケジュール、監査ログエクスポート、ハッシュチェーン検証 |
リトライ・DLQ 設計
| 設定 | 値 | 説明 |
|---|---|---|
| 最大リトライ回数 | 5 | Exponential Backoff(1分, 5分, 25分, 2時間, 10時間) |
| バックオフ方式 | Exponential | delay = base × 5^attempt |
| DLQ (Failed キュー) | 自動移動 | 最大リトライ超過後に Failed 状態に遷移 |
| Failed ジョブ保持期間 | 30日 | ダッシュボードから手動リトライ可能 |
| 成功ジョブ保持期間 | 7日 | ダッシュボードでの確認用 |
ジョブ監視
- Hangfire Dashboard を
/system/jobsに統合(sys_adminロールのみアクセス可) - ダッシュボードの認証は ASP.NET Core の認可ポリシーで制御
- キュー別のジョブ滞留数を Cloud Monitoring にエクスポートし、閾値超過でアラート:
criticalキュー: 滞留 > 10件 → Sev3defaultキュー: 滞留 > 100件 → Sev4bulkキュー: 滞留 > 50件 → Sev4- Failed ジョブ: > 0件 → Sev4(日次通知)
将来拡張: Cloud Pub/Sub
以下の条件を満たした場合に Cloud Pub/Sub への移行を検討する:
- 複数のマイクロサービスへの分割が決定した場合
- ジョブの処理量が単一インスタンスの処理能力を超えた場合(目安: 10,000 ジョブ/時 超)
- イベント駆動アーキテクチャへの移行が決定した場合
通知配信アーキテクチャ
通知フロー概要
チャネル実装
| チャネル | フェーズ | 実装方式 | 備考 |
|---|---|---|---|
| MVP | SendGrid C# SDK | 詳細は後述の「SendGrid メール基盤設計」参照 | |
| Teams | MVP | Microsoft Graph API | テナント別の OAuth 連携 |
| Slack | v1.1 | Slack Web API (chat.postMessage) | Webhook URL をテナント設定で管理 |
| LINE WORKS | v1.1 | LINE WORKS Bot API | 日本市場向け |
| システム内通知 | MVP | PostgreSQL + TanStack Query polling | 未読バッジ表示、既読管理 |
テンプレートエンジン
選定: Scriban(Liquid 互換)
- Liquid 互換のテンプレート構文で、非エンジニアでも編集しやすい
- .NET ネイティブで高速(Razor よりサンドボックス性が高い)
- テンプレートは DB(DM-904 NotificationTemplate)に保存し、管理画面から編集可能
多言語自動選択:
- 受信者の言語設定(
Employee.preferred_locale)を取得 - 該当言語のテンプレートバリアントを選択
- フォールバック:
ja→en→ テンプレートのデフォルト言語
通知スケジュール
| 項目 | 設定 |
|---|---|
| 実行方式 | Hangfire Recurring Job |
| リマインド間隔 | 企業設定で定義(デフォルト: 3日, 5日, 7日) |
| 送信時間帯 | 9:00〜18:00 JST(時間外に到達したジョブは翌営業日 9:00 に遅延) |
| エスカレーション | 最終リマインド後、未提出者一覧を企業管理者にメール通知 |
| 一括配信制限 | 1バッチあたり最大 500件(SendGrid レート制限に合わせて分割) |
SendGrid メール基盤設計
認証・送信ドメイン設定
| 設定 | 値 | 説明 |
|---|---|---|
| SPF | include:sendgrid.net | 送信元 IP の認証 |
| DKIM | SendGrid 提供の CNAME レコード | メール本文の署名検証 |
| DMARC | p=quarantine; rua=... | SPF/DKIM 失敗時のポリシー |
| Return-Path | bounces@mail.tashika.example | バウンスメールの受信先 |
| From ドメイン | noreply@tashika.example | 送信元アドレス |
バウンスハンドリング
| イベント | 対応 | 説明 |
|---|---|---|
| Hard Bounce | 配信停止 | 宛先アドレスを undeliverable としてマーク。管理者に通知 |
| Soft Bounce | 3回リトライ | Exponential Backoff(1時間, 6時間, 24時間)でリトライ。3回失敗後は配信停止 |
| Spam Complaint | 配信停止 + 調査 | 該当アドレスへの配信を即時停止。Sev3 アラート発報 |
| Invalid Email | 配信停止 | バリデーション強化のためログ記録 |
| Unsubscribe | 配信停止 | 法的要件に基づく即時停止(CAN-SPAM / 特電法) |
SendGrid Event Webhook
- エンドポイント:
POST /api/v1/webhooks/sendgrid/events - 認証: ECDSA 署名検証(SendGrid の Event Webhook Verification Key を使用)
- 処理対象イベント:
delivered,bounce,dropped,spam_report,unsubscribe,open,click - イベントは Notification(DM-902)に記録し、配信ステータスを更新
テナント別レート制限
| テナント規模 | 従業員数 | 通常期上限 (件/時) | 繁忙期上限 (件/時) | 説明 |
|---|---|---|---|---|
| Small | 〜100名 | 100 | 200 | |
| Medium | 101〜1,000名 | 500 | 1,000 | |
| Large | 1,001名〜 | 2,000 | 4,000 |
繁忙期: 1月1日〜1月31日は上限を2倍に引き上げ。SendGrid のサブユーザー機能でテナント別の送信量を管理。
メール種別
| メール種別 | トリガー | キュー | テンプレート ID 例 | 多言語 |
|---|---|---|---|---|
| リマインド(未提出) | Hangfire Recurring Job | default | reminder_unsubmitted | 7言語 |
| 差し戻し通知 | 管理者操作 | default | declaration_returned | 7言語 |
| 承認完了通知 | 管理者操作 | default | declaration_approved | 7言語 |
| パスワードリセット | ユーザー操作 | critical | password_reset | 7言語 |
| 招待メール | 管理者操作 | default | employee_invitation | 7言語 |
| インシデント通知 | システム検出 | critical | security_incident | 日本語のみ |
| エスカレーション | Hangfire Recurring Job | default | escalation_admin | 日本語のみ |
送信ログ保持
- 全送信ログは Notification(DM-902)に記録
- 保持期間の二層構造: 配信メタデータ(宛先ハッシュ、テンプレート ID、送信日時、配信ステータス、チャネル種別)= 7年(→ CR-010 監査ログ保持 準拠)。メール本文・通知本文 = 90日後に削除(個人情報最小化・プライバシー保護)