Skip to content

非同期ジョブ・通知アーキテクチャ設計

本ドキュメントは、TASHIKAプラットフォームの非同期ジョブ基盤、通知配信アーキテクチャ、およびメール配信基盤(SendGrid)の設計を定義します。

→ 満たす要件: DM-902 NotificationDM-903 AsyncJobDM-904 NotificationTemplate


非同期ジョブ基盤

技術選定

項目Hangfire + PostgreSQLQuartz.NET自前実装
セットアップ容易性◎ NuGet + 数行の設定○ やや設定が多い× フルスクラッチ
ダッシュボード◎ 組み込み Web UI× なし(別途構築)× なし
リトライ・DLQ◎ 組み込み○ 自前設定× フルスクラッチ
PostgreSQL 対応Hangfire.PostgreSql◎ ネイティブ○ テーブル設計から
ジョブの可視性◎ 状態遷移が明確△ ログベース× 自前実装
コミュニティ◎ 活発◎ 活発
選定採用

選定理由: Hangfire は PostgreSQL をバックエンドとして使用でき、追加のインフラ(Redis 等)が不要。組み込みダッシュボードでジョブ監視を低コストで実現できる。

アーキテクチャ構成図

クライアントApplication Server (Cloud Run)Hangfire ServerPostgreSQL監視API リクエスト定期実行トリガーCommand / Event HandlerHangfire Clientcritical キューワーカー数: 5default キューワーカー数: 10bulk キューワーカー数: 3scheduled キューワーカー数: 2Hangfire Dashboard/system/jobsHangfire Job Storeジョブ状態管理Application DBCloud Monitoringキュー滞留アラート
クライアントApplication Server (Cloud Run)Hangfire ServerPostgreSQL監視API リクエスト定期実行トリガーCommand / Event HandlerHangfire Clientcritical キューワーカー数: 5default キューワーカー数: 10bulk キューワーカー数: 3scheduled キューワーカー数: 2Hangfire Dashboard/system/jobsHangfire Job Storeジョブ状態管理Application DBCloud Monitoringキュー滞留アラート

ジョブカテゴリとキュー設計

キュー名ワーカー数用途
critical5即時性が求められる通知パスワードリセット、インシデント通知
default10通常の非同期処理リマインドメール、差し戻し通知、承認完了通知
bulk3大量処理バッチPDF 一括生成、一括税額計算、一括メール配信
scheduled2定期実行ジョブリマインドスケジュール、監査ログエクスポート、ハッシュチェーン検証

リトライ・DLQ 設計

設定説明
最大リトライ回数5Exponential Backoff(1分, 5分, 25分, 2時間, 10時間)
バックオフ方式Exponentialdelay = base × 5^attempt
DLQ (Failed キュー)自動移動最大リトライ超過後に Failed 状態に遷移
Failed ジョブ保持期間30日ダッシュボードから手動リトライ可能
成功ジョブ保持期間7日ダッシュボードでの確認用

ジョブ監視

  • Hangfire Dashboard を /system/jobs に統合(sys_admin ロールのみアクセス可)
  • ダッシュボードの認証は ASP.NET Core の認可ポリシーで制御
  • キュー別のジョブ滞留数を Cloud Monitoring にエクスポートし、閾値超過でアラート:
    • critical キュー: 滞留 > 10件 → Sev3
    • default キュー: 滞留 > 100件 → Sev4
    • bulk キュー: 滞留 > 50件 → Sev4
    • Failed ジョブ: > 0件 → Sev4(日次通知)

将来拡張: Cloud Pub/Sub

以下の条件を満たした場合に Cloud Pub/Sub への移行を検討する:

  • 複数のマイクロサービスへの分割が決定した場合
  • ジョブの処理量が単一インスタンスの処理能力を超えた場合(目安: 10,000 ジョブ/時 超)
  • イベント駆動アーキテクチャへの移行が決定した場合

通知配信アーキテクチャ

通知フロー概要

alt [Email チャネル][Teams チャネル][Slack チャネル][システム内通知]通知リクエストテンプレート選択(受信者の preferred_locale)レンダリング済み本文ジョブ登録ジョブ実行配信ステータス: sendingSendGrid API 送信delivered / bounceGraph API 送信送信結果chat.postMessage送信結果DB 保存配信ステータス更新トリガー(操作 / Recurring Job)NotificationHandlerScriban テンプレートHangfire キューチャネルルーターSendGrid (Email)Microsoft Graph (Teams)Slack Web APIシステム内通知 (DB)Notification (DM-902)
alt [Email チャネル][Teams チャネル][Slack チャネル][システム内通知]通知リクエストテンプレート選択(受信者の preferred_locale)レンダリング済み本文ジョブ登録ジョブ実行配信ステータス: sendingSendGrid API 送信delivered / bounceGraph API 送信送信結果chat.postMessage送信結果DB 保存配信ステータス更新トリガー(操作 / Recurring Job)NotificationHandlerScriban テンプレートHangfire キューチャネルルーターSendGrid (Email)Microsoft Graph (Teams)Slack Web APIシステム内通知 (DB)Notification (DM-902)

チャネル実装

チャネルフェーズ実装方式備考
EmailMVPSendGrid C# SDK詳細は後述の「SendGrid メール基盤設計」参照
TeamsMVPMicrosoft Graph APIテナント別の OAuth 連携
Slackv1.1Slack Web API (chat.postMessage)Webhook URL をテナント設定で管理
LINE WORKSv1.1LINE WORKS Bot API日本市場向け
システム内通知MVPPostgreSQL + TanStack Query polling未読バッジ表示、既読管理

テンプレートエンジン

選定: Scriban(Liquid 互換)

  • Liquid 互換のテンプレート構文で、非エンジニアでも編集しやすい
  • .NET ネイティブで高速(Razor よりサンドボックス性が高い)
  • テンプレートは DB(DM-904 NotificationTemplate)に保存し、管理画面から編集可能

多言語自動選択:

  1. 受信者の言語設定(Employee.preferred_locale)を取得
  2. 該当言語のテンプレートバリアントを選択
  3. フォールバック: jaen → テンプレートのデフォルト言語

通知スケジュール

項目設定
実行方式Hangfire Recurring Job
リマインド間隔企業設定で定義(デフォルト: 3日, 5日, 7日)
送信時間帯9:00〜18:00 JST(時間外に到達したジョブは翌営業日 9:00 に遅延)
エスカレーション最終リマインド後、未提出者一覧を企業管理者にメール通知
一括配信制限1バッチあたり最大 500件(SendGrid レート制限に合わせて分割)

SendGrid メール基盤設計

認証・送信ドメイン設定

設定説明
SPFinclude:sendgrid.net送信元 IP の認証
DKIMSendGrid 提供の CNAME レコードメール本文の署名検証
DMARCp=quarantine; rua=...SPF/DKIM 失敗時のポリシー
Return-Pathbounces@mail.tashika.exampleバウンスメールの受信先
From ドメインnoreply@tashika.example送信元アドレス

バウンスハンドリング

イベント対応説明
Hard Bounce配信停止宛先アドレスを undeliverable としてマーク。管理者に通知
Soft Bounce3回リトライ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名100200
Medium101〜1,000名5001,000
Large1,001名〜2,0004,000

繁忙期: 1月1日〜1月31日は上限を2倍に引き上げ。SendGrid のサブユーザー機能でテナント別の送信量を管理。

メール種別

メール種別トリガーキューテンプレート ID 例多言語
リマインド(未提出)Hangfire Recurring Jobdefaultreminder_unsubmitted7言語
差し戻し通知管理者操作defaultdeclaration_returned7言語
承認完了通知管理者操作defaultdeclaration_approved7言語
パスワードリセットユーザー操作criticalpassword_reset7言語
招待メール管理者操作defaultemployee_invitation7言語
インシデント通知システム検出criticalsecurity_incident日本語のみ
エスカレーションHangfire Recurring Jobdefaultescalation_admin日本語のみ

送信ログ保持

  • 全送信ログは Notification(DM-902)に記録
  • 保持期間の二層構造: 配信メタデータ(宛先ハッシュ、テンプレート ID、送信日時、配信ステータス、チャネル種別)= 7年(→ CR-010 監査ログ保持 準拠)。メール本文・通知本文 = 90日後に削除(個人情報最小化・プライバシー保護)