The Problem:
The PUT operations on EHR, COMPOSITION, and DIRECTORY are currently not idempotent. They require the client to pass an 'If-Match' header that matches the previous version ID of the resource. Executing the same request multiple times fill fail with "412 Precondition Failed".
Why is this an issue?
When moving data from other systems into openEHR the requirement of having the previous version ID adds a lot of complexity. Many distributed systems have an "at-least-once" guarantee, with PUT requests to REST endpoints being considered idempotent making version ID fetching and conflict resolution even more problematic.
Consider an example of a legacy database trying to stream all old and new records into a message broker like RabbitMQ or NATS or an event streaming platform like Kafka with an "at-least-once" guarantee for the messages - the same message might repeat more than once. It's a common setup to have an event processing pipeline that finally ends up making a PUT request to the openEHR REST API to update changes in the old system. The system will need to make a GET request to the resource first and in the meanwhile, the repeating messages would all fail with a 412 Precondition Failed - this does not result in net data loss, however, adds a significant amount of overhead to what should be much simpler.
This is a very common problem that there are ecosystems of tools link Kafka Connector, for example, can plug and play for system integrations -- they correlate database INSERTs to HTTP PUT requests. And the PUT request being idempotent is a requirement for this kind of system. The typical behavior of PUT according to [REST standards](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) also correlates with this:
```
The difference between PUT and POST is that PUT is idempotent: calling it once or several times successively has the same effect (that is no side effect)
```
I also believe this is how most REST API PUT operations function. Eg: Elasticsearch, Hasura, FHIR.
Proposal:
Having idempotent PUT for EHR, COMPOSITION, and DIRECTORY can be achieved by making the following changes:
1. Depreciate and make the "If-Match" header optional: Enforce strict checking of the "If-Match" header if it's required to maintain backward compatibility. By default, however, try to always update the latest version of the resource if it exists. If there are concurrent updates, it should be up to the implementation to decide the winner, but the losing change should be faithfully recorded in the previous version.
2. PUT operations should create the resource if it does not exist with the given ID. Must return a 201 Created if the resources have been created, and must return a 200 OK or 204 No Content if the resource has been updated.
The Problem: The PUT operations on EHR, COMPOSITION, and DIRECTORY are currently not idempotent. They require the client to pass an 'If-Match' header that matches the previous version ID of the resource. Executing the same request multiple times fill fail with "412 Precondition Failed". Why is this an issue? When moving data from other systems into openEHR the requirement of having the previous version ID adds a lot of complexity. Many distributed systems have an "at-least-once" guarantee, with PUT requests to REST endpoints being considered idempotent making version ID fetching and conflict resolution even more problematic. Consider an example of a legacy database trying to stream all old and new records into a message broker like RabbitMQ or NATS or an event streaming platform like Kafka with an "at-least-once" guarantee for the messages - the same message might repeat more than once. It's a common setup to have an event processing pipeline that finally ends up making a PUT request to the openEHR REST API to update changes in the old system. The system will need to make a GET request to the resource first and in the meanwhile, the repeating messages would all fail with a 412 Precondition Failed - this does not result in net data loss, however, adds a significant amount of overhead to what should be much simpler. This is a very common problem that there are ecosystems of tools link Kafka Connector, for example, can plug and play for system integrations -- they correlate database INSERTs to HTTP PUT requests. And the PUT request being idempotent is a requirement for this kind of system. The typical behavior of PUT according to [REST standards](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) also correlates with this: ``` The difference between PUT and POST is that PUT is idempotent: calling it once or several times successively has the same effect (that is no side effect) ``` I also believe this is how most REST API PUT operations function. Eg: Elasticsearch, Hasura, FHIR. Proposal: Having idempotent PUT for EHR, COMPOSITION, and DIRECTORY can be achieved by making the following changes: 1. Depreciate and make the "If-Match" header optional: Enforce strict checking of the "If-Match" header if it's required to maintain backward compatibility. By default, however, try to always update the latest version of the resource if it exists. If there are concurrent updates, it should be up to the implementation to decide the winner, but the losing change should be faithfully recorded in the previous version. 2. PUT operations should create the resource if it does not exist with the given ID. Must return a 201 Created if the resources have been created, and must return a 200 OK or 204 No Content if the resource has been updated.