Introduction
The FHIR standard specifies a powerful mechanism for push-based notification of changes in the repository. This mechanism is called Subscription.
A Subscription is a publish-subscribe (pub/sub) mechanism built into the FHIR specification. Subscriptions are defined using the Subscription resource, which specifies what type of data is being subscribed to and how the recipient should be notified.
A simple example of a Subscription resource follows:
{
"resourceType": "Subscription",
"status": "requested",
"criteria": "Patient?name=smith",
"channel": {
"type": "rest-hook",
"endpoint": "http://example.com:8080/fhir",
"payload": "application/json"
}
}
The Subscription resource contains several important fields:
status
– When a Subscription is created by a client, it should have a status of requested
. Smile CDR will process this Subscription, and if it is valid, the status will automatically be changed to active
, meaning that the Subscription is now being processed.
criteria
– This is a FHIR search query URL that will be used to determine which resources apply to the Subscription. These resources will trigger a notification when they change. See Criteria below for more information.
channel.type
– This is the mechanism for delivery, such as rest-hook, websocket, email, sms, or message. See Channel Types for more information.
channel.endpoint
– For channel types that require the server to initiate a connection to the client, this is the URL of the endpoint to which the server should connect.
channel.payload
– This is the mimetype encoding to use (e.g. application/fhir+json
for JSON data).
channel.extension
- Providing an extension allows finer control of subscription handling. Some extensions are channel specific, while others are used to define retry handling.
To create a new Subscription, the subscription should be submitted to the server via a FHIR create operation (i.e. exactly the same way that any other resource is created).
Subscriptions should be requested by submitting the subscription in REQUESTED
state. The server will examine the subscription, and if it is able to activate it, the status will automatically be changed to ACTIVE
. Only subscription types which have been enabled on that FHIR Storage module (e.g. REST_HOOK
, EMAIL
) will be activated. All other incoming subscriptions will be left in the REQUESTED
state.
Subscriptions that fail to deliver to their specified channel will retry on error. By default, they will continue to retry indefinitely until they succeed.
Some systems can use an extension to configure a subscription with a maximum retry count.
URL | Type | Description |
---|---|---|
http://hapifhir.io/fhir/StructureDefinition/subscription-delivery-retry-count | integer | If specified, this extension defines the maximum number of retries to deliver a subscription payload to its configured channel. Retries occur with an exponential backoff strategy. Once retries are exhausted, the failing payload will be added to the message broker's default Dead Letter Queue. |
An example resource including this extension is shown below:
{
"resourceType": "Subscription",
"status": "active",
"criteria": "Patient?name=Krabappel",
"channel": {
"type": "rest-hook",
"endpoint": "http://localhost:1234/endpoint",
"payload": "application/json",
"extension": [
{
"url": "http://hapifhir.io/fhir/StructureDefinition/subscription-delivery-retry-count",
"valueInteger": "5"
}
]
}
}
Dead Letter Queues (DLQs) are used to store undeliverable messages.
If the message broker is configured to create queues/topics, they will be created when they are first needed; otherwise the queues/topics must be created ahead of time.
The name of the DLQ depends on the message broker, and is case-sensitive.
KAFKA.DLQ
for Kafka.ActiveMQ.DLQ
for ActiveMQIf delivery to the DLQ fails, then the message is dropped. Dropped messages are logged to the
logs/smile-dlq-failures.log
file for manual recovery.
Subscriptions will by default only listen to incoming resources from the same partition as the subscription. Cross-partition subscription can be enabled via the subscription.cross_partition.enabled setting, allowing subscriptions on the default partition to listen to all incoming changes. Cross-partition subscriptions will need to be distinguished using an extension on the subscription resource.
URL | Type | Description |
---|---|---|
https://smilecdr.com/fhir/ns/StructureDefinition/subscription-cross-partition | Boolean | If specified, this extension defines if the subscription is marked as cross-partition and will attempt to listen to changes to resource from all partitions. |
An example resource including this extension is shown below:
{
"resourceType": "Subscription",
"status": "requested",
"criteria": "Patient?name=smith",
"channel": {
"type": "rest-hook",
"endpoint": "http://localhost:1234/endpoint",
"payload": "application/json"
},
"extension": [ {
"url": "https://smilecdr.com/fhir/ns/StructureDefinition/subscription-cross-partition",
"valueBoolean": true
} ]
}
When any resources that match Subscription.criteria
are created or updated, the specified notification will occur. For example, if the Subscription specifies a criteria of Patient?name=smith
then a notification will occur any time a Patient named "smith" is created or updated.
Smile CDR tries to match subscription criteria against an incoming resource using only the data available within the resource. If this isn't possible, it queries the database to determine a match, either via a database call. The following subscription criteria elements are not supported by the in-memory matcher:
_id
, _lastUpdated
, _has
, _tag
, _text
, _content
, etc.eq
, gt
, etc.
date
comparisons: gt
, ge
, eq
, lt
, and le
.Patient?_has:Observation:patient:code=1234-5
Group?characteristic-value=gender$mixed
Patient?_list=42
If any of these elements is present in a subscription criteria, then Smile CDR will not match the resource against the subscription criteria in-memory, but instead fall back to querying the repository directly.
HAPI FHIR and Smile CDR support a custom criteria format that can be used to match all resources of multiple resource types. This format takes the form [type1,type2,...]
, including the square brackets. The value inside the square brackets is a comma separated list of the resource type names you want to include. A star can be used to match all types except Subscription. For example:
"criteria": "[Patient,Observation,Organization]"
– Include all resources of type Patient, Observation, and Organization"[*]"
– Include all resources of all types except SubscriptionTo correctly update or delete Subscription resources in a clustered Smile CDR with multiple Subscription Matcher modules, all of these modules must be restarted when subscriptions are changed or deleted.
The Subscription Troubleshooting Log can be helpful in diagnosing issues relating to subscriptions.