Xem bản video
1. Subscriptions trong FHIR R5
FHIR R5 giới thiệu Topic-based Subscriptions — thay thế hoàn toàn cơ chế cũ của R4. Cho phép hệ thống nhận thông báo real-time khi data thay đổi.
┌──────────┐ Subscribe ┌──────────┐
│ Client │ ──────────────────▶ │ FHIR │
│ (EMR, │ │ Server │
│ app) │ ◀────────────────── │ │
│ │ Notification │ │
└──────────┘ └──────────┘
2. SubscriptionTopic
SubscriptionTopic định nghĩa "chuyện gì có thể subscribe" — events, triggers, filters có sẵn.
{
"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. Subscription Resource
{
"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
}
Channel Types
| Channel | Mô tả | Use case |
|---|---|---|
| rest-hook | HTTP POST đến endpoint | Server-to-server integration |
| websocket | WebSocket connection | Real-time UI, dashboards |
| Email notification | Alert cho clinicians | |
| message | FHIR Messaging ($process-message) | Tích hợp messaging systems |
Content Levels
| Level | Mô tả |
|---|---|
| empty | Chỉ notification header, không có resource data |
| id-only | Resource ID + type, client tự fetch |
| full-resource | Chứa đầy đủ resource trong notification |
4. Notification Types
Handshake Notification
Gửi khi subscription được tạo, xác nhận endpoint hoạt động.
{
"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"
}
}
]
}
Event Notification
{
"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"
}
}
]
}
Heartbeat Notification
Gửi định kỳ để xác nhận subscription còn hoạt động, ngay cả khi không có events.
5. Subscription Lifecycle
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. Thực hành Subscriptions trên 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. Tổng kết
SubscriptionTopic — Server định nghĩa events có thể subscribe
Subscription — Client đăng ký nhận thông báo, chọn channel, filter, content level
Channels — rest-hook (phổ biến nhất), websocket, email, message
Notification types — handshake, heartbeat, event-notification
Thay thế hoàn toàn cơ chế Subscription cũ của R4 (criteria-based)