1. FHIR R5 のサブスクリプション
FHIR R5導入 トピックベースの購読 — R4 の古いメカニズムを完全に置き換えます。データが変更されたときにシステムがリアルタイムの通知を受信できるようにします。
┌──────────┐ Subscribe ┌──────────┐
│ Client │ ──────────────────▶ │ FHIR │
│ (EMR, │ │ Server │
│ app) │ ◀────────────────── │ │
│ │ Notification │ │
└──────────┘ └──────────┘
2. サブスクリプショントピック
サブスクリプショントピックの定義 「何を購読できますか?」 — イベント、トリガー、フィルターが利用可能。
{
"resourceType": "SubscriptionTopic",
"id": "topic-encounter-admission",
"url": "http://hospital.vn/fhir/SubscriptionTopic/encounter-admission",
"title": "Encounter Admission",
"status": "active",
"description": "Thông báo khi có bệnh nhân nhập viện mới",
"resourceTrigger": [
{
"description": "Encounter mới được tạo hoặc chuyển status sang in-progress",
"resource": "http://hl7.org/fhir/StructureDefinition/Encounter",
"supportedInteraction": ["create", "update"],
"queryCriteria": {
"current": "status=in-progress&class=http://terminology.hl7.org/CodeSystem/v3-ActCode|IMP",
"resultForCreate": "test-passes",
"resultForDelete": "test-fails"
}
}
],
"canFilterBy": [
{
"description": "Filter theo location (khoa)",
"resource": "Encounter",
"filterParameter": "location"
},
{
"description": "Filter theo service provider",
"resource": "Encounter",
"filterParameter": "service-provider"
}
],
"notificationShape": [
{
"resource": "Encounter",
"include": [
"Encounter:subject",
"Encounter:participant"
]
}
]
}
3. サブスクリプションリソース
{
"resourceType": "Subscription",
"id": "sub-admission-notify-001",
"status": "requested",
"topic": "http://hospital.vn/fhir/SubscriptionTopic/encounter-admission",
"reason": "Nhận thông báo nhập viện khoa Tim mạch",
"filterBy": [
{
"resourceType": "Encounter",
"filterParameter": "location",
"value": "Location/loc-cardiology"
}
],
"channelType": {
"system": "http://terminology.hl7.org/CodeSystem/subscription-channel-type",
"code": "rest-hook"
},
"endpoint": "https://ehr-app.hospital.vn/api/webhooks/fhir-notifications",
"heartbeatPeriod": 60,
"timeout": 60,
"contentType": "application/fhir+json",
"content": "id-only",
"maxCount": 10
}
チャネルの種類
| チャンネル | 説明 | ユースケース |
|---|---|---|
| レストフック | エンドポイントへのHTTP POST | サーバー間の統合 |
| ウェブソケット | WebSocket接続 | リアルタイム UI、ダッシュボード |
| 電子メール | 電子メール通知 | エンジニアへの注意喚起 |
| メッセージ。メッセージ | FHIR メッセージング ($process-message) | 統合メッセージング システム |
コンテンツレベル
| レベル | 説明 |
|---|---|
| 空の | 通知ヘッダーのみ、リソース データなし |
| ID のみ | リソース ID + タイプ、クライアントが自身を取得する |
| フルリソース | 通知内のすべてのリソースが含まれます |
4. 通知の種類
ハンドシェイク通知
サブスクリプションの作成時に送信され、エンドポイントがアクティブであることを確認します。
{
"resourceType": "Bundle",
"type": "subscription-notification",
"entry": [
{
"resource": {
"resourceType": "SubscriptionStatus",
"type": "handshake",
"subscription": {
"reference": "Subscription/sub-admission-notify-001"
},
"topic": "http://hospital.vn/fhir/SubscriptionTopic/encounter-admission",
"eventsSinceSubscriptionStart": "0"
}
}
]
}
イベントのお知らせ
{
"resourceType": "Bundle",
"type": "subscription-notification",
"entry": [
{
"resource": {
"resourceType": "SubscriptionStatus",
"type": "event-notification",
"subscription": {
"reference": "Subscription/sub-admission-notify-001"
},
"topic": "http://hospital.vn/fhir/SubscriptionTopic/encounter-admission",
"eventsSinceSubscriptionStart": "5",
"notificationEvent": [
{
"eventNumber": "5",
"focus": {
"reference": "Encounter/enc-new-001"
},
"additionalContext": [
{"reference": "Patient/patient-new-001"}
]
}
]
}
},
{
"fullUrl": "https://fhir-server.example.com/fhir/r5/Encounter/enc-new-001",
"resource": {
"resourceType": "Encounter",
"id": "enc-new-001",
"status": "in-progress"
}
}
]
}
ハートビート通知
イベントがない場合でも、サブスクリプションがアクティブであることを確認するために定期的に送信します。
5. サブスクリプションのライフサイクル
requested → active → error → off
│ │ │
│ │ └── Server tạm dừng sau nhiều lần gửi thất bại
│ └── Nhận handshake thành công
└── Client POST Subscription
6. HAPI FHIR でのサブスクリプションの練習
# 1. Kiểm tra SubscriptionTopics có sẵn
curl -s https://hapi.fhir.org/baseR5/SubscriptionTopic | jq '.entry[].resource.url'
# 2. Tạo Subscription
curl -X POST https://hapi.fhir.org/baseR5/Subscription \
-H "Content-Type: application/fhir+json" \
-d '{
"resourceType": "Subscription",
"status": "requested",
"topic": "http://example.org/FHIR/SubscriptionTopic/admission",
"channelType": {"code": "rest-hook"},
"endpoint": "https://your-webhook.example.com/fhir-notify",
"contentType": "application/fhir+json",
"content": "id-only"
}'
# 3. Kiểm tra status
curl -s https://hapi.fhir.org/baseR5/Subscription/sub-id | jq '.status'
# 4. Tạo Encounter để trigger notification
curl -X POST https://hapi.fhir.org/baseR5/Encounter \
-H "Content-Type: application/fhir+json" \
-d '{"resourceType":"Encounter","status":"in-progress","class":[{"coding":[{"code":"IMP"}]}],"subject":{"reference":"Patient/123"}}'
7. まとめ
サブスクリプショントピック — サーバーはサブスクライブできるイベントを定義します
定期購入 — クライアントは通知を受信するように登録し、チャネル、フィルター、コンテンツ レベルを選択します
チャンネル — レストフック (最も一般的)、WebSocket、電子メール、メッセージ
通知の種類 — ハンドシェイク、ハートビート、イベント通知
R4 の古いサブスクリプション メカニズム (基準ベース) を完全に置き換えます。