Stream: implementers
Topic: GCP: Managing Resource Contention with FHIR Bundle
Nguyen Quang Huy (Aug 06 2020 at 08:52):
Hi, so currently I am trying to update multiple FHIR resources via executeBundle[1] and "Managing Resource Contention"[2] by using Etag with If-Match header. But GCP returning "412 Precondition Failed" with "diagnostics": "the version id doesn't match current value"
.
But it return "200 OK" when I try to update a single FHIR resource separately via executeBundle.
The different here are:
- Case 1: request bundle have 2 or more entries, each entry is a different resource of the same type with different versionId.
- Case 2: request bundle have only 1 entry.
[1] https://cloud.google.com/healthcare/docs/reference/rest/v1/projects.locations.datasets.fhirStores.fhir/executeBundle
[2] http://hl7.org/fhir/http.html#concurrency
So my request body for executeBundle look like this:
POST https://healthcare.googleapis.com/v1/projects/*/locations/*/datasets/*/fhirStores/*/fhir
- Case 1:
{
"entry": [
{
"resource": {
"active": false,
"gender": "female",
"id": "example1",
"meta": {
"lastUpdated": "2020-08-06T08:19:13.138829+00:00",
"versionId": "validVersionIdExample1"
},
"resourceType": "Patient"
},
"request": {
"method": "PUT",
"url": "Patient/example1",
"ifMatch": "W/\"validVersionIdExample1\""
}
},
{
"resource": {
"active": false,
"gender": "male",
"id": "example2",
"meta": {
"lastUpdated": "2020-08-06T08:19:30.331322+00:00",
"versionId": "validVersionIdExample2"
},
"resourceType": "Patient"
},
"request": {
"method": "PUT",
"url": "Patient/example2",
"ifMatch": "W/\"validVersionIdExample2\""
}
}
],
"type": "transaction",
"resourceType": "Bundle"
}
GCP will return: "Status: 412 Precondition Failed"
{
"issue": [
{
"code": "structure",
"details": {
"text": "invalid_headers"
},
"diagnostics": "the version id doesn't match current value",
"severity": "error"
}
],
"resourceType": "OperationOutcome"
}
- Case 2:
{
"entry": [
{
"resource": {
"active": false,
"gender": "female",
"id": "example1",
"meta": {
"lastUpdated": "2020-08-06T08:19:13.138829+00:00",
"versionId": "validVersionIdExample1"
},
"resourceType": "Patient"
},
"request": {
"method": "PUT",
"url": "Patient/example1",
"ifMatch": "W/\"validVersionIdExample1\""
}
}
],
"type": "transaction",
"resourceType": "Bundle"
}
GCP will return: "Status: 200 OK"
{
"entry": [
{
"response": {
"etag": "W/\"newVersionId\"",
"lastModified": "2020-08-06T08:41:01.385494+00:00",
"location": "https://healthcare.googleapis.com/v1/projects/*/locations/*/datasets/*/fhirStores/*/fhir/Patient/example1/_history/newVersionId",
"status": "200 OK"
}
}
],
"resourceType": "Bundle",
"type": "transaction-response"
}
Lloyd McKenzie (Aug 06 2020 at 14:40):
@Paul Church
Paul Church (Aug 06 2020 at 17:14):
What are your expectations in each of these cases? It depends on the current state of the resources compared to the version IDs specified in If-Match.
Nguyen Quang Huy (Aug 07 2020 at 06:13):
Paul Church said:
What are your expectations in each of these cases? It depends on the current state of the resources compared to the version IDs specified in If-Match.
For case 1: I expect GCP to return Status: 200 OK
response bundle with 2 entries which is updated resources from request. And of course those 2 resources should be updated.
For case 2: It is already return what I expect it to be returned.
Paul Church (Aug 10 2020 at 21:27):
I believe the confusion here is that the meta.lastUpdated and meta.versionId in the resources in the bundle have no effect. These fields are assigned by the server. The ifMatch header compares against the version ID of the resource currently in the store.
Also, our implementation does not check IfMatch when doing a PUT to a resource that does not exist - perhaps it is a matter of interpretation whether this should be rejected.
Your examples are succeeding or failing depending on the state of the store.
Nguyen Quang Huy (Aug 11 2020 at 08:29):
I think you miss understanding of my example. Let's me make it more clear:
- I have 2 Patient resources which already exist in FHIR store for example are
Patient/example1
&Patient/example2
. - I send to GCP an
executeBundle
to PUT those 2 already exist Patients, thetransaction bundle
in request body will have 2 entries which is corresponding toPatient/example1
&Patient/example2
. - The
ifMatch
will point to current version ID ofPatient/example1
&Patient/example2
corresponding arecurrentVersionOfPatientExample1
¤tVersionOfPatientExample2
. So it will look like this:
"entry": [
{
"resource": {
"id": "example1",
"resourceType": "Patient"
},
"request": {
"method": "PUT",
"url": "Patient/example1",
"ifMatch": "W/\"currentVersionOfPatientExample1\""
}
},
{
"resource": {
"id": "example2",
"resourceType": "Patient"
},
"request": {
"method": "PUT",
"url": "Patient/example2",
"ifMatch": "W/\"currentVersionOfPatientExample2\""
}
}
],
"type": "transaction",
"resourceType": "Bundle"
}
This will sometimes succeed and sometimes fail. So I don't know what is happening here as why sometimes it succeed and sometimes it fail.
Paul Church (Aug 18 2020 at 18:56):
@Nguyen Quang Huy I haven't reproduced this so far but we're still investigating. There are no existing known issues with IfMatch that would explain it.
Paul Church (Aug 20 2020 at 15:40):
@Nguyen Quang Huy We have identified the cause of this issue and a fix is in progress. The issue is specific to transaction bundles containing more than one entry with an IfMatch condition. I don't have any workarounds to suggest but we are confident that the fix will address the issue once rolled out to production.
Last updated: Apr 12 2022 at 19:14 UTC