Changes API
Simple API to react on resource changes
Changes API is prone to race conditions.
Please review Possible Race Condition section. It outlines scenarios that could lead to event loss and suggests potential solutions to mitigate this risk.
Changes API can be used to get changes of resourceType or specific resource by versions. Each event (creating, updating, deleting) will increase version of the resource by 1.
Polling request is cheap! If you want to watch rare changes (minutes-hours), this API is very resource efficient (no subscriptions, no queues) and provides you lots of control. If nothing has been changed, you will get a response with status 304
, otherwise Changes API will response with a list of changes and a new version to poll next time.
Endpoints
GET /<resourceType>/$changes
— returns the latest version for the resourceType
.
GET /<resourceType>/$changes?<parameters>
— depending on parameters returns changes of the resourceType
.
GET /<resourceType>/<id>/$changes
— returns latest version of a specific resource.
GET /<resourceType>/<id>/$changes?<parameters>
— depending on parameters returns changes of the specific resource.
Query-string parameters
Below are parameters to use in both resourceType and specific resource endpoints.
Parameter | Meaning |
---|---|
| Returns changes since the specified version |
| Returns changes after the |
| If set to |
| If set to |
| Work as described here |
| Work as described here |
With parameters which start with dot you can filter resources by equality, e.g. .name.0.family=<string>
Example
Get the latest version of the Patient resource.
Assume the latest version is 1, no changes since version 1.
Let's add 2 patients to change version of Patient resource.
Since version 1, two events happened: created 2 patients.
We can filter events by dot expressions. Filtering Patient events by family name:
Check changes happened since version 1 until version 2.
Check version of patient with id pt-1
.
Use omit-resources=true
to request only id and resourceType fields in resources.
Cache performance
Changes API uses a cache to track a resourceType last change. To build the cache it runs a query to get the max
value of the txid
column. To make this operation efficient, it is recommended to build an index on the txid
column for tables where Changes API will be used.
Use query:
Replace <resourceType> with table name, for example:
CREATE INDEX IF NOT EXISTS patient_txid_btree ON patient using btree(txid);
CREATE INDEX IF NOT EXISTS patient_history_txid_btree ON patient_history using btree(txid);
Possible Race Condition
Consider a scenario where we have two database transactions: transaction-1, which creates patient-1, and transaction-2, which creates patient-2. These transactions are initiated almost simultaneously.
In this scenario, let's assume transaction-1 starts first, retrieving the value 99
from a database sequence object for txid
. Transaction-2 then starts and retrieves the next sequence value, 100
, for its txid
. Although transaction-1 started earlier, both transactions are processed concurrently in the database, which may result in transaction-2 being committed before transaction-1.
If the $changes
API is called after transaction-2 has been committed but before transaction-1 has been committed, the response will look like this:
In this case, the application will likely start its next iteration from getting the changes starting with version 100
, causing version 99
to be missed.
If the missing a single event is crucial for your situation, the potential solutions could be:
Periodically re-read all changes to ensure no events have been missed.
Implement the solution based on Aidbox topic-based subscriptions which can provide you
at-least-once
delivery guaranties.
Last updated