diff --git a/.github/scripts/check-referential-integrity-enforced.sh b/.github/scripts/check-referential-integrity-enforced.sh new file mode 100755 index 000000000..39b9fd3b6 --- /dev/null +++ b/.github/scripts/check-referential-integrity-enforced.sh @@ -0,0 +1,10 @@ +#!/bin/bash -e + +ENFORCED=$(curl -s http://localhost:8080/fhir/metadata | jq -r 'isempty(.rest[].resource[].referencePolicy[] | select(. == "enforced")) | not') + +if [ "true" = "$ENFORCED" ]; then + echo "Success" +else + echo "Fail" + exit 1 +fi diff --git a/.github/scripts/check-referential-integrity-not-enforced.sh b/.github/scripts/check-referential-integrity-not-enforced.sh new file mode 100755 index 000000000..f5faeee88 --- /dev/null +++ b/.github/scripts/check-referential-integrity-not-enforced.sh @@ -0,0 +1,10 @@ +#!/bin/bash -e + +ENFORCED=$(curl -s http://localhost:8080/fhir/metadata | jq -r 'isempty(.rest[].resource[].referencePolicy[] | select(. == "enforced")) | not') + +if [ "false" = "$ENFORCED" ]; then + echo "Success" +else + echo "Fail" + exit 1 +fi diff --git a/.github/scripts/check-total-number-of-resources.sh b/.github/scripts/check-total-number-of-resources.sh new file mode 100755 index 000000000..a0d58ef38 --- /dev/null +++ b/.github/scripts/check-total-number-of-resources.sh @@ -0,0 +1,10 @@ +#!/bin/bash -e + +TOTAL=$(curl -s http://localhost:8080/fhir | jq -r .total) + +if [ "$1" = "$TOTAL" ]; then + echo "Success" +else + echo "Fail: total number of resources was $TOTAL but should be $1" + exit 1 +fi diff --git a/.github/test-data/etl/0-condition.json b/.github/test-data/etl/0-condition.json new file mode 100644 index 000000000..a5fc02cdc --- /dev/null +++ b/.github/test-data/etl/0-condition.json @@ -0,0 +1,33 @@ +{ + "resourceType": "Bundle", + "type": "transaction", + "entry": [ + { + "fullUrl": "Condition/1-1", + "request": { + "method": "PUT", + "url": "Condition/1-1" + }, + "resource": { + "id": "1-1", + "meta": { + "profile": [ + "https://fhir.bbmri.de/StructureDefinition/Condition" + ] + }, + "resourceType": "Condition", + "code": { + "coding": [ + { + "system": "http://fhir.de/CodeSystem/dimdi/icd-10-gm", + "code": "C34.9" + } + ] + }, + "subject": { + "reference": "Patient/1" + } + } + } + ] +} diff --git a/.github/test-data/etl/1-specimen.json b/.github/test-data/etl/1-specimen.json new file mode 100644 index 000000000..b56f203d2 --- /dev/null +++ b/.github/test-data/etl/1-specimen.json @@ -0,0 +1,111 @@ +{ + "resourceType": "Bundle", + "type": "transaction", + "entry": [ + { + "fullUrl": "Specimen/1-1", + "request": { + "method": "PUT", + "url": "Specimen/1-1" + }, + "resource": { + "extension": [ + { + "url": "https://fhir.bbmri.de/StructureDefinition/Custodian", + "valueReference": { + "reference": "Organization/zebanc" + } + } + ], + "id": "1-1", + "meta": { + "profile": [ + "https://fhir.bbmri.de/StructureDefinition/Specimen" + ] + }, + "resourceType": "Specimen", + "subject": { + "reference": "Patient/1" + }, + "type": { + "coding": [ + { + "code": "blood-plasma", + "system": "https://fhir.bbmri.de/CodeSystem/SampleMaterialType" + } + ] + } + } + }, + { + "fullUrl": "Specimen/1-2", + "request": { + "method": "PUT", + "url": "Specimen/1-2" + }, + "resource": { + "extension": [ + { + "url": "https://fhir.bbmri.de/StructureDefinition/Custodian", + "valueReference": { + "reference": "Organization/zebanc" + } + } + ], + "id": "1-2", + "meta": { + "profile": [ + "https://fhir.bbmri.de/StructureDefinition/Specimen" + ] + }, + "resourceType": "Specimen", + "subject": { + "reference": "Patient/1" + }, + "type": { + "coding": [ + { + "code": "peripheral-blood-cells-vital", + "system": "https://fhir.bbmri.de/CodeSystem/SampleMaterialType" + } + ] + } + } + }, + { + "fullUrl": "Specimen/1-3", + "request": { + "method": "PUT", + "url": "Specimen/1-3" + }, + "resource": { + "extension": [ + { + "url": "https://fhir.bbmri.de/StructureDefinition/Custodian", + "valueReference": { + "reference": "Organization/zebanc" + } + } + ], + "id": "1-3", + "meta": { + "profile": [ + "https://fhir.bbmri.de/StructureDefinition/Specimen" + ] + }, + "resourceType": "Specimen", + "subject": { + "reference": "Patient/1" + }, + "type": { + "coding": [ + { + "code": "blood-plasma", + "system": "https://fhir.bbmri.de/CodeSystem/SampleMaterialType" + } + ] + } + } + } + ] +} diff --git a/.github/test-data/etl/2-patient.json b/.github/test-data/etl/2-patient.json new file mode 100644 index 000000000..7deebd32c --- /dev/null +++ b/.github/test-data/etl/2-patient.json @@ -0,0 +1,24 @@ +{ + "resourceType": "Bundle", + "type": "transaction", + "entry": [ + { + "fullUrl": "Patient/1", + "request": { + "method": "PUT", + "url": "Patient/1" + }, + "resource": { + "birthDate": "1989-11-18", + "gender": "male", + "id": "1", + "meta": { + "profile": [ + "https://fhir.bbmri.de/StructureDefinition/Patient" + ] + }, + "resourceType": "Patient" + } + } + ] +} diff --git a/.github/test-data/0-hospitalInformation1625911868739.json.bz2 b/.github/test-data/synthea/0-hospitalInformation1625911868739.json.bz2 similarity index 100% rename from .github/test-data/0-hospitalInformation1625911868739.json.bz2 rename to .github/test-data/synthea/0-hospitalInformation1625911868739.json.bz2 diff --git a/.github/test-data/0-practitionerInformation1625911868739.json.bz2 b/.github/test-data/synthea/0-practitionerInformation1625911868739.json.bz2 similarity index 100% rename from .github/test-data/0-practitionerInformation1625911868739.json.bz2 rename to .github/test-data/synthea/0-practitionerInformation1625911868739.json.bz2 diff --git a/.github/test-data/057aa36e-b892-9964-75b9-ffb46b097e34.json.bz2 b/.github/test-data/synthea/057aa36e-b892-9964-75b9-ffb46b097e34.json.bz2 similarity index 100% rename from .github/test-data/057aa36e-b892-9964-75b9-ffb46b097e34.json.bz2 rename to .github/test-data/synthea/057aa36e-b892-9964-75b9-ffb46b097e34.json.bz2 diff --git a/.github/test-data/0696ac49-3128-87d3-7344-04510aa4f324.json.bz2 b/.github/test-data/synthea/0696ac49-3128-87d3-7344-04510aa4f324.json.bz2 similarity index 100% rename from .github/test-data/0696ac49-3128-87d3-7344-04510aa4f324.json.bz2 rename to .github/test-data/synthea/0696ac49-3128-87d3-7344-04510aa4f324.json.bz2 diff --git a/.github/test-data/085e81c0-7a95-ef02-16ef-aa1b4344deed.json.bz2 b/.github/test-data/synthea/085e81c0-7a95-ef02-16ef-aa1b4344deed.json.bz2 similarity index 100% rename from .github/test-data/085e81c0-7a95-ef02-16ef-aa1b4344deed.json.bz2 rename to .github/test-data/synthea/085e81c0-7a95-ef02-16ef-aa1b4344deed.json.bz2 diff --git a/.github/test-data/098fc002-b87e-49dc-4b8e-8900a1bc8661.json.bz2 b/.github/test-data/synthea/098fc002-b87e-49dc-4b8e-8900a1bc8661.json.bz2 similarity index 100% rename from .github/test-data/098fc002-b87e-49dc-4b8e-8900a1bc8661.json.bz2 rename to .github/test-data/synthea/098fc002-b87e-49dc-4b8e-8900a1bc8661.json.bz2 diff --git a/.github/test-data/0ef7a3b5-53ee-e765-10e2-c63a904ad0fd.json.bz2 b/.github/test-data/synthea/0ef7a3b5-53ee-e765-10e2-c63a904ad0fd.json.bz2 similarity index 100% rename from .github/test-data/0ef7a3b5-53ee-e765-10e2-c63a904ad0fd.json.bz2 rename to .github/test-data/synthea/0ef7a3b5-53ee-e765-10e2-c63a904ad0fd.json.bz2 diff --git a/.github/test-data/0f2074a0-4173-1a32-988f-5316d7f1cbbe.json.bz2 b/.github/test-data/synthea/0f2074a0-4173-1a32-988f-5316d7f1cbbe.json.bz2 similarity index 100% rename from .github/test-data/0f2074a0-4173-1a32-988f-5316d7f1cbbe.json.bz2 rename to .github/test-data/synthea/0f2074a0-4173-1a32-988f-5316d7f1cbbe.json.bz2 diff --git a/.github/test-data/1363ed76-25b9-dc4f-6de7-6ee133d82db3.json.bz2 b/.github/test-data/synthea/1363ed76-25b9-dc4f-6de7-6ee133d82db3.json.bz2 similarity index 100% rename from .github/test-data/1363ed76-25b9-dc4f-6de7-6ee133d82db3.json.bz2 rename to .github/test-data/synthea/1363ed76-25b9-dc4f-6de7-6ee133d82db3.json.bz2 diff --git a/.github/test-data/13956cdf-f7cc-1cd7-9c99-eb796db62ec7.json.bz2 b/.github/test-data/synthea/13956cdf-f7cc-1cd7-9c99-eb796db62ec7.json.bz2 similarity index 100% rename from .github/test-data/13956cdf-f7cc-1cd7-9c99-eb796db62ec7.json.bz2 rename to .github/test-data/synthea/13956cdf-f7cc-1cd7-9c99-eb796db62ec7.json.bz2 diff --git a/.github/test-data/18be282b-67b9-d958-226a-c5510e5ef0c2.json.bz2 b/.github/test-data/synthea/18be282b-67b9-d958-226a-c5510e5ef0c2.json.bz2 similarity index 100% rename from .github/test-data/18be282b-67b9-d958-226a-c5510e5ef0c2.json.bz2 rename to .github/test-data/synthea/18be282b-67b9-d958-226a-c5510e5ef0c2.json.bz2 diff --git a/.github/test-data/19625ee6-1a94-1a6a-ca95-40c4efbbdfc7.json.bz2 b/.github/test-data/synthea/19625ee6-1a94-1a6a-ca95-40c4efbbdfc7.json.bz2 similarity index 100% rename from .github/test-data/19625ee6-1a94-1a6a-ca95-40c4efbbdfc7.json.bz2 rename to .github/test-data/synthea/19625ee6-1a94-1a6a-ca95-40c4efbbdfc7.json.bz2 diff --git a/.github/test-data/1ae8d602-4b41-4571-8c49-b460a22892c2.json.bz2 b/.github/test-data/synthea/1ae8d602-4b41-4571-8c49-b460a22892c2.json.bz2 similarity index 100% rename from .github/test-data/1ae8d602-4b41-4571-8c49-b460a22892c2.json.bz2 rename to .github/test-data/synthea/1ae8d602-4b41-4571-8c49-b460a22892c2.json.bz2 diff --git a/.github/test-data/1c574eeb-0f08-37cd-475e-fa4021b62ad3.json.bz2 b/.github/test-data/synthea/1c574eeb-0f08-37cd-475e-fa4021b62ad3.json.bz2 similarity index 100% rename from .github/test-data/1c574eeb-0f08-37cd-475e-fa4021b62ad3.json.bz2 rename to .github/test-data/synthea/1c574eeb-0f08-37cd-475e-fa4021b62ad3.json.bz2 diff --git a/.github/test-data/23275f24-df5a-6bcf-17cc-ff6507270b1c.json.bz2 b/.github/test-data/synthea/23275f24-df5a-6bcf-17cc-ff6507270b1c.json.bz2 similarity index 100% rename from .github/test-data/23275f24-df5a-6bcf-17cc-ff6507270b1c.json.bz2 rename to .github/test-data/synthea/23275f24-df5a-6bcf-17cc-ff6507270b1c.json.bz2 diff --git a/.github/test-data/24d82e9b-4114-f230-4318-60474031ec4d.json.bz2 b/.github/test-data/synthea/24d82e9b-4114-f230-4318-60474031ec4d.json.bz2 similarity index 100% rename from .github/test-data/24d82e9b-4114-f230-4318-60474031ec4d.json.bz2 rename to .github/test-data/synthea/24d82e9b-4114-f230-4318-60474031ec4d.json.bz2 diff --git a/.github/test-data/252abfcc-dd25-a9ce-f187-873a98cecc53.json.bz2 b/.github/test-data/synthea/252abfcc-dd25-a9ce-f187-873a98cecc53.json.bz2 similarity index 100% rename from .github/test-data/252abfcc-dd25-a9ce-f187-873a98cecc53.json.bz2 rename to .github/test-data/synthea/252abfcc-dd25-a9ce-f187-873a98cecc53.json.bz2 diff --git a/.github/test-data/2ad91c08-1b48-0562-dbb2-79f23c1b692b.json.bz2 b/.github/test-data/synthea/2ad91c08-1b48-0562-dbb2-79f23c1b692b.json.bz2 similarity index 100% rename from .github/test-data/2ad91c08-1b48-0562-dbb2-79f23c1b692b.json.bz2 rename to .github/test-data/synthea/2ad91c08-1b48-0562-dbb2-79f23c1b692b.json.bz2 diff --git a/.github/test-data/2b208315-4cc4-3d52-e597-a03509645859.json.bz2 b/.github/test-data/synthea/2b208315-4cc4-3d52-e597-a03509645859.json.bz2 similarity index 100% rename from .github/test-data/2b208315-4cc4-3d52-e597-a03509645859.json.bz2 rename to .github/test-data/synthea/2b208315-4cc4-3d52-e597-a03509645859.json.bz2 diff --git a/.github/test-data/2fcbe29d-94f0-ec20-dcf3-740c45bc08ba.json.bz2 b/.github/test-data/synthea/2fcbe29d-94f0-ec20-dcf3-740c45bc08ba.json.bz2 similarity index 100% rename from .github/test-data/2fcbe29d-94f0-ec20-dcf3-740c45bc08ba.json.bz2 rename to .github/test-data/synthea/2fcbe29d-94f0-ec20-dcf3-740c45bc08ba.json.bz2 diff --git a/.github/test-data/36ab6ed1-e43f-2903-2a7e-62df3a06702c.json.bz2 b/.github/test-data/synthea/36ab6ed1-e43f-2903-2a7e-62df3a06702c.json.bz2 similarity index 100% rename from .github/test-data/36ab6ed1-e43f-2903-2a7e-62df3a06702c.json.bz2 rename to .github/test-data/synthea/36ab6ed1-e43f-2903-2a7e-62df3a06702c.json.bz2 diff --git a/.github/test-data/3edde3b8-c705-5e74-5994-e69463d9fc69.json.bz2 b/.github/test-data/synthea/3edde3b8-c705-5e74-5994-e69463d9fc69.json.bz2 similarity index 100% rename from .github/test-data/3edde3b8-c705-5e74-5994-e69463d9fc69.json.bz2 rename to .github/test-data/synthea/3edde3b8-c705-5e74-5994-e69463d9fc69.json.bz2 diff --git a/.github/test-data/4004a424-c33b-6ced-23c3-c1318e45c419.json.bz2 b/.github/test-data/synthea/4004a424-c33b-6ced-23c3-c1318e45c419.json.bz2 similarity index 100% rename from .github/test-data/4004a424-c33b-6ced-23c3-c1318e45c419.json.bz2 rename to .github/test-data/synthea/4004a424-c33b-6ced-23c3-c1318e45c419.json.bz2 diff --git a/.github/test-data/44717d84-17d5-cefa-acf9-fe51fddc5d1c.json.bz2 b/.github/test-data/synthea/44717d84-17d5-cefa-acf9-fe51fddc5d1c.json.bz2 similarity index 100% rename from .github/test-data/44717d84-17d5-cefa-acf9-fe51fddc5d1c.json.bz2 rename to .github/test-data/synthea/44717d84-17d5-cefa-acf9-fe51fddc5d1c.json.bz2 diff --git a/.github/test-data/451e7c69-78b8-9bc9-b8a7-030c4a968215.json.bz2 b/.github/test-data/synthea/451e7c69-78b8-9bc9-b8a7-030c4a968215.json.bz2 similarity index 100% rename from .github/test-data/451e7c69-78b8-9bc9-b8a7-030c4a968215.json.bz2 rename to .github/test-data/synthea/451e7c69-78b8-9bc9-b8a7-030c4a968215.json.bz2 diff --git a/.github/test-data/4b86befa-fa7e-9285-615f-e081dab3f93c.json.bz2 b/.github/test-data/synthea/4b86befa-fa7e-9285-615f-e081dab3f93c.json.bz2 similarity index 100% rename from .github/test-data/4b86befa-fa7e-9285-615f-e081dab3f93c.json.bz2 rename to .github/test-data/synthea/4b86befa-fa7e-9285-615f-e081dab3f93c.json.bz2 diff --git a/.github/test-data/4fa27f17-62da-04b8-fcb6-81ba9f5e15af.json.bz2 b/.github/test-data/synthea/4fa27f17-62da-04b8-fcb6-81ba9f5e15af.json.bz2 similarity index 100% rename from .github/test-data/4fa27f17-62da-04b8-fcb6-81ba9f5e15af.json.bz2 rename to .github/test-data/synthea/4fa27f17-62da-04b8-fcb6-81ba9f5e15af.json.bz2 diff --git a/.github/test-data/5035bbae-27fc-b927-4a9b-7af7fdd536eb.json.bz2 b/.github/test-data/synthea/5035bbae-27fc-b927-4a9b-7af7fdd536eb.json.bz2 similarity index 100% rename from .github/test-data/5035bbae-27fc-b927-4a9b-7af7fdd536eb.json.bz2 rename to .github/test-data/synthea/5035bbae-27fc-b927-4a9b-7af7fdd536eb.json.bz2 diff --git a/.github/test-data/52ebdcae-3656-1a42-0bfc-c0a718b5158a.json.bz2 b/.github/test-data/synthea/52ebdcae-3656-1a42-0bfc-c0a718b5158a.json.bz2 similarity index 100% rename from .github/test-data/52ebdcae-3656-1a42-0bfc-c0a718b5158a.json.bz2 rename to .github/test-data/synthea/52ebdcae-3656-1a42-0bfc-c0a718b5158a.json.bz2 diff --git a/.github/test-data/53eac4c0-8d6b-72da-2768-a6d08e687f48.json.bz2 b/.github/test-data/synthea/53eac4c0-8d6b-72da-2768-a6d08e687f48.json.bz2 similarity index 100% rename from .github/test-data/53eac4c0-8d6b-72da-2768-a6d08e687f48.json.bz2 rename to .github/test-data/synthea/53eac4c0-8d6b-72da-2768-a6d08e687f48.json.bz2 diff --git a/.github/test-data/5656ee0a-e373-844b-92da-9afb6c321e76.json.bz2 b/.github/test-data/synthea/5656ee0a-e373-844b-92da-9afb6c321e76.json.bz2 similarity index 100% rename from .github/test-data/5656ee0a-e373-844b-92da-9afb6c321e76.json.bz2 rename to .github/test-data/synthea/5656ee0a-e373-844b-92da-9afb6c321e76.json.bz2 diff --git a/.github/test-data/56fce424-2560-0447-a0b0-4502d5abd975.json.bz2 b/.github/test-data/synthea/56fce424-2560-0447-a0b0-4502d5abd975.json.bz2 similarity index 100% rename from .github/test-data/56fce424-2560-0447-a0b0-4502d5abd975.json.bz2 rename to .github/test-data/synthea/56fce424-2560-0447-a0b0-4502d5abd975.json.bz2 diff --git a/.github/test-data/5875d3aa-192c-6d05-221a-88a9cee35ff9.json.bz2 b/.github/test-data/synthea/5875d3aa-192c-6d05-221a-88a9cee35ff9.json.bz2 similarity index 100% rename from .github/test-data/5875d3aa-192c-6d05-221a-88a9cee35ff9.json.bz2 rename to .github/test-data/synthea/5875d3aa-192c-6d05-221a-88a9cee35ff9.json.bz2 diff --git a/.github/test-data/5ad53a48-97ae-ca72-0ed8-0a31497f06cf.json.bz2 b/.github/test-data/synthea/5ad53a48-97ae-ca72-0ed8-0a31497f06cf.json.bz2 similarity index 100% rename from .github/test-data/5ad53a48-97ae-ca72-0ed8-0a31497f06cf.json.bz2 rename to .github/test-data/synthea/5ad53a48-97ae-ca72-0ed8-0a31497f06cf.json.bz2 diff --git a/.github/test-data/5d2a2d08-cf2e-b7ad-a0db-77551a2777ec.json.bz2 b/.github/test-data/synthea/5d2a2d08-cf2e-b7ad-a0db-77551a2777ec.json.bz2 similarity index 100% rename from .github/test-data/5d2a2d08-cf2e-b7ad-a0db-77551a2777ec.json.bz2 rename to .github/test-data/synthea/5d2a2d08-cf2e-b7ad-a0db-77551a2777ec.json.bz2 diff --git a/.github/test-data/5f66ecbb-b445-1290-4b55-9fc3ddfd569e.json.bz2 b/.github/test-data/synthea/5f66ecbb-b445-1290-4b55-9fc3ddfd569e.json.bz2 similarity index 100% rename from .github/test-data/5f66ecbb-b445-1290-4b55-9fc3ddfd569e.json.bz2 rename to .github/test-data/synthea/5f66ecbb-b445-1290-4b55-9fc3ddfd569e.json.bz2 diff --git a/.github/test-data/6a63e007-a6e5-9252-0155-79221cb61b60.json.bz2 b/.github/test-data/synthea/6a63e007-a6e5-9252-0155-79221cb61b60.json.bz2 similarity index 100% rename from .github/test-data/6a63e007-a6e5-9252-0155-79221cb61b60.json.bz2 rename to .github/test-data/synthea/6a63e007-a6e5-9252-0155-79221cb61b60.json.bz2 diff --git a/.github/test-data/6c8f3e83-c351-ed33-c38d-6be101c275d2.json.bz2 b/.github/test-data/synthea/6c8f3e83-c351-ed33-c38d-6be101c275d2.json.bz2 similarity index 100% rename from .github/test-data/6c8f3e83-c351-ed33-c38d-6be101c275d2.json.bz2 rename to .github/test-data/synthea/6c8f3e83-c351-ed33-c38d-6be101c275d2.json.bz2 diff --git a/.github/test-data/6db9aea3-4f89-5e2a-82d4-b2cd90268bc7.json.bz2 b/.github/test-data/synthea/6db9aea3-4f89-5e2a-82d4-b2cd90268bc7.json.bz2 similarity index 100% rename from .github/test-data/6db9aea3-4f89-5e2a-82d4-b2cd90268bc7.json.bz2 rename to .github/test-data/synthea/6db9aea3-4f89-5e2a-82d4-b2cd90268bc7.json.bz2 diff --git a/.github/test-data/718007d0-218e-d904-c3ec-0f23d4d2cd8b.json.bz2 b/.github/test-data/synthea/718007d0-218e-d904-c3ec-0f23d4d2cd8b.json.bz2 similarity index 100% rename from .github/test-data/718007d0-218e-d904-c3ec-0f23d4d2cd8b.json.bz2 rename to .github/test-data/synthea/718007d0-218e-d904-c3ec-0f23d4d2cd8b.json.bz2 diff --git a/.github/test-data/72376f6f-a404-ee42-7c9a-45a6b0bdc9f2.json.bz2 b/.github/test-data/synthea/72376f6f-a404-ee42-7c9a-45a6b0bdc9f2.json.bz2 similarity index 100% rename from .github/test-data/72376f6f-a404-ee42-7c9a-45a6b0bdc9f2.json.bz2 rename to .github/test-data/synthea/72376f6f-a404-ee42-7c9a-45a6b0bdc9f2.json.bz2 diff --git a/.github/test-data/7277a553-d195-6596-0124-b482d859691e.json.bz2 b/.github/test-data/synthea/7277a553-d195-6596-0124-b482d859691e.json.bz2 similarity index 100% rename from .github/test-data/7277a553-d195-6596-0124-b482d859691e.json.bz2 rename to .github/test-data/synthea/7277a553-d195-6596-0124-b482d859691e.json.bz2 diff --git a/.github/test-data/7278ffc8-5b59-8cb5-8419-294639a9908f.json.bz2 b/.github/test-data/synthea/7278ffc8-5b59-8cb5-8419-294639a9908f.json.bz2 similarity index 100% rename from .github/test-data/7278ffc8-5b59-8cb5-8419-294639a9908f.json.bz2 rename to .github/test-data/synthea/7278ffc8-5b59-8cb5-8419-294639a9908f.json.bz2 diff --git a/.github/test-data/728248bf-a984-5d08-efff-c44f98f56435.json.bz2 b/.github/test-data/synthea/728248bf-a984-5d08-efff-c44f98f56435.json.bz2 similarity index 100% rename from .github/test-data/728248bf-a984-5d08-efff-c44f98f56435.json.bz2 rename to .github/test-data/synthea/728248bf-a984-5d08-efff-c44f98f56435.json.bz2 diff --git a/.github/test-data/72b9ff2f-b285-2dd1-b020-eb672210c016.json.bz2 b/.github/test-data/synthea/72b9ff2f-b285-2dd1-b020-eb672210c016.json.bz2 similarity index 100% rename from .github/test-data/72b9ff2f-b285-2dd1-b020-eb672210c016.json.bz2 rename to .github/test-data/synthea/72b9ff2f-b285-2dd1-b020-eb672210c016.json.bz2 diff --git a/.github/test-data/738c6a70-cd4d-1ec9-077e-1828484674b4.json.bz2 b/.github/test-data/synthea/738c6a70-cd4d-1ec9-077e-1828484674b4.json.bz2 similarity index 100% rename from .github/test-data/738c6a70-cd4d-1ec9-077e-1828484674b4.json.bz2 rename to .github/test-data/synthea/738c6a70-cd4d-1ec9-077e-1828484674b4.json.bz2 diff --git a/.github/test-data/76f217df-3176-7627-8fef-e60a9b3574c2.json.bz2 b/.github/test-data/synthea/76f217df-3176-7627-8fef-e60a9b3574c2.json.bz2 similarity index 100% rename from .github/test-data/76f217df-3176-7627-8fef-e60a9b3574c2.json.bz2 rename to .github/test-data/synthea/76f217df-3176-7627-8fef-e60a9b3574c2.json.bz2 diff --git a/.github/test-data/771500c7-1f71-f706-1c07-155670e2db3a.json.bz2 b/.github/test-data/synthea/771500c7-1f71-f706-1c07-155670e2db3a.json.bz2 similarity index 100% rename from .github/test-data/771500c7-1f71-f706-1c07-155670e2db3a.json.bz2 rename to .github/test-data/synthea/771500c7-1f71-f706-1c07-155670e2db3a.json.bz2 diff --git a/.github/test-data/7a8faea5-1769-a9d8-fa58-a6240f7c252d.json.bz2 b/.github/test-data/synthea/7a8faea5-1769-a9d8-fa58-a6240f7c252d.json.bz2 similarity index 100% rename from .github/test-data/7a8faea5-1769-a9d8-fa58-a6240f7c252d.json.bz2 rename to .github/test-data/synthea/7a8faea5-1769-a9d8-fa58-a6240f7c252d.json.bz2 diff --git a/.github/test-data/7d8cb13b-3ec2-91af-cfdd-3bb3a0d07039.json.bz2 b/.github/test-data/synthea/7d8cb13b-3ec2-91af-cfdd-3bb3a0d07039.json.bz2 similarity index 100% rename from .github/test-data/7d8cb13b-3ec2-91af-cfdd-3bb3a0d07039.json.bz2 rename to .github/test-data/synthea/7d8cb13b-3ec2-91af-cfdd-3bb3a0d07039.json.bz2 diff --git a/.github/test-data/83c9c542-0421-9ccb-34f6-8c6876fe04e5.json.bz2 b/.github/test-data/synthea/83c9c542-0421-9ccb-34f6-8c6876fe04e5.json.bz2 similarity index 100% rename from .github/test-data/83c9c542-0421-9ccb-34f6-8c6876fe04e5.json.bz2 rename to .github/test-data/synthea/83c9c542-0421-9ccb-34f6-8c6876fe04e5.json.bz2 diff --git a/.github/test-data/8682665a-3515-ffeb-39d5-3802f6f36932.json.bz2 b/.github/test-data/synthea/8682665a-3515-ffeb-39d5-3802f6f36932.json.bz2 similarity index 100% rename from .github/test-data/8682665a-3515-ffeb-39d5-3802f6f36932.json.bz2 rename to .github/test-data/synthea/8682665a-3515-ffeb-39d5-3802f6f36932.json.bz2 diff --git a/.github/test-data/8708d3e1-f718-96bb-03f0-f2a6564ae1cd.json.bz2 b/.github/test-data/synthea/8708d3e1-f718-96bb-03f0-f2a6564ae1cd.json.bz2 similarity index 100% rename from .github/test-data/8708d3e1-f718-96bb-03f0-f2a6564ae1cd.json.bz2 rename to .github/test-data/synthea/8708d3e1-f718-96bb-03f0-f2a6564ae1cd.json.bz2 diff --git a/.github/test-data/88e4bac8-2609-3c28-a354-ab29f69153f4.json.bz2 b/.github/test-data/synthea/88e4bac8-2609-3c28-a354-ab29f69153f4.json.bz2 similarity index 100% rename from .github/test-data/88e4bac8-2609-3c28-a354-ab29f69153f4.json.bz2 rename to .github/test-data/synthea/88e4bac8-2609-3c28-a354-ab29f69153f4.json.bz2 diff --git a/.github/test-data/897a61e0-353b-25d1-7806-2a21710cb764.json.bz2 b/.github/test-data/synthea/897a61e0-353b-25d1-7806-2a21710cb764.json.bz2 similarity index 100% rename from .github/test-data/897a61e0-353b-25d1-7806-2a21710cb764.json.bz2 rename to .github/test-data/synthea/897a61e0-353b-25d1-7806-2a21710cb764.json.bz2 diff --git a/.github/test-data/897eba7c-8b8c-7022-634f-8c69f0702b30.json.bz2 b/.github/test-data/synthea/897eba7c-8b8c-7022-634f-8c69f0702b30.json.bz2 similarity index 100% rename from .github/test-data/897eba7c-8b8c-7022-634f-8c69f0702b30.json.bz2 rename to .github/test-data/synthea/897eba7c-8b8c-7022-634f-8c69f0702b30.json.bz2 diff --git a/.github/test-data/8a4c9c04-1524-9f1c-d65b-9b17e4520fef.json.bz2 b/.github/test-data/synthea/8a4c9c04-1524-9f1c-d65b-9b17e4520fef.json.bz2 similarity index 100% rename from .github/test-data/8a4c9c04-1524-9f1c-d65b-9b17e4520fef.json.bz2 rename to .github/test-data/synthea/8a4c9c04-1524-9f1c-d65b-9b17e4520fef.json.bz2 diff --git a/.github/test-data/8dd4ed1f-108e-64ad-ce09-926c83ce7f76.json.bz2 b/.github/test-data/synthea/8dd4ed1f-108e-64ad-ce09-926c83ce7f76.json.bz2 similarity index 100% rename from .github/test-data/8dd4ed1f-108e-64ad-ce09-926c83ce7f76.json.bz2 rename to .github/test-data/synthea/8dd4ed1f-108e-64ad-ce09-926c83ce7f76.json.bz2 diff --git a/.github/test-data/9478e08e-4573-88e1-7ea2-1b757771da8b.json.bz2 b/.github/test-data/synthea/9478e08e-4573-88e1-7ea2-1b757771da8b.json.bz2 similarity index 100% rename from .github/test-data/9478e08e-4573-88e1-7ea2-1b757771da8b.json.bz2 rename to .github/test-data/synthea/9478e08e-4573-88e1-7ea2-1b757771da8b.json.bz2 diff --git a/.github/test-data/98f6377c-4f40-745a-04aa-fcb2ce32d9bd.json.bz2 b/.github/test-data/synthea/98f6377c-4f40-745a-04aa-fcb2ce32d9bd.json.bz2 similarity index 100% rename from .github/test-data/98f6377c-4f40-745a-04aa-fcb2ce32d9bd.json.bz2 rename to .github/test-data/synthea/98f6377c-4f40-745a-04aa-fcb2ce32d9bd.json.bz2 diff --git a/.github/test-data/99e6bacf-7def-f6b6-5f1b-888241c8729a.json.bz2 b/.github/test-data/synthea/99e6bacf-7def-f6b6-5f1b-888241c8729a.json.bz2 similarity index 100% rename from .github/test-data/99e6bacf-7def-f6b6-5f1b-888241c8729a.json.bz2 rename to .github/test-data/synthea/99e6bacf-7def-f6b6-5f1b-888241c8729a.json.bz2 diff --git a/.github/test-data/9a174f9e-ed67-6617-0106-745fb1f9a344.json.bz2 b/.github/test-data/synthea/9a174f9e-ed67-6617-0106-745fb1f9a344.json.bz2 similarity index 100% rename from .github/test-data/9a174f9e-ed67-6617-0106-745fb1f9a344.json.bz2 rename to .github/test-data/synthea/9a174f9e-ed67-6617-0106-745fb1f9a344.json.bz2 diff --git a/.github/test-data/9b6fa8e6-e618-17c5-28a8-1095559fd19b.json.bz2 b/.github/test-data/synthea/9b6fa8e6-e618-17c5-28a8-1095559fd19b.json.bz2 similarity index 100% rename from .github/test-data/9b6fa8e6-e618-17c5-28a8-1095559fd19b.json.bz2 rename to .github/test-data/synthea/9b6fa8e6-e618-17c5-28a8-1095559fd19b.json.bz2 diff --git a/.github/test-data/9d3e5754-acb3-5573-ef17-fe95d83dc941.json.bz2 b/.github/test-data/synthea/9d3e5754-acb3-5573-ef17-fe95d83dc941.json.bz2 similarity index 100% rename from .github/test-data/9d3e5754-acb3-5573-ef17-fe95d83dc941.json.bz2 rename to .github/test-data/synthea/9d3e5754-acb3-5573-ef17-fe95d83dc941.json.bz2 diff --git a/.github/test-data/9fa1e332-a3eb-52e2-d79a-62042a485967.json.bz2 b/.github/test-data/synthea/9fa1e332-a3eb-52e2-d79a-62042a485967.json.bz2 similarity index 100% rename from .github/test-data/9fa1e332-a3eb-52e2-d79a-62042a485967.json.bz2 rename to .github/test-data/synthea/9fa1e332-a3eb-52e2-d79a-62042a485967.json.bz2 diff --git a/.github/test-data/9fe7994a-5fec-874c-8452-e45786bcfb0a.json.bz2 b/.github/test-data/synthea/9fe7994a-5fec-874c-8452-e45786bcfb0a.json.bz2 similarity index 100% rename from .github/test-data/9fe7994a-5fec-874c-8452-e45786bcfb0a.json.bz2 rename to .github/test-data/synthea/9fe7994a-5fec-874c-8452-e45786bcfb0a.json.bz2 diff --git a/.github/test-data/README.md b/.github/test-data/synthea/README.md similarity index 99% rename from .github/test-data/README.md rename to .github/test-data/synthea/README.md index fcb53ae23..0b69e811e 100644 --- a/.github/test-data/README.md +++ b/.github/test-data/synthea/README.md @@ -1,4 +1,4 @@ -# FHIR Test Data +# FHIR Synthea Test Data Generates with Synthea v2.7.0 using openjdk 11. @@ -269,4 +269,4 @@ Max Age: 140 98 -- Billy698 Homenick806 (78 y/o M) Newton, Massachusetts 93 -- Karine844 Blanda868 (58 y/o F) Worcester, Massachusetts Records: total=120, alive=100, dead=20 -``` \ No newline at end of file +``` diff --git a/.github/test-data/a1935ff2-8d78-6259-e537-1036c451d997.json.bz2 b/.github/test-data/synthea/a1935ff2-8d78-6259-e537-1036c451d997.json.bz2 similarity index 100% rename from .github/test-data/a1935ff2-8d78-6259-e537-1036c451d997.json.bz2 rename to .github/test-data/synthea/a1935ff2-8d78-6259-e537-1036c451d997.json.bz2 diff --git a/.github/test-data/a47131c6-a60c-4a8e-f099-0ae21c7969ff.json.bz2 b/.github/test-data/synthea/a47131c6-a60c-4a8e-f099-0ae21c7969ff.json.bz2 similarity index 100% rename from .github/test-data/a47131c6-a60c-4a8e-f099-0ae21c7969ff.json.bz2 rename to .github/test-data/synthea/a47131c6-a60c-4a8e-f099-0ae21c7969ff.json.bz2 diff --git a/.github/test-data/a8327210-6158-2be1-fb72-553a78a0ff37.json.bz2 b/.github/test-data/synthea/a8327210-6158-2be1-fb72-553a78a0ff37.json.bz2 similarity index 100% rename from .github/test-data/a8327210-6158-2be1-fb72-553a78a0ff37.json.bz2 rename to .github/test-data/synthea/a8327210-6158-2be1-fb72-553a78a0ff37.json.bz2 diff --git a/.github/test-data/a8376487-72d8-ac29-a654-91f3622cc7a4.json.bz2 b/.github/test-data/synthea/a8376487-72d8-ac29-a654-91f3622cc7a4.json.bz2 similarity index 100% rename from .github/test-data/a8376487-72d8-ac29-a654-91f3622cc7a4.json.bz2 rename to .github/test-data/synthea/a8376487-72d8-ac29-a654-91f3622cc7a4.json.bz2 diff --git a/.github/test-data/a97a7383-b712-e276-4cc1-51e4b4e84c13.json.bz2 b/.github/test-data/synthea/a97a7383-b712-e276-4cc1-51e4b4e84c13.json.bz2 similarity index 100% rename from .github/test-data/a97a7383-b712-e276-4cc1-51e4b4e84c13.json.bz2 rename to .github/test-data/synthea/a97a7383-b712-e276-4cc1-51e4b4e84c13.json.bz2 diff --git a/.github/test-data/aaac7c75-2413-47f0-6696-19d645ae5eda.json.bz2 b/.github/test-data/synthea/aaac7c75-2413-47f0-6696-19d645ae5eda.json.bz2 similarity index 100% rename from .github/test-data/aaac7c75-2413-47f0-6696-19d645ae5eda.json.bz2 rename to .github/test-data/synthea/aaac7c75-2413-47f0-6696-19d645ae5eda.json.bz2 diff --git a/.github/test-data/ab5537a3-8608-5f56-53f5-d10b00eb4680.json.bz2 b/.github/test-data/synthea/ab5537a3-8608-5f56-53f5-d10b00eb4680.json.bz2 similarity index 100% rename from .github/test-data/ab5537a3-8608-5f56-53f5-d10b00eb4680.json.bz2 rename to .github/test-data/synthea/ab5537a3-8608-5f56-53f5-d10b00eb4680.json.bz2 diff --git a/.github/test-data/ac22410a-b0e0-31eb-5ff2-2a3a47f1cff0.json.bz2 b/.github/test-data/synthea/ac22410a-b0e0-31eb-5ff2-2a3a47f1cff0.json.bz2 similarity index 100% rename from .github/test-data/ac22410a-b0e0-31eb-5ff2-2a3a47f1cff0.json.bz2 rename to .github/test-data/synthea/ac22410a-b0e0-31eb-5ff2-2a3a47f1cff0.json.bz2 diff --git a/.github/test-data/acd56837-aaab-5825-8f24-784319fc02df.json.bz2 b/.github/test-data/synthea/acd56837-aaab-5825-8f24-784319fc02df.json.bz2 similarity index 100% rename from .github/test-data/acd56837-aaab-5825-8f24-784319fc02df.json.bz2 rename to .github/test-data/synthea/acd56837-aaab-5825-8f24-784319fc02df.json.bz2 diff --git a/.github/test-data/ad0b4b7a-2285-7a3c-5fd2-edbe4d67b7e7.json.bz2 b/.github/test-data/synthea/ad0b4b7a-2285-7a3c-5fd2-edbe4d67b7e7.json.bz2 similarity index 100% rename from .github/test-data/ad0b4b7a-2285-7a3c-5fd2-edbe4d67b7e7.json.bz2 rename to .github/test-data/synthea/ad0b4b7a-2285-7a3c-5fd2-edbe4d67b7e7.json.bz2 diff --git a/.github/test-data/b08d10a2-5031-379f-0157-ddceb2196440.json.bz2 b/.github/test-data/synthea/b08d10a2-5031-379f-0157-ddceb2196440.json.bz2 similarity index 100% rename from .github/test-data/b08d10a2-5031-379f-0157-ddceb2196440.json.bz2 rename to .github/test-data/synthea/b08d10a2-5031-379f-0157-ddceb2196440.json.bz2 diff --git a/.github/test-data/b3664f86-0ce9-4a2c-ae85-4d390d438512.json.bz2 b/.github/test-data/synthea/b3664f86-0ce9-4a2c-ae85-4d390d438512.json.bz2 similarity index 100% rename from .github/test-data/b3664f86-0ce9-4a2c-ae85-4d390d438512.json.bz2 rename to .github/test-data/synthea/b3664f86-0ce9-4a2c-ae85-4d390d438512.json.bz2 diff --git a/.github/test-data/b62462f8-e515-7cdd-449d-e03b38e976e1.json.bz2 b/.github/test-data/synthea/b62462f8-e515-7cdd-449d-e03b38e976e1.json.bz2 similarity index 100% rename from .github/test-data/b62462f8-e515-7cdd-449d-e03b38e976e1.json.bz2 rename to .github/test-data/synthea/b62462f8-e515-7cdd-449d-e03b38e976e1.json.bz2 diff --git a/.github/test-data/b6f92fa3-b989-fa1b-aad8-aafb1020a5e9.json.bz2 b/.github/test-data/synthea/b6f92fa3-b989-fa1b-aad8-aafb1020a5e9.json.bz2 similarity index 100% rename from .github/test-data/b6f92fa3-b989-fa1b-aad8-aafb1020a5e9.json.bz2 rename to .github/test-data/synthea/b6f92fa3-b989-fa1b-aad8-aafb1020a5e9.json.bz2 diff --git a/.github/test-data/b7dbbc09-0370-0e9f-dc4b-46f41e48b82d.json.bz2 b/.github/test-data/synthea/b7dbbc09-0370-0e9f-dc4b-46f41e48b82d.json.bz2 similarity index 100% rename from .github/test-data/b7dbbc09-0370-0e9f-dc4b-46f41e48b82d.json.bz2 rename to .github/test-data/synthea/b7dbbc09-0370-0e9f-dc4b-46f41e48b82d.json.bz2 diff --git a/.github/test-data/b9590b16-804d-3d9f-0de0-b80b794f1017.json.bz2 b/.github/test-data/synthea/b9590b16-804d-3d9f-0de0-b80b794f1017.json.bz2 similarity index 100% rename from .github/test-data/b9590b16-804d-3d9f-0de0-b80b794f1017.json.bz2 rename to .github/test-data/synthea/b9590b16-804d-3d9f-0de0-b80b794f1017.json.bz2 diff --git a/.github/test-data/bba190d1-1356-0588-7a1b-7e1325835baa.json.bz2 b/.github/test-data/synthea/bba190d1-1356-0588-7a1b-7e1325835baa.json.bz2 similarity index 100% rename from .github/test-data/bba190d1-1356-0588-7a1b-7e1325835baa.json.bz2 rename to .github/test-data/synthea/bba190d1-1356-0588-7a1b-7e1325835baa.json.bz2 diff --git a/.github/test-data/be9d18f7-f230-dadc-049e-c13d3a4ac079.json.bz2 b/.github/test-data/synthea/be9d18f7-f230-dadc-049e-c13d3a4ac079.json.bz2 similarity index 100% rename from .github/test-data/be9d18f7-f230-dadc-049e-c13d3a4ac079.json.bz2 rename to .github/test-data/synthea/be9d18f7-f230-dadc-049e-c13d3a4ac079.json.bz2 diff --git a/.github/test-data/beb53716-4df8-a51c-c58e-a8b814b8ac88.json.bz2 b/.github/test-data/synthea/beb53716-4df8-a51c-c58e-a8b814b8ac88.json.bz2 similarity index 100% rename from .github/test-data/beb53716-4df8-a51c-c58e-a8b814b8ac88.json.bz2 rename to .github/test-data/synthea/beb53716-4df8-a51c-c58e-a8b814b8ac88.json.bz2 diff --git a/.github/test-data/c0697745-be05-4abc-07e0-f78ca6cb7230.json.bz2 b/.github/test-data/synthea/c0697745-be05-4abc-07e0-f78ca6cb7230.json.bz2 similarity index 100% rename from .github/test-data/c0697745-be05-4abc-07e0-f78ca6cb7230.json.bz2 rename to .github/test-data/synthea/c0697745-be05-4abc-07e0-f78ca6cb7230.json.bz2 diff --git a/.github/test-data/c1933e20-95c2-61c5-684b-7554a943648b.json.bz2 b/.github/test-data/synthea/c1933e20-95c2-61c5-684b-7554a943648b.json.bz2 similarity index 100% rename from .github/test-data/c1933e20-95c2-61c5-684b-7554a943648b.json.bz2 rename to .github/test-data/synthea/c1933e20-95c2-61c5-684b-7554a943648b.json.bz2 diff --git a/.github/test-data/c4bf405e-26ad-4bb9-e17c-9ee3a40f86c6.json.bz2 b/.github/test-data/synthea/c4bf405e-26ad-4bb9-e17c-9ee3a40f86c6.json.bz2 similarity index 100% rename from .github/test-data/c4bf405e-26ad-4bb9-e17c-9ee3a40f86c6.json.bz2 rename to .github/test-data/synthea/c4bf405e-26ad-4bb9-e17c-9ee3a40f86c6.json.bz2 diff --git a/.github/test-data/c535373c-cbac-c4cd-3281-8eaa9dcc116d.json.bz2 b/.github/test-data/synthea/c535373c-cbac-c4cd-3281-8eaa9dcc116d.json.bz2 similarity index 100% rename from .github/test-data/c535373c-cbac-c4cd-3281-8eaa9dcc116d.json.bz2 rename to .github/test-data/synthea/c535373c-cbac-c4cd-3281-8eaa9dcc116d.json.bz2 diff --git a/.github/test-data/c5c9dbe6-4370-55b5-f14f-3374b173753e.json.bz2 b/.github/test-data/synthea/c5c9dbe6-4370-55b5-f14f-3374b173753e.json.bz2 similarity index 100% rename from .github/test-data/c5c9dbe6-4370-55b5-f14f-3374b173753e.json.bz2 rename to .github/test-data/synthea/c5c9dbe6-4370-55b5-f14f-3374b173753e.json.bz2 diff --git a/.github/test-data/c94995d9-8ee6-7c32-2b54-acb14e716901.json.bz2 b/.github/test-data/synthea/c94995d9-8ee6-7c32-2b54-acb14e716901.json.bz2 similarity index 100% rename from .github/test-data/c94995d9-8ee6-7c32-2b54-acb14e716901.json.bz2 rename to .github/test-data/synthea/c94995d9-8ee6-7c32-2b54-acb14e716901.json.bz2 diff --git a/.github/test-data/cd185ab5-8efb-c68a-4779-d49dd4ba8f28.json.bz2 b/.github/test-data/synthea/cd185ab5-8efb-c68a-4779-d49dd4ba8f28.json.bz2 similarity index 100% rename from .github/test-data/cd185ab5-8efb-c68a-4779-d49dd4ba8f28.json.bz2 rename to .github/test-data/synthea/cd185ab5-8efb-c68a-4779-d49dd4ba8f28.json.bz2 diff --git a/.github/test-data/cdb9464f-4968-0f08-c49d-b0b85254620f.json.bz2 b/.github/test-data/synthea/cdb9464f-4968-0f08-c49d-b0b85254620f.json.bz2 similarity index 100% rename from .github/test-data/cdb9464f-4968-0f08-c49d-b0b85254620f.json.bz2 rename to .github/test-data/synthea/cdb9464f-4968-0f08-c49d-b0b85254620f.json.bz2 diff --git a/.github/test-data/cee84886-eadf-fbeb-d9b9-91321b5d213f.json.bz2 b/.github/test-data/synthea/cee84886-eadf-fbeb-d9b9-91321b5d213f.json.bz2 similarity index 100% rename from .github/test-data/cee84886-eadf-fbeb-d9b9-91321b5d213f.json.bz2 rename to .github/test-data/synthea/cee84886-eadf-fbeb-d9b9-91321b5d213f.json.bz2 diff --git a/.github/test-data/d1193889-ebd9-4e35-bf1b-8a73ecbfc00b.json.bz2 b/.github/test-data/synthea/d1193889-ebd9-4e35-bf1b-8a73ecbfc00b.json.bz2 similarity index 100% rename from .github/test-data/d1193889-ebd9-4e35-bf1b-8a73ecbfc00b.json.bz2 rename to .github/test-data/synthea/d1193889-ebd9-4e35-bf1b-8a73ecbfc00b.json.bz2 diff --git a/.github/test-data/d6149fdd-6607-bbc6-731a-519f920e7c88.json.bz2 b/.github/test-data/synthea/d6149fdd-6607-bbc6-731a-519f920e7c88.json.bz2 similarity index 100% rename from .github/test-data/d6149fdd-6607-bbc6-731a-519f920e7c88.json.bz2 rename to .github/test-data/synthea/d6149fdd-6607-bbc6-731a-519f920e7c88.json.bz2 diff --git a/.github/test-data/d614dcb6-435f-be94-5344-00143898b1c3.json.bz2 b/.github/test-data/synthea/d614dcb6-435f-be94-5344-00143898b1c3.json.bz2 similarity index 100% rename from .github/test-data/d614dcb6-435f-be94-5344-00143898b1c3.json.bz2 rename to .github/test-data/synthea/d614dcb6-435f-be94-5344-00143898b1c3.json.bz2 diff --git a/.github/test-data/da203ade-58db-ae38-3608-f20843a86759.json.bz2 b/.github/test-data/synthea/da203ade-58db-ae38-3608-f20843a86759.json.bz2 similarity index 100% rename from .github/test-data/da203ade-58db-ae38-3608-f20843a86759.json.bz2 rename to .github/test-data/synthea/da203ade-58db-ae38-3608-f20843a86759.json.bz2 diff --git a/.github/test-data/dd4d5564-3cdd-19ce-8efc-f30e5395f5c6.json.bz2 b/.github/test-data/synthea/dd4d5564-3cdd-19ce-8efc-f30e5395f5c6.json.bz2 similarity index 100% rename from .github/test-data/dd4d5564-3cdd-19ce-8efc-f30e5395f5c6.json.bz2 rename to .github/test-data/synthea/dd4d5564-3cdd-19ce-8efc-f30e5395f5c6.json.bz2 diff --git a/.github/test-data/dd92a3e7-d1db-c15a-f8fe-e3847b7f07b1.json.bz2 b/.github/test-data/synthea/dd92a3e7-d1db-c15a-f8fe-e3847b7f07b1.json.bz2 similarity index 100% rename from .github/test-data/dd92a3e7-d1db-c15a-f8fe-e3847b7f07b1.json.bz2 rename to .github/test-data/synthea/dd92a3e7-d1db-c15a-f8fe-e3847b7f07b1.json.bz2 diff --git a/.github/test-data/e0d320aa-cba1-6d50-ef4a-56191eb00c41.json.bz2 b/.github/test-data/synthea/e0d320aa-cba1-6d50-ef4a-56191eb00c41.json.bz2 similarity index 100% rename from .github/test-data/e0d320aa-cba1-6d50-ef4a-56191eb00c41.json.bz2 rename to .github/test-data/synthea/e0d320aa-cba1-6d50-ef4a-56191eb00c41.json.bz2 diff --git a/.github/test-data/e1404dc3-4e21-84ae-cdcf-89d04084020c.json.bz2 b/.github/test-data/synthea/e1404dc3-4e21-84ae-cdcf-89d04084020c.json.bz2 similarity index 100% rename from .github/test-data/e1404dc3-4e21-84ae-cdcf-89d04084020c.json.bz2 rename to .github/test-data/synthea/e1404dc3-4e21-84ae-cdcf-89d04084020c.json.bz2 diff --git a/.github/test-data/e1dbcb04-9c64-e94c-2bd0-d7b199d369e5.json.bz2 b/.github/test-data/synthea/e1dbcb04-9c64-e94c-2bd0-d7b199d369e5.json.bz2 similarity index 100% rename from .github/test-data/e1dbcb04-9c64-e94c-2bd0-d7b199d369e5.json.bz2 rename to .github/test-data/synthea/e1dbcb04-9c64-e94c-2bd0-d7b199d369e5.json.bz2 diff --git a/.github/test-data/e2053282-a9da-7d0c-8683-481ae0b8c75c.json.bz2 b/.github/test-data/synthea/e2053282-a9da-7d0c-8683-481ae0b8c75c.json.bz2 similarity index 100% rename from .github/test-data/e2053282-a9da-7d0c-8683-481ae0b8c75c.json.bz2 rename to .github/test-data/synthea/e2053282-a9da-7d0c-8683-481ae0b8c75c.json.bz2 diff --git a/.github/test-data/e2d6fb82-fce6-063b-a9b1-554d585bb268.json.bz2 b/.github/test-data/synthea/e2d6fb82-fce6-063b-a9b1-554d585bb268.json.bz2 similarity index 100% rename from .github/test-data/e2d6fb82-fce6-063b-a9b1-554d585bb268.json.bz2 rename to .github/test-data/synthea/e2d6fb82-fce6-063b-a9b1-554d585bb268.json.bz2 diff --git a/.github/test-data/e3ba24ed-aad7-86db-2646-4c510dfd7280.json.bz2 b/.github/test-data/synthea/e3ba24ed-aad7-86db-2646-4c510dfd7280.json.bz2 similarity index 100% rename from .github/test-data/e3ba24ed-aad7-86db-2646-4c510dfd7280.json.bz2 rename to .github/test-data/synthea/e3ba24ed-aad7-86db-2646-4c510dfd7280.json.bz2 diff --git a/.github/test-data/e5a8d3f4-4484-ebfd-7404-d9f02c9fe6a6.json.bz2 b/.github/test-data/synthea/e5a8d3f4-4484-ebfd-7404-d9f02c9fe6a6.json.bz2 similarity index 100% rename from .github/test-data/e5a8d3f4-4484-ebfd-7404-d9f02c9fe6a6.json.bz2 rename to .github/test-data/synthea/e5a8d3f4-4484-ebfd-7404-d9f02c9fe6a6.json.bz2 diff --git a/.github/test-data/e660ef94-5bfc-04d6-c321-c5baaf41cfb8.json.bz2 b/.github/test-data/synthea/e660ef94-5bfc-04d6-c321-c5baaf41cfb8.json.bz2 similarity index 100% rename from .github/test-data/e660ef94-5bfc-04d6-c321-c5baaf41cfb8.json.bz2 rename to .github/test-data/synthea/e660ef94-5bfc-04d6-c321-c5baaf41cfb8.json.bz2 diff --git a/.github/test-data/e78fd9c5-5c89-26ca-d397-e9da30700444.json.bz2 b/.github/test-data/synthea/e78fd9c5-5c89-26ca-d397-e9da30700444.json.bz2 similarity index 100% rename from .github/test-data/e78fd9c5-5c89-26ca-d397-e9da30700444.json.bz2 rename to .github/test-data/synthea/e78fd9c5-5c89-26ca-d397-e9da30700444.json.bz2 diff --git a/.github/test-data/e8247f30-fc71-a582-66e5-1c2c0c097fc8.json.bz2 b/.github/test-data/synthea/e8247f30-fc71-a582-66e5-1c2c0c097fc8.json.bz2 similarity index 100% rename from .github/test-data/e8247f30-fc71-a582-66e5-1c2c0c097fc8.json.bz2 rename to .github/test-data/synthea/e8247f30-fc71-a582-66e5-1c2c0c097fc8.json.bz2 diff --git a/.github/test-data/ea84fe02-2e40-bf0f-da50-56d2786b8162.json.bz2 b/.github/test-data/synthea/ea84fe02-2e40-bf0f-da50-56d2786b8162.json.bz2 similarity index 100% rename from .github/test-data/ea84fe02-2e40-bf0f-da50-56d2786b8162.json.bz2 rename to .github/test-data/synthea/ea84fe02-2e40-bf0f-da50-56d2786b8162.json.bz2 diff --git a/.github/test-data/eff34607-816a-5c0c-0ed5-47587311b1e9.json.bz2 b/.github/test-data/synthea/eff34607-816a-5c0c-0ed5-47587311b1e9.json.bz2 similarity index 100% rename from .github/test-data/eff34607-816a-5c0c-0ed5-47587311b1e9.json.bz2 rename to .github/test-data/synthea/eff34607-816a-5c0c-0ed5-47587311b1e9.json.bz2 diff --git a/.github/test-data/effb1622-6779-27de-dd68-ba7a53a99eb2.json.bz2 b/.github/test-data/synthea/effb1622-6779-27de-dd68-ba7a53a99eb2.json.bz2 similarity index 100% rename from .github/test-data/effb1622-6779-27de-dd68-ba7a53a99eb2.json.bz2 rename to .github/test-data/synthea/effb1622-6779-27de-dd68-ba7a53a99eb2.json.bz2 diff --git a/.github/test-data/f0f322e5-2683-5a04-0e17-3b765f92072f.json.bz2 b/.github/test-data/synthea/f0f322e5-2683-5a04-0e17-3b765f92072f.json.bz2 similarity index 100% rename from .github/test-data/f0f322e5-2683-5a04-0e17-3b765f92072f.json.bz2 rename to .github/test-data/synthea/f0f322e5-2683-5a04-0e17-3b765f92072f.json.bz2 diff --git a/.github/test-data/f500d29f-be62-9008-43c5-e2c173dde9bd.json.bz2 b/.github/test-data/synthea/f500d29f-be62-9008-43c5-e2c173dde9bd.json.bz2 similarity index 100% rename from .github/test-data/f500d29f-be62-9008-43c5-e2c173dde9bd.json.bz2 rename to .github/test-data/synthea/f500d29f-be62-9008-43c5-e2c173dde9bd.json.bz2 diff --git a/.github/test-data/f804dced-f61f-f1a9-00ef-01b81ed2c6f9.json.bz2 b/.github/test-data/synthea/f804dced-f61f-f1a9-00ef-01b81ed2c6f9.json.bz2 similarity index 100% rename from .github/test-data/f804dced-f61f-f1a9-00ef-01b81ed2c6f9.json.bz2 rename to .github/test-data/synthea/f804dced-f61f-f1a9-00ef-01b81ed2c6f9.json.bz2 diff --git a/.github/test-data/f92fdc8c-3fad-641d-d003-45ed72b50a12.json.bz2 b/.github/test-data/synthea/f92fdc8c-3fad-641d-d003-45ed72b50a12.json.bz2 similarity index 100% rename from .github/test-data/f92fdc8c-3fad-641d-d003-45ed72b50a12.json.bz2 rename to .github/test-data/synthea/f92fdc8c-3fad-641d-d003-45ed72b50a12.json.bz2 diff --git a/.github/test-data/fa7ff0de-a190-28a1-ccb8-515bc6ee8541.json.bz2 b/.github/test-data/synthea/fa7ff0de-a190-28a1-ccb8-515bc6ee8541.json.bz2 similarity index 100% rename from .github/test-data/fa7ff0de-a190-28a1-ccb8-515bc6ee8541.json.bz2 rename to .github/test-data/synthea/fa7ff0de-a190-28a1-ccb8-515bc6ee8541.json.bz2 diff --git a/.github/test-data/fb08980f-4a77-f46d-0b2c-dba79a247437.json.bz2 b/.github/test-data/synthea/fb08980f-4a77-f46d-0b2c-dba79a247437.json.bz2 similarity index 100% rename from .github/test-data/fb08980f-4a77-f46d-0b2c-dba79a247437.json.bz2 rename to .github/test-data/synthea/fb08980f-4a77-f46d-0b2c-dba79a247437.json.bz2 diff --git a/.github/test-data/fbe5ba5b-cb6a-c511-7ada-612173191d63.json.bz2 b/.github/test-data/synthea/fbe5ba5b-cb6a-c511-7ada-612173191d63.json.bz2 similarity index 100% rename from .github/test-data/fbe5ba5b-cb6a-c511-7ada-612173191d63.json.bz2 rename to .github/test-data/synthea/fbe5ba5b-cb6a-c511-7ada-612173191d63.json.bz2 diff --git a/.github/test-data/fcd31792-91d8-982e-8e28-ef1eb284e260.json.bz2 b/.github/test-data/synthea/fcd31792-91d8-982e-8e28-ef1eb284e260.json.bz2 similarity index 100% rename from .github/test-data/fcd31792-91d8-982e-8e28-ef1eb284e260.json.bz2 rename to .github/test-data/synthea/fcd31792-91d8-982e-8e28-ef1eb284e260.json.bz2 diff --git a/.github/test-data/fee04478-ddcd-4fe8-02c4-d15fe97bbce3.json.bz2 b/.github/test-data/synthea/fee04478-ddcd-4fe8-02c4-d15fe97bbce3.json.bz2 similarity index 100% rename from .github/test-data/fee04478-ddcd-4fe8-02c4-d15fe97bbce3.json.bz2 rename to .github/test-data/synthea/fee04478-ddcd-4fe8-02c4-d15fe97bbce3.json.bz2 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 10c85e5c8..36788b519 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -303,17 +303,6 @@ jobs: - name: Check out Git repository uses: actions/checkout@v2 - - name: Setup Java - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Clojure - uses: DeLaGuardo/setup-clojure@master - with: - tools-deps: '1.10.3.1029' - - name: Install Blazectl run: .github/scripts/install-blazectl.sh @@ -339,8 +328,14 @@ jobs: - name: Check Capability Statement run: .github/scripts/check-capability-statement.sh + - name: Check Referential Integrity Enforced + run: .github/scripts/check-referential-integrity-enforced.sh + - name: Load Data - run: blazectl --server http://localhost:8080/fhir upload .github/test-data + run: blazectl --server http://localhost:8080/fhir upload .github/test-data/synthea + + - name: Check Total-Number of Resources are 92114 + run: .github/scripts/check-total-number-of-resources.sh 92114 - name: Count Resources run: blazectl --server http://localhost:8080/fhir count-resources @@ -459,6 +454,48 @@ jobs: - name: Prometheus Metrics run: curl -f http://localhost:8081/metrics + not-enforcing-referential-integrity-test: + needs: build + runs-on: ubuntu-20.04 + + steps: + - name: Check out Git repository + uses: actions/checkout@v2 + + - name: Install Blazectl + run: .github/scripts/install-blazectl.sh + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.CR_PAT }} + + - name: Pull Docker Image + run: docker pull ghcr.io/samply/blaze:sha-${{ github.sha }} + + - name: Run Blaze + run: docker run --name blaze -d -e JAVA_TOOL_OPTIONS=-Xmx2g -e ENFORCE_REFERENTIAL_INTEGRITY=false -p 8080:8080 -v blaze-data:/app/data ghcr.io/samply/blaze:sha-${{ github.sha }} + + - name: Sleep 60 Seconds + run: sleep 60 + + - name: Docker Logs + run: docker logs blaze + + - name: Check Capability Statement + run: .github/scripts/check-capability-statement.sh + + - name: Check Referential Integrity Not Enforced + run: .github/scripts/check-referential-integrity-not-enforced.sh + + - name: Load Data + run: blazectl --server http://localhost:8080/fhir upload -c1 .github/test-data/etl + + - name: Check Total-Number of Resources are 5 + run: .github/scripts/check-total-number-of-resources.sh 5 + jepsen-test: needs: build runs-on: ubuntu-20.04 @@ -556,23 +593,6 @@ jobs: - name: Check out Git repository uses: actions/checkout@v2 - - name: Setup Java - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Clojure - uses: DeLaGuardo/setup-clojure@master - with: - tools-deps: '1.10.3.1029' - - - name: APT Update - run: sudo apt-get update - - - name: Install Gnuplot - run: sudo apt-get install gnuplot - - name: Install Blazectl run: .github/scripts/install-blazectl.sh @@ -613,8 +633,14 @@ jobs: - name: Check Capability Statement run: .github/scripts/check-capability-statement.sh + - name: Check Referential Integrity Enforced + run: .github/scripts/check-referential-integrity-enforced.sh + - name: Load Data - run: blazectl --server http://localhost:8080/fhir upload .github/test-data + run: blazectl --server http://localhost:8080/fhir upload .github/test-data/synthea + + - name: Check Total-Number of Resources are 92114 + run: .github/scripts/check-total-number-of-resources.sh 92114 - name: Count Resources run: blazectl --server http://localhost:8080/fhir count-resources diff --git a/CHANGELOG.md b/CHANGELOG.md index bdda7162b..5babd7402 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## v0.14.0 + +### New Features + +* Allow Disabling Referential Integrity ([#544](https://github.com/samply/blaze/pull/544)) + +The full changelog can be found [here](https://github.com/samply/blaze/milestone/11?closed=1). + ## v0.13.5 ### Bugfixes diff --git a/docs/deployment/docker-deployment.md b/docs/deployment/docker-deployment.md index 0ddb3113b..979f948ff 100644 --- a/docs/deployment/docker-deployment.md +++ b/docs/deployment/docker-deployment.md @@ -27,7 +27,7 @@ Blaze should log something like this: 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:64] - JVM version: 16.0.2 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:65] - Maximum available memory: 1738 MiB 2021-06-27T11:02:37.835Z ee086ef908c1 main INFO [blaze.core:66] - Number of available processors: 8 -2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.13.5 in 8.2 seconds +2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.14.0 in 8.2 seconds ``` In order to test connectivity, query the health endpoint: @@ -47,7 +47,7 @@ that should return: ```json { "name": "Blaze", - "version": "0.13.5" + "version": "0.14.0" } ``` diff --git a/docs/deployment/environment-variables.md b/docs/deployment/environment-variables.md index b469d0f1d..ec820790f 100644 --- a/docs/deployment/environment-variables.md +++ b/docs/deployment/environment-variables.md @@ -80,6 +80,7 @@ More information about distributed deployment are available [here](distributed.m | JAVA_TOOL_OPTIONS | — | | JVM options \(Docker only\) | | FHIR_OPERATION_EVALUATE_MEASURE_THREADS | 4 | v0.8 | The maximum number of parallel $evaluate-measure executions. Not the same as the number of threads used for measure evaluation which equal to the number of available processors. | | OPENID_PROVIDER_URL | - | v0.11 | [OpenID Connect][4] provider URL to enable [authentication][5] | +| ENFORCE_REFERENTIAL_INTEGRITY | true | v0.14 | Enforce referential integrity on resource create, update and delete. It's enabled by default but can be disabled on proxy/middleware/secondary systems were a primary system ensures referential integrity. | ### Common JAVA_TOOL_OPTIONS diff --git a/docs/deployment/manual-deployment.md b/docs/deployment/manual-deployment.md index 3e18c6554..208afaeff 100644 --- a/docs/deployment/manual-deployment.md +++ b/docs/deployment/manual-deployment.md @@ -2,12 +2,12 @@ The installation works under Windows, Linux and macOS. The only dependency is an installed OpenJDK 11. Blaze is tested with [AdoptOpenJDK][1]. -Blaze runs on the JVM and comes as single JAR file. Download the most recent version [here](https://github.com/samply/blaze/releases/tag/v0.13.1). Look for `blaze-0.13.5-standalone.jar`. +Blaze runs on the JVM and comes as single JAR file. Download the most recent version [here](https://github.com/samply/blaze/releases/tag/v0.13.1). Look for `blaze-0.14.0-standalone.jar`. After the download, you can start blaze with the following command (Linux, macOS): ```sh -java -jar blaze-0.13.5-standalone.jar -m blaze.core +java -jar blaze-0.14.0-standalone.jar -m blaze.core ``` Blaze will run with an in-memory, volatile database for testing and demo purposes. @@ -17,14 +17,14 @@ Blaze can be run with durable storage by setting the environment variables `STOR Under Linux/macOS: ```sh -STORAGE=standalone java -jar blaze-0.13.5-standalone.jar -m blaze.core +STORAGE=standalone java -jar blaze-0.14.0-standalone.jar -m blaze.core ``` Under Windows, you need to set the Environment variables in the PowerShell before starting Blaze: ```powershell $Env:STORAGE="standalone" -java -jar blaze-0.13.5-standalone.jar -m blaze.core +java -jar blaze-0.14.0-standalone.jar -m blaze.core ``` This will create three directories called `index`, `transaction` and `resource` inside the current working directory, one for each database part used. @@ -42,7 +42,7 @@ The output should look like this: 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:64] - JVM version: 16.0.2 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:65] - Maximum available memory: 1738 MiB 2021-06-27T11:02:37.835Z ee086ef908c1 main INFO [blaze.core:66] - Number of available processors: 8 -2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.13.5 in 8.2 seconds +2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.14.0 in 8.2 seconds ``` In order to test connectivity, query the health endpoint: @@ -62,7 +62,7 @@ that should return: ```json { "name": "Blaze", - "version": "0.13.5" + "version": "0.14.0" } ``` diff --git a/docs/importing-data.md b/docs/importing-data.md index d17b5c62e..f7ba1a632 100644 --- a/docs/importing-data.md +++ b/docs/importing-data.md @@ -1,6 +1,6 @@ # Importing Data -In order to use Blaze for queries, you have to import your data. Although you can use the full functionality of the [FHIR RESTful API](https://www.hl7.org/fhir/http.html) available under `http://localhost:8080/fhir` to create resources, the easiest way is to download [blazectl](https://github.com/samply/blazectl/releases/tag/v0.2.0) to upload [bundles](https://www.hl7.org/fhir/bundle.html). +In order to use Blaze for queries, you have to import your data. Although you can use the full functionality of the [FHIR RESTful API](https://www.hl7.org/fhir/http.html) available under `http://localhost:8080/fhir` to create resources, the easiest way is to download [blazectl](https://github.com/samply/blazectl/releases/tag/v0.8.1) to upload [bundles](https://www.hl7.org/fhir/bundle.html). First you should test connectivity by counting already available resources in Blaze which should be zero: @@ -71,3 +71,16 @@ Specimen : 100 total : 742 ``` +## Disabling Referential Integrity Checks + +If your primary date source ensures referential integrity already, and you can't import the resources into Blaze in the right order or bunldes so that the referential integrity will be maintained per transaction, you can disable the referential integrity checks in Blaze by setting the env var `ENFORCE_REFERENTIAL_INTEGRITY` to `false`. + +The checks can be enabled/disabled at each start of Blaze. You can check whether the checks are enabled by executing: + +````sh +curl -s http://localhost:8080/fhir/metadata | jq -r 'isempty(.rest[].resource[].referencePolicy[] | select(. == "enforced")) | not' +```` + +That command return `true` or `false` depending on whether the referential integrity checks are enabled or not. + +Please be aware that Blaze doesn't check the referential integrity of already imported resource if you enable the checks after you have already imported resources. By disabling the referential integrity checks at some time, you will have a database that can contain stale references. diff --git a/modules/cql/src/blaze/elm/compiler/external_data.clj b/modules/cql/src/blaze/elm/compiler/external_data.clj index 6e3fb1d79..6880d771c 100644 --- a/modules/cql/src/blaze/elm/compiler/external_data.clj +++ b/modules/cql/src/blaze/elm/compiler/external_data.clj @@ -4,14 +4,13 @@ Section numbers are according to https://cql.hl7.org/04-logicalspecification.html." (:require - [blaze.anomaly :as ba :refer [throw-anom]] + [blaze.anomaly :as ba :refer [if-ok]] [blaze.db.api :as d] [blaze.db.api-spec] [blaze.elm.compiler.core :as core] [blaze.elm.spec] [blaze.elm.util :as elm-util] - [clojure.string :as str] - [cognitect.anomalies :as anom])) + [clojure.string :as str])) (set! *warn-on-reflection* true) @@ -139,11 +138,10 @@ (if-let [result-type-name (:result-type-name (meta context-expr))] (let [[value-type-ns context-type] (elm-util/parse-qualified-name result-type-name)] (if (= "http://hl7.org/fhir" value-type-ns) - (let [clauses [(into [code-property] (map code->clause-value) codes)] - query (d/compile-compartment-query node context-type data-type clauses)] - (if (::anom/category query) - (throw (ex-info (::anom/message query) query)) - (->WithRelatedContextQueryRetrieveExpression context-expr query))) + (let [clauses [(into [code-property] (map code->clause-value) codes)]] + (if-ok [query (d/compile-compartment-query node context-type data-type clauses)] + (->WithRelatedContextQueryRetrieveExpression context-expr query) + ba/throw-anom)) (->WithRelatedContextCodeRetrieveExpression context-expr data-type @@ -159,13 +157,12 @@ (reify core/Expression (-eval [_ {:keys [db]} _ _] (into [] (d/type-list db data-type)))) - (let [clauses [(into [code-property] (map code->clause-value) codes)] - query (d/compile-type-query node data-type clauses)] - (if (::anom/category query) - (throw (ex-info (::anom/message query) query)) + (let [clauses [(into [code-property] (map code->clause-value) codes)]] + (if-ok [query (d/compile-type-query node data-type clauses)] (reify core/Expression (-eval [_ {:keys [db]} _ _] - (into [] (d/execute-query db query)))))))) + (into [] (d/execute-query db query)))) + ba/throw-anom)))) (defn- expr* [node eval-context data-type code-property codes] @@ -211,4 +208,4 @@ data-type code-property (some->> codes-expr (core/compile* context))) - (throw-anom (unsupported-type-namespace-anom type-ns))))) + (ba/throw-anom (unsupported-type-namespace-anom type-ns))))) diff --git a/modules/cql/src/blaze/elm/compiler/queries.clj b/modules/cql/src/blaze/elm/compiler/queries.clj index 4379b8b25..8414a431e 100644 --- a/modules/cql/src/blaze/elm/compiler/queries.clj +++ b/modules/cql/src/blaze/elm/compiler/queries.clj @@ -335,6 +335,18 @@ (some #(when (contains? (:life/scopes %) alias) %) operands)) +(def ^:private missing-lhs-operand-anom + (ba/incorrect (format "Unsupported call without left-hand-side operand."))) + + +(defn- missing-rhs-operand-msg [alias] + (format "Unsupported call without right-hand-side operand with alias `%s`." + alias)) + +(defn- missing-rhs-operand-anom [alias] + (ba/incorrect (missing-rhs-operand-msg alias))) + + (defn compile-with-equiv-clause "We use the terms `lhs` and `rhs` for left-hand-side and right-hand-side of the semi-join here. @@ -355,12 +367,8 @@ (core/compile* (dissoc context :life/single-query-scope)))] (->WithXformFactory rhs rhs-operand such-that lhs-operand single-query-scope)) - (throw-anom - (ba/incorrect - (format "Unsupported call without left-hand-side operand.")))) - (throw-anom - (ba/incorrect - (format "Unsupported call without right-hand-side operand with alias `%s`." alias)))) + (throw-anom missing-lhs-operand-anom)) + (throw-anom (missing-rhs-operand-anom alias))) (throw-anom (ba/incorrect (format "Unsupported call without single query scope."))))) diff --git a/modules/cql/src/blaze/elm/deps_infer.clj b/modules/cql/src/blaze/elm/deps_infer.clj index f16b3650d..f76abb8b0 100644 --- a/modules/cql/src/blaze/elm/deps_infer.clj +++ b/modules/cql/src/blaze/elm/deps_infer.clj @@ -2,7 +2,6 @@ (:require [blaze.elm.spec] [clojure.set :as set] - [clojure.spec.alpha :as s] [cuerdas.core :as str])) @@ -19,9 +18,6 @@ (mapv #(update % :expression infer-deps) expression-defs)) -(s/fdef infer-library-deps - :args (s/cat :library :elm/library)) - (defn infer-library-deps [library] (update-in library [:statements :def] update-expression-defs)) @@ -529,6 +525,12 @@ (derive :elm.deps.type/exists :elm.deps.type/unary-expression) +;; 20.10. First +(defmethod infer-deps :elm.deps.type/first + [expression] + (update expression :source infer-deps)) + + ;; 20.25. SingletonFrom (derive :elm.deps.type/singleton-from :elm.deps.type/unary-expression) diff --git a/modules/cql/src/blaze/elm/equiv_relationships.clj b/modules/cql/src/blaze/elm/equiv_relationships.clj index 28c4a8010..0c9efee08 100644 --- a/modules/cql/src/blaze/elm/equiv_relationships.clj +++ b/modules/cql/src/blaze/elm/equiv_relationships.clj @@ -3,7 +3,6 @@ expression resulting in equiv semi-joins and semi-differences." (:require [blaze.elm.spec] - [clojure.spec.alpha :as s] [cuerdas.core :as str])) @@ -11,16 +10,13 @@ {:arglists '([expression])} (fn [{:keys [type]}] (assert type) - (keyword "elm.normalizer.type" (str/kebab type)))) + (keyword "elm.equiv-relationships.type" (str/kebab type)))) (defn- update-expression-defs [expression-defs] (mapv #(update % :expression find-equiv-rels) expression-defs)) -(s/fdef find-equiv-rels-library - :args (s/cat :library :elm/library)) - (defn find-equiv-rels-library [library] (update-in library [:statements :def] update-expression-defs)) @@ -30,12 +26,12 @@ expression) -(defmethod find-equiv-rels :elm.normalizer.type/unary-expression +(defmethod find-equiv-rels :elm.equiv-relationships.type/unary-expression [expression] (update expression :operand find-equiv-rels)) -(defmethod find-equiv-rels :elm.normalizer.type/multiary-expression +(defmethod find-equiv-rels :elm.equiv-relationships.type/multiary-expression [expression] (update expression :operand #(mapv find-equiv-rels %))) @@ -87,16 +83,31 @@ relationship))) -(defmethod find-equiv-rels :elm.normalizer.type/query +(defmethod find-equiv-rels :elm.equiv-relationships.type/query [{relationships :relationship :as expression}] (assoc expression :relationship (mapv find-equiv-relationship relationships))) + ;; 20. List Operators +;; 20.4. Distinct +(derive :elm.equiv-relationships.type/distinct :elm.equiv-relationships.type/unary-expression) + + ;; 20.8. Exists -(derive :elm.normalizer.type/exists :elm.normalizer.type/unary-expression) +(derive :elm.equiv-relationships.type/exists :elm.equiv-relationships.type/unary-expression) + + +;; 20.10. First +(defmethod find-equiv-rels :elm.equiv-relationships.type/first + [expression] + (update expression :source find-equiv-rels)) + + +;; 20.11. Flatten +(derive :elm.equiv-relationships.type/flatten :elm.equiv-relationships.type/unary-expression) ;; 20.25. SingletonFrom -(derive :elm.normalizer.type/singleton-from :elm.normalizer.type/unary-expression) +(derive :elm.equiv-relationships.type/singleton-from :elm.equiv-relationships.type/unary-expression) diff --git a/modules/cql/src/blaze/elm/normalizer.clj b/modules/cql/src/blaze/elm/normalizer.clj index cfd88bb86..37e300129 100644 --- a/modules/cql/src/blaze/elm/normalizer.clj +++ b/modules/cql/src/blaze/elm/normalizer.clj @@ -397,6 +397,30 @@ +;; 20. List Operators + +;; 20.4. Distinct +(derive :elm.normalizer.type/distinct :elm.normalizer.type/unary-expression) + +;; 20.8. Exists +(derive :elm.normalizer.type/exists :elm.normalizer.type/unary-expression) + + +;; 20.10. First +(defmethod normalize :elm.normalizer.type/first + [expression] + (update expression :source normalize)) + + +;; 20.11. Flatten +(derive :elm.normalizer.type/flatten :elm.normalizer.type/unary-expression) + + +;; 20.25. SingletonFrom +(derive :elm.normalizer.type/singleton-from :elm.normalizer.type/unary-expression) + + + ;; 23. Clinical Operators ;; 23.3. CalculateAge diff --git a/modules/cql/test/blaze/elm/compiler/external_data_test.clj b/modules/cql/test/blaze/elm/compiler/external_data_test.clj index 1d039c556..04709d2bc 100644 --- a/modules/cql/test/blaze/elm/compiler/external_data_test.clj +++ b/modules/cql/test/blaze/elm/compiler/external_data_test.clj @@ -224,17 +224,37 @@ {:def [{:name "sys-def-225944" :id "system-225806"}]}}} - elm (elm/retrieve - {:type "Medication" - :codes #elm/list[#elm/code["sys-def-225944" - "code-225809"]]}) + elm #elm/retrieve + {:type "Medication" + :codes #elm/list[#elm/code["sys-def-225944" + "code-225809"]]} expr (c/compile context elm) db (d/db node)] (given (core/-eval expr {:db db} nil nil) count := 1 [0 fhir-spec/fhir-type] := :fhir/Medication - [0 :id] := "0"))))) + [0 :id] := "0")))) + + (testing "unknown code property" + (with-system [{:blaze.db/keys [node]} mem-node-system] + (let [context + {:node node + :eval-context "Unfiltered" + :library + {:codeSystems + {:def + [{:name "sys-def-225944" + :id "system-225806"}]}}} + elm #elm/retrieve + {:type "Medication" + :codes #elm/list[#elm/code["sys-def-225944" + "code-225809"]] + :code-property "foo"}] + + (given (ba/try-anomaly (c/compile context elm)) + ::anom/category := ::anom/not-found + ::anom/message := "The search-param with code `foo` and type `Medication` was not found."))))) (testing "with related context" (testing "with pre-compiled database query" @@ -245,13 +265,32 @@ {:def [{:name "name-174207" :resultTypeName "{http://hl7.org/fhir}Patient"}]}} - elm {:type "Retrieve" - :dataType "{http://hl7.org/fhir}Observation" - :context #elm/expression-ref "name-174207" - :codes #elm/list [#elm/code ["sys-def-174848" "code-174911"]]} + elm #elm/retrieve + {:type "Observation" + :context #elm/expression-ref "name-174207" + :codes #elm/list[#elm/code["sys-def-174848" + "code-174911"]]} expr (c/compile {:node node :library library} elm)] (given expr - type := WithRelatedContextQueryRetrieveExpression))))) + type := WithRelatedContextQueryRetrieveExpression)))) + + (testing "unknown code property" + (with-system [{:blaze.db/keys [node]} mem-node-system] + (let [library {:codeSystems + {:def [{:name "sys-def-174848" :id "system-174915"}]} + :statements + {:def + [{:name "name-174207" + :resultTypeName "{http://hl7.org/fhir}Patient"}]}} + elm #elm/retrieve + {:type "Observation" + :context #elm/expression-ref "name-174207" + :codes #elm/list[#elm/code["sys-def-174848" + "code-174911"]] + :code-property "foo"}] + (given (ba/try-anomaly (c/compile {:node node :library library} elm)) + ::anom/category := ::anom/not-found + ::anom/message := "The search-param with code `foo` and type `Observation` was not found."))))) (testing "with unsupported type namespace" (let [elm {:type "Retrieve" :dataType "{foo}Bar"}] diff --git a/modules/cql/test/blaze/elm/compiler/list_operators_test.clj b/modules/cql/test/blaze/elm/compiler/list_operators_test.clj index 71285fc49..29fc02a3b 100644 --- a/modules/cql/test/blaze/elm/compiler/list_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/list_operators_test.clj @@ -165,7 +165,7 @@ ;; ;; If the argument is null, the result is null. (deftest compile-first-test - (are [source res] (= res (core/-eval (c/compile {} {:type "First" :source source}) {} nil nil)) + (are [source res] (= res (core/-eval (c/compile {} (elm/first source)) {} nil nil)) #elm/list [#elm/integer"1"] 1 #elm/list [#elm/integer"1" #elm/integer"2"] 1 diff --git a/modules/cql/test/blaze/elm/deps_infer_spec.clj b/modules/cql/test/blaze/elm/deps_infer_spec.clj new file mode 100644 index 000000000..9d0332ce8 --- /dev/null +++ b/modules/cql/test/blaze/elm/deps_infer_spec.clj @@ -0,0 +1,9 @@ +(ns blaze.elm.deps-infer-spec + (:require + [blaze.elm.deps-infer :as deps-infer] + [blaze.elm.spec] + [clojure.spec.alpha :as s])) + + +(s/fdef deps-infer/infer-library-deps + :args (s/cat :library :elm/library)) diff --git a/modules/cql/test/blaze/elm/equiv_relationships_spec.clj b/modules/cql/test/blaze/elm/equiv_relationships_spec.clj new file mode 100644 index 000000000..221ef613e --- /dev/null +++ b/modules/cql/test/blaze/elm/equiv_relationships_spec.clj @@ -0,0 +1,9 @@ +(ns blaze.elm.equiv-relationships-spec + (:require + [blaze.elm.equiv-relationships :as equiv-relationships] + [blaze.elm.spec] + [clojure.spec.alpha :as s])) + + +(s/fdef equiv-relationships/find-equiv-rels-library + :args (s/cat :library :elm/library)) diff --git a/modules/cql/test/blaze/elm/equiv_relationships_test.clj b/modules/cql/test/blaze/elm/equiv_relationships_test.clj index 5dcbe5f54..e1827f054 100644 --- a/modules/cql/test/blaze/elm/equiv_relationships_test.clj +++ b/modules/cql/test/blaze/elm/equiv_relationships_test.clj @@ -1,11 +1,11 @@ (ns blaze.elm.equiv-relationships-test (:require - [blaze.elm.equiv-relationships - :refer [split-by-first-equal-expression]] - [blaze.elm.literal] + [blaze.elm.equiv-relationships :as equiv-relationships] + [blaze.elm.equiv-relationships-spec] + [blaze.elm.literal :as elm] [blaze.elm.literal-spec] [clojure.spec.test.alpha :as st] - [clojure.test :as test :refer [are deftest]])) + [clojure.test :as test :refer [are deftest is testing]])) (st/instrument) @@ -22,7 +22,7 @@ (deftest split-by-first-equal-expression-test (are [input equal-expr rest-expr] - (let [res (split-by-first-equal-expression input)] + (let [res (equiv-relationships/split-by-first-equal-expression input)] (and (= equal-expr (:equal-expr res)) (= rest-expr (:rest-expr res)))) {:type "Equal"} @@ -72,3 +72,61 @@ {:type "Equal" :pos 2}]} {:type "Equal" :pos 1} {:type "Equal" :pos 2})) + + +(def query + {:type "Query" + :source + [{:expression + {:type "Retrieve" + :dataType "{http://hl7.org/fhir}Condition"} + :alias "C"}] + :relationship + [{:type "With" + :alias "P" + :expression + {:type "Retrieve" :dataType "{http://hl7.org/fhir}Procedure"} + :suchThat + {:type "Equal" + :operand [#elm/integer "1" #elm/integer "1"]}}]}) + + +(def equiv-query + {:type "Query" + :source + [{:expression + {:type "Retrieve" + :dataType "{http://hl7.org/fhir}Condition"} + :alias "C"}] + :relationship + [{:type "WithEquiv" + :alias "P" + :expression + {:type "Retrieve" :dataType "{http://hl7.org/fhir}Procedure"} + :equivOperand + [#elm/integer "1" #elm/integer "1"]}]}) + + +(deftest find-equiv-rels-test + (testing "query" + (is (= (equiv-relationships/find-equiv-rels query) equiv-query))) + + (testing "20.4. Distinct" + (is (= (equiv-relationships/find-equiv-rels (elm/distinct query)) + (elm/distinct equiv-query)))) + + (testing "20.8. Exists" + (is (= (equiv-relationships/find-equiv-rels (elm/exists query)) + (elm/exists equiv-query)))) + + (testing "20.10. First" + (is (= (equiv-relationships/find-equiv-rels (elm/first query)) + (elm/first equiv-query)))) + + (testing "20.11. Flatten" + (is (= (equiv-relationships/find-equiv-rels (elm/flatten query)) + (elm/flatten equiv-query)))) + + (testing "20.25. SingletonFrom" + (is (= (equiv-relationships/find-equiv-rels (elm/singleton-from query)) + (elm/singleton-from equiv-query))))) diff --git a/modules/cql/test/blaze/elm/literal.clj b/modules/cql/test/blaze/elm/literal.clj index 358d71ef4..eadc830cc 100644 --- a/modules/cql/test/blaze/elm/literal.clj +++ b/modules/cql/test/blaze/elm/literal.clj @@ -1,6 +1,6 @@ (ns blaze.elm.literal (:refer-clojure - :exclude [and boolean count distinct flatten list max min not or time]) + :exclude [and boolean count distinct first flatten list max min not or time]) (:require [blaze.elm.spec] [clojure.spec.alpha :as s] @@ -102,12 +102,16 @@ ;; 11. External Data ;; 11.1. Retrieve -(defn retrieve [{:keys [type codes]}] +(defn retrieve [{:keys [type codes code-property context]}] (cond-> {:type "Retrieve" :dataType (str "{http://hl7.org/fhir}" type)} codes - (assoc :codes codes))) + (assoc :codes codes) + code-property + (assoc :codeProperty code-property) + context + (assoc :context context))) @@ -528,6 +532,11 @@ {:type "Exists" :operand list}) +;; 20.10. First +(defn first [source] + {:type "First" :source source}) + + ;; 20.11. Flatten (defn flatten [list] {:type "Flatten" :operand list}) diff --git a/modules/cql/test/blaze/elm/literal_spec.clj b/modules/cql/test/blaze/elm/literal_spec.clj index 621121cb9..84d84fa42 100644 --- a/modules/cql/test/blaze/elm/literal_spec.clj +++ b/modules/cql/test/blaze/elm/literal_spec.clj @@ -366,6 +366,12 @@ :ret :elm/expression) +;; 20.10. First +(s/fdef literal/first + :args (s/cat :source :elm/expression) + :ret :elm/expression) + + ;; 20.11. Flatten (s/fdef literal/flatten :args (s/cat :list :elm/expression) diff --git a/modules/cql/test/blaze/elm/normalizer_test.clj b/modules/cql/test/blaze/elm/normalizer_test.clj index a6209dd76..b768545d8 100644 --- a/modules/cql/test/blaze/elm/normalizer_test.clj +++ b/modules/cql/test/blaze/elm/normalizer_test.clj @@ -2,7 +2,7 @@ "Section numbers are according to https://cql.hl7.org/04-logicalspecification.html." (:require - [blaze.elm.literal] + [blaze.elm.literal :as elm] [blaze.elm.normalizer :refer [normalize]] [blaze.elm.normalizer-spec] [clojure.spec.test.alpha :as st] @@ -242,3 +242,36 @@ :condition := (normalize expression-1) :then := (normalize expression-2) :else := (normalize expression-3)))) + + + +;; 20. List Operators + +;; 20.4. Distinct +(deftest normalize-distinct-test + (given (normalize (elm/distinct expression-1)) + :operand := (normalize expression-1))) + + +;; 20.8. Exists +(deftest normalize-exists-test + (given (normalize (elm/exists expression-1)) + :operand := (normalize expression-1))) + + +;; 20.10. First +(deftest normalize-first-test + (given (normalize (elm/first expression-1)) + :source := (normalize expression-1))) + + +;; 20.11. Flatten +(deftest normalize-flatten-test + (given (normalize (elm/flatten expression-1)) + :operand := (normalize expression-1))) + + +;; 20.25. SingletonFrom +(deftest normalize-singleton-from-test + (given (normalize (elm/singleton-from expression-1)) + :operand := (normalize expression-1))) diff --git a/modules/cql/test/data_readers.clj b/modules/cql/test/data_readers.clj index db40e8c3e..0c537430a 100644 --- a/modules/cql/test/data_readers.clj +++ b/modules/cql/test/data_readers.clj @@ -9,6 +9,7 @@ elm/quantity blaze.elm.literal/quantity elm/parameter-ref blaze.elm.literal/parameter-ref elm/expression-ref blaze.elm.literal/expression-ref + elm/retrieve blaze.elm.literal/retrieve elm/equal blaze.elm.literal/equal elm/equivalent blaze.elm.literal/equivalent elm/greater blaze.elm.literal/greater @@ -50,6 +51,9 @@ elm/interval blaze.elm.literal/interval elm/intersect blaze.elm.literal/intersect elm/current blaze.elm.literal/current + elm/distinct blaze.elm.literal/distinct + elm/exists blaze.elm.literal/exists + elm/first blaze.elm.literal/first elm/singleton-from blaze.elm.literal/singleton-from elm/as blaze.elm.literal/as elm/can-convert-quantity blaze.elm.literal/can-convert-quantity diff --git a/modules/db-resource-store-cassandra/src/blaze/db/resource_store/cassandra.clj b/modules/db-resource-store-cassandra/src/blaze/db/resource_store/cassandra.clj index afce51de0..564154e7d 100644 --- a/modules/db-resource-store-cassandra/src/blaze/db/resource_store/cassandra.clj +++ b/modules/db-resource-store-cassandra/src/blaze/db/resource_store/cassandra.clj @@ -166,7 +166,7 @@ ::cass/request-timeout])) -(defn init-msg [config] +(defn- init-msg [config] (str "Open Cassandra resource store with the following settings: " (cass/format-config config))) diff --git a/modules/db-stub/src/blaze/db/api_stub.clj b/modules/db-stub/src/blaze/db/api_stub.clj index c02635605..8667d84ed 100644 --- a/modules/db-stub/src/blaze/db/api_stub.clj +++ b/modules/db-stub/src/blaze/db/api_stub.clj @@ -19,16 +19,18 @@ [java-time :as time])) -(def mem-node-system +(defn create-mem-node-system [node-config] {:blaze.db/node - {:tx-log (ig/ref :blaze.db/tx-log) - :resource-handle-cache (ig/ref :blaze.db/resource-handle-cache) - :tx-cache (ig/ref :blaze.db/tx-cache) - :indexer-executor (ig/ref :blaze.db.node/indexer-executor) - :resource-store (ig/ref :blaze.db/resource-store) - :kv-store (ig/ref :blaze.db/index-kv-store) - :search-param-registry (ig/ref :blaze.db/search-param-registry) - :poll-timeout (time/millis 10)} + (merge + {:tx-log (ig/ref :blaze.db/tx-log) + :resource-handle-cache (ig/ref :blaze.db/resource-handle-cache) + :tx-cache (ig/ref :blaze.db/tx-cache) + :indexer-executor (ig/ref :blaze.db.node/indexer-executor) + :resource-store (ig/ref :blaze.db/resource-store) + :kv-store (ig/ref :blaze.db/index-kv-store) + :search-param-registry (ig/ref :blaze.db/search-param-registry) + :poll-timeout (time/millis 10)} + node-config) ::tx-log/local {:kv-store (ig/ref :blaze.db/transaction-kv-store) @@ -70,6 +72,10 @@ :blaze.db/search-param-registry {}}) +(def mem-node-system + (create-mem-node-system {})) + + (defmacro with-system-data [[binding-form system] txs & body] `(with-system [system# ~system] (run! #(deref (d/transact (:blaze.db/node system#) %)) ~txs) diff --git a/modules/db-tx-log/src/blaze/db/tx_log/spec.clj b/modules/db-tx-log/src/blaze/db/tx_log/spec.clj index 4d712d574..a28c434e4 100644 --- a/modules/db-tx-log/src/blaze/db/tx_log/spec.clj +++ b/modules/db-tx-log/src/blaze/db/tx_log/spec.clj @@ -23,12 +23,8 @@ :fhir.type/name) -(s/def :blaze.db/local-ref - (s/tuple :fhir.type/name :blaze.resource/id)) - - (s/def :blaze.db.tx-cmd/refs - (s/coll-of :blaze.db/local-ref)) + (s/coll-of :blaze.fhir/local-ref-tuple)) (s/def :blaze.db/t diff --git a/modules/db/src/blaze/db/node.clj b/modules/db/src/blaze/db/node.clj index 4d3139482..57e9200d0 100644 --- a/modules/db/src/blaze/db/node.clj +++ b/modules/db/src/blaze/db/node.clj @@ -232,7 +232,7 @@ (rs/get resource-store hash))) -(defrecord Node [tx-log rh-cache tx-cache kv-store resource-store +(defrecord Node [context tx-log rh-cache tx-cache kv-store resource-store search-param-registry resource-indexer state run? poll-timeout finished] np/Node @@ -252,7 +252,7 @@ (-submit-tx [_ tx-ops] (log/trace "submit" (count tx-ops) "tx-ops") (if-ok [_ (validation/validate-ops tx-ops)] - (let [[tx-cmds entries] (tx/prepare-ops tx-ops)] + (let [[tx-cmds entries] (tx/prepare-ops context tx-ops)] (-> (rs/put! resource-store entries) (ac/then-compose (fn [_] (tx-log/submit tx-log tx-cmds entries))))) ac/completed-future)) @@ -358,6 +358,20 @@ :error-t 0}) +(defn- init-msg + [{:keys [enforce-referential-integrity] + :or {enforce-referential-integrity true}}] + (log/info "Open local database node with" + (if enforce-referential-integrity "enabled" "disabled") + "referential integrity checks")) + + +(defn- ctx + [{:keys [enforce-referential-integrity] + :or {enforce-referential-integrity true}}] + {:blaze.db/enforce-referential-integrity enforce-referential-integrity}) + + (defmethod ig/pre-init-spec :blaze.db/node [_] (s/keys :req-un @@ -367,16 +381,18 @@ ::indexer-executor :blaze.db/kv-store :blaze.db/resource-store - :blaze.db/search-param-registry])) - + :blaze.db/search-param-registry] + :opt-un + [:blaze.db/enforce-referential-integrity])) (defmethod ig/init-key :blaze.db/node [_ {:keys [tx-log resource-handle-cache tx-cache indexer-executor kv-store resource-store search-param-registry poll-timeout] - :or {poll-timeout (time/seconds 1)}}] - (log/info "Open local database node") + :or {poll-timeout (time/seconds 1)} + :as config}] + (init-msg config) (let [resource-indexer (new-resource-indexer search-param-registry kv-store) - node (->Node tx-log resource-handle-cache tx-cache kv-store + node (->Node (ctx config) tx-log resource-handle-cache tx-cache kv-store resource-store search-param-registry resource-indexer (atom (initial-state kv-store)) (volatile! true) diff --git a/modules/db/src/blaze/db/node/transaction.clj b/modules/db/src/blaze/db/node/transaction.clj index b5e4013a5..97f2aada4 100644 --- a/modules/db/src/blaze/db/node/transaction.clj +++ b/modules/db/src/blaze/db/node/transaction.clj @@ -10,13 +10,13 @@ [blaze.fhir.spec.type :as type])) -(defmulti prepare-op first) +(defmulti prepare-op (fn [_ [op]] op)) (defmethod prepare-op :create - [[op resource clauses]] + [{:keys [references-fn]} [op resource clauses]] (let [hash (hash/generate resource) - refs (type/references resource)] + refs (references-fn resource)] {:hash-resource [hash resource] :blaze.db/tx-cmd @@ -32,9 +32,9 @@ (defmethod prepare-op :put - [[op resource matches]] + [{:keys [references-fn]} [op resource matches]] (let [hash (hash/generate resource) - refs (type/references resource)] + refs (references-fn resource)] {:hash-resource [hash resource] :blaze.db/tx-cmd @@ -50,7 +50,7 @@ (defmethod prepare-op :delete - [[_ type id]] + [_ [_ type id]] {:blaze.db/tx-cmd {:op "delete" :type type @@ -61,11 +61,24 @@ (juxt #(mapv :blaze.db/tx-cmd %) #(into {} (map :hash-resource) %))) +(defn- ctx + [{:blaze.db/keys [enforce-referential-integrity] + :or {enforce-referential-integrity true}}] + {:references-fn + (if enforce-referential-integrity + type/references + (constantly nil))}) + + (defn prepare-ops "Splits `tx-ops` into a tuple of :blaze.db/tx-cmds and a map of resource - hashes to resource contents." - [tx-ops] - (split (mapv prepare-op tx-ops))) + hashes to resource contents. + + Puts :refs into the returned :blaze.db/tx-cmds if + :blaze.db/enforce-referential-integrity is true in `context` which is the + default." + [context tx-ops] + (split (mapv (partial prepare-op (ctx context)) tx-ops))) (defn- missing-tx-msg [t] diff --git a/modules/db/src/blaze/db/spec.clj b/modules/db/src/blaze/db/spec.clj index 05d1f90a7..071bb1cd4 100644 --- a/modules/db/src/blaze/db/spec.clj +++ b/modules/db/src/blaze/db/spec.clj @@ -90,3 +90,7 @@ (s/def :blaze.db/tx-ops (s/coll-of :blaze.db/tx-op :kind vector? :min-count 1)) + + +(s/def :blaze.db/enforce-referential-integrity + boolean?) diff --git a/modules/db/test/blaze/db/api_test.clj b/modules/db/test/blaze/db/api_test.clj index fe2313b01..50f67a548 100644 --- a/modules/db/test/blaze/db/api_test.clj +++ b/modules/db/test/blaze/db/api_test.clj @@ -52,16 +52,18 @@ (test/use-fixtures :each fixture) -(def system +(defn create-system [node-config] {:blaze.db/node - {:tx-log (ig/ref :blaze.db/tx-log) - :resource-handle-cache (ig/ref :blaze.db/resource-handle-cache) - :tx-cache (ig/ref :blaze.db/tx-cache) - :indexer-executor (ig/ref :blaze.db.node/indexer-executor) - :resource-store (ig/ref :blaze.db/resource-store) - :kv-store (ig/ref :blaze.db/index-kv-store) - :search-param-registry (ig/ref :blaze.db/search-param-registry) - :poll-timeout (time/millis 10)} + (merge + {:tx-log (ig/ref :blaze.db/tx-log) + :resource-handle-cache (ig/ref :blaze.db/resource-handle-cache) + :tx-cache (ig/ref :blaze.db/tx-cache) + :indexer-executor (ig/ref :blaze.db.node/indexer-executor) + :resource-store (ig/ref :blaze.db/resource-store) + :kv-store (ig/ref :blaze.db/index-kv-store) + :search-param-registry (ig/ref :blaze.db/search-param-registry) + :poll-timeout (time/millis 10)} + node-config) ::tx-log/local {:kv-store (ig/ref :blaze.db/transaction-kv-store) @@ -103,6 +105,10 @@ :blaze.db/search-param-registry {}}) +(def system + (create-system {})) + + (defmethod ig/init-key ::slow-resource-store [_ {:keys [resource-store]}] (reify rs/ResourceStore @@ -197,7 +203,7 @@ (with-system [{:blaze.db/keys [node]} system] @(d/transact node - ;; the create ops are purposely disordered in order to test the + ;; create ops are purposely disordered in order to test the ;; reference dependency ordering algorithm [[:create {:fhir/type :fhir/Observation :id "0" @@ -514,6 +520,23 @@ ::anom/category := ::anom/conflict ::anom/message := "Referential integrity violated. Resource `Observation/1` should be deleted but is referenced from `List/0`.")))) + (testing "not enforcing referential integrity" + (testing "creating an Observation were the subject doesn't exist" + (testing "create" + (with-system [{:blaze.db/keys [node]} (create-system {:enforce-referential-integrity false})] + @(d/transact + node + [[:create + {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}]]) + + (given @(d/pull node (d/resource-handle (d/db node) "Observation" "0")) + :fhir/type := :fhir/Observation + :id := "0" + [:subject :reference] := "Patient/0" + [:meta :versionId] := #fhir/id"1" + [meta :blaze.db/op] := :create))))) + (testing "creating 100 transactions in parallel" (with-system [{:blaze.db/keys [node]} slow-resource-store-system] (let [db-futures diff --git a/modules/db/test/blaze/db/node/transaction/spec.clj b/modules/db/test/blaze/db/node/transaction/spec.clj new file mode 100644 index 000000000..186834294 --- /dev/null +++ b/modules/db/test/blaze/db/node/transaction/spec.clj @@ -0,0 +1,11 @@ +(ns blaze.db.node.transaction.spec + (:require + [blaze.db.spec] + [blaze.db.tx-log.spec] + [blaze.fhir.hash.spec] + [blaze.fhir.spec.spec] + [clojure.spec.alpha :as s])) + + +(s/def :blaze.db.node.transaction/context + (s/keys :opt [:blaze.db/enforce-referential-integrity])) diff --git a/modules/db/test/blaze/db/node/transaction_spec.clj b/modules/db/test/blaze/db/node/transaction_spec.clj index 2de2bdeba..e6f05b528 100644 --- a/modules/db/test/blaze/db/node/transaction_spec.clj +++ b/modules/db/test/blaze/db/node/transaction_spec.clj @@ -2,12 +2,10 @@ (:require [blaze.anomaly-spec] [blaze.db.node.transaction :as tx] - [blaze.db.tx-log.spec] - [blaze.fhir.hash.spec] - [blaze.fhir.spec.spec] + [blaze.db.node.transaction.spec] [clojure.spec.alpha :as s])) (s/fdef tx/prepare-ops - :args (s/cat :tx-ops :blaze.db/tx-ops) + :args (s/cat :context :blaze.db.node.transaction/context :tx-ops :blaze.db/tx-ops) :ret (s/tuple :blaze.db/tx-cmds (s/map-of :blaze.resource/hash :blaze/resource))) diff --git a/modules/db/test/blaze/db/node/transaction_test.clj b/modules/db/test/blaze/db/node/transaction_test.clj index ecaabf6ef..9f390e017 100644 --- a/modules/db/test/blaze/db/node/transaction_test.clj +++ b/modules/db/test/blaze/db/node/transaction_test.clj @@ -23,10 +23,15 @@ (test/use-fixtures :each fixture) +(def context + {}) + + (deftest prepare-ops-test (testing "create" (testing "with references" (given (tx/prepare-ops + context [[:create {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference{:reference "Patient/0"}}]]) [0 0 :op] := "create" @@ -36,10 +41,18 @@ [0 0 :refs] := [["Patient" "0"]] [1 0 0] := #blaze/byte-string"7B3980C2BFCF43A8CDD61662E1AABDA9CA6431964820BC8D52958AEC9A270378" [1 0 1] := {:fhir/type :fhir/Observation :id "0" - :subject #fhir/Reference{:reference "Patient/0"}})) + :subject #fhir/Reference{:reference "Patient/0"}}) + + (testing "with disabled referential integrity check" + (given (tx/prepare-ops + {:blaze.db/enforce-referential-integrity false} + [[:create {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}]]) + [0 0 :refs] :? empty?))) (testing "conditional" (given (tx/prepare-ops + context [[:create {:fhir/type :fhir/Patient :id "id-220036"} [["identifier" "115508"]]]]) [0 0 :op] := "create" @@ -47,21 +60,41 @@ [0 0 :id] := "id-220036" [0 0 :if-none-exist] := [["identifier" "115508"]]))) - (testing "one put" - (given (tx/prepare-ops [[:put {:fhir/type :fhir/Patient :id "0"}]]) + (testing "put" + (given (tx/prepare-ops context [[:put {:fhir/type :fhir/Patient :id "0"}]]) [0 0 :op] := "put" [0 0 :type] := "Patient" [0 0 :id] := "0" [0 0 :hash] := #blaze/byte-string"C9ADE22457D5AD750735B6B166E3CE8D6878D09B64C2C2868DCB6DE4C9EFBD4F" [1 0 0] := #blaze/byte-string"C9ADE22457D5AD750735B6B166E3CE8D6878D09B64C2C2868DCB6DE4C9EFBD4F" - [1 0 1] := {:fhir/type :fhir/Patient :id "0"})) + [1 0 1] := {:fhir/type :fhir/Patient :id "0"}) + + (testing "with references" + (given (tx/prepare-ops + context + [[:put {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}]]) + [0 0 :op] := "put" + [0 0 :type] := "Observation" + [0 0 :id] := "0" + [0 0 :hash] := #blaze/byte-string"7B3980C2BFCF43A8CDD61662E1AABDA9CA6431964820BC8D52958AEC9A270378" + [0 0 :refs] := [["Patient" "0"]] + [1 0 0] := #blaze/byte-string"7B3980C2BFCF43A8CDD61662E1AABDA9CA6431964820BC8D52958AEC9A270378" + [1 0 1] := {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}) + + (testing "with disabled referential integrity check" + (given (tx/prepare-ops {:blaze.db/enforce-referential-integrity false} + [[:put {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}]]) + [0 0 :refs] :? empty?))) - (testing "one put with matches" - (given (tx/prepare-ops [[:put {:fhir/type :fhir/Patient :id "0"} 4]]) - [0 0 :if-match] := 4)) + (testing "with matches" + (given (tx/prepare-ops context [[:put {:fhir/type :fhir/Patient :id "0"} 4]]) + [0 0 :if-match] := 4))) - (testing "one delete" - (given (tx/prepare-ops [[:delete "Patient" "0"]]) + (testing "delete" + (given (tx/prepare-ops context [[:delete "Patient" "0"]]) [0 0 :op] := "delete" [0 0 :type] := "Patient" [0 0 :id] := "0" diff --git a/modules/db/test/blaze/db/node_test.clj b/modules/db/test/blaze/db/node_test.clj index e81212422..b5293d0ff 100644 --- a/modules/db/test/blaze/db/node_test.clj +++ b/modules/db/test/blaze/db/node_test.clj @@ -144,7 +144,21 @@ [:explain ::s/problems 4 :pred] := `(fn ~'[%] (contains? ~'% :resource-store)) [:explain ::s/problems 5 :pred] := `(fn ~'[%] (contains? ~'% :search-param-registry)) [:explain ::s/problems 6 :pred] := `(fn ~'[%] (satisfies? tx-log/TxLog ~'%)) - [:explain ::s/problems 6 :val] := ::invalid))) + [:explain ::s/problems 6 :val] := ::invalid)) + + (testing "invalid enforce-referential-integrity" + (given-thrown (ig/init {:blaze.db/node {:enforce-referential-integrity ::invalid}}) + :key := :blaze.db/node + :reason := ::ig/build-failed-spec + [:explain ::s/problems 0 :pred] := `(fn ~'[%] (contains? ~'% :tx-log)) + [:explain ::s/problems 1 :pred] := `(fn ~'[%] (contains? ~'% :resource-handle-cache)) + [:explain ::s/problems 2 :pred] := `(fn ~'[%] (contains? ~'% :tx-cache)) + [:explain ::s/problems 3 :pred] := `(fn ~'[%] (contains? ~'% :indexer-executor)) + [:explain ::s/problems 4 :pred] := `(fn ~'[%] (contains? ~'% :kv-store)) + [:explain ::s/problems 5 :pred] := `(fn ~'[%] (contains? ~'% :resource-store)) + [:explain ::s/problems 6 :pred] := `(fn ~'[%] (contains? ~'% :search-param-registry)) + [:explain ::s/problems 7 :pred] := `boolean? + [:explain ::s/problems 7 :val] := ::invalid))) (deftest duration-seconds-collector-init-test diff --git a/modules/fhir-structure/src/blaze/fhir/spec/spec.clj b/modules/fhir-structure/src/blaze/fhir/spec/spec.clj index 23276a9c8..f70236664 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/spec.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/spec.clj @@ -25,10 +25,14 @@ (s/and string? #(re-matches #"[A-Za-z0-9\-\.]{1,64}" %))) +(s/def :blaze.fhir/local-ref-tuple + (s/tuple :fhir.resource/type :blaze.resource/id)) + + (s/def :blaze.fhir/local-ref (s/and string? (s/conformer #(str/split % #"/" 2)) - (s/tuple :fhir.resource/type :blaze.resource/id))) + :blaze.fhir/local-ref-tuple)) (s/def :blaze/resource diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type.clj b/modules/fhir-structure/src/blaze/fhir/spec/type.clj index f7cb0f076..abc1db941 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type.clj @@ -55,7 +55,10 @@ (p/-hash-into x sink)) -(defn references [x] +(defn references + "Returns a collection of local references which are tuples of FHIR resource + type name and FHIR resource id." + [x] (p/-references x)) diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type_spec.clj b/modules/fhir-structure/src/blaze/fhir/spec/type_spec.clj index 978266468..5d8ab69e2 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type_spec.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type_spec.clj @@ -19,7 +19,7 @@ (s/fdef type/references :args (s/cat :x any?) - :ret (s/coll-of :blaze.db/local-ref)) + :ret (s/coll-of :blaze.fhir/local-ref-tuple)) (s/fdef type/->Date diff --git a/modules/interaction/.clj-kondo/config.edn b/modules/interaction/.clj-kondo/config.edn index 21883cafd..bef83071e 100644 --- a/modules/interaction/.clj-kondo/config.edn +++ b/modules/interaction/.clj-kondo/config.edn @@ -24,7 +24,8 @@ blaze.interaction.transaction-test/with-handler clojure.core/fn blaze.interaction.transaction-test/with-handler-data clojure.core/fn blaze.interaction.update-test/with-handler clojure.core/fn - blaze.interaction.update-test/with-handler-data clojure.core/fn} + blaze.interaction.update-test/with-handler-data clojure.core/fn + blaze.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces diff --git a/modules/interaction/test/blaze/interaction/create_test.clj b/modules/interaction/test/blaze/interaction/create_test.clj index 23e00def5..4ae5eefee 100644 --- a/modules/interaction/test/blaze/interaction/create_test.clj +++ b/modules/interaction/test/blaze/interaction/create_test.clj @@ -6,14 +6,15 @@ https://www.hl7.org/fhir/http.html#ops" (:require [blaze.anomaly-spec] - [blaze.db.api-stub :refer [mem-node-system with-system-data]] + [blaze.db.api-stub + :refer [create-mem-node-system with-system-data]] [blaze.executors :as ex] [blaze.fhir.response.create-spec] [blaze.fhir.spec.type] [blaze.interaction.create] [blaze.interaction.util-spec] [blaze.middleware.fhir.error :refer [wrap-error]] - [blaze.test-util :refer [given-thrown]] + [blaze.test-util :refer [given-thrown with-system]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -43,7 +44,8 @@ (def router (reitit/router - [["/Patient" {:name :Patient/type}]] + [["/Patient" {:name :Patient/type}] + ["/Observation" {:name :Observation/type}]] {:syntax :bracket})) @@ -74,8 +76,8 @@ [:explain ::s/problems 3 :val] := ::invalid))) -(def system - (assoc mem-node-system +(defn create-system [node-config] + (assoc (create-mem-node-system node-config) :blaze.interaction/create {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor) @@ -85,6 +87,10 @@ :blaze.test/fixed-rng-fn {})) +(def system + (create-system {})) + + (defn wrap-defaults [handler] (fn [request] (handler @@ -104,59 +110,63 @@ (reitit/map->Match {:data {:fhir.resource/type "Patient"}})) +(def observation-match + (reitit/map->Match {:data {:fhir.resource/type "Observation"}})) + + (deftest handler-test - (testing "Returns Error on missing body" - (with-handler [handler] - [] - (let [{:keys [status body]} - @(handler - {::reitit/match patient-match})] + (testing "errors on" + (testing "missing body" + (with-handler [handler] + [] + (let [{:keys [status body]} + @(handler + {::reitit/match patient-match})] - (is (= 400 status)) + (is (= 400 status)) - (given body - :fhir/type := :fhir/OperationOutcome - [:issue 0 :severity] := #fhir/code"error" - [:issue 0 :code] := #fhir/code"invalid" - [:issue 0 :diagnostics] := "Missing HTTP body.")))) + (given body + :fhir/type := :fhir/OperationOutcome + [:issue 0 :severity] := #fhir/code"error" + [:issue 0 :code] := #fhir/code"invalid" + [:issue 0 :diagnostics] := "Missing HTTP body.")))) - (testing "Returns Error on type mismatch" - (with-handler [handler] - [] - (let [{:keys [status body]} - @(handler - {::reitit/match patient-match - :body {:fhir/type :fhir/Observation}})] + (testing "type mismatch" + (with-handler [handler] + [] + (let [{:keys [status body]} + @(handler + {::reitit/match patient-match + :body {:fhir/type :fhir/Observation}})] - (is (= 400 status)) + (is (= 400 status)) - (given body - :fhir/type := :fhir/OperationOutcome - [:issue 0 :severity] := #fhir/code"error" - [:issue 0 :code] := #fhir/code"invariant" - [:issue 0 :details :coding 0 :system] := #fhir/uri"http://terminology.hl7.org/CodeSystem/operation-outcome" - [:issue 0 :details :coding 0 :code] := #fhir/code"MSG_RESOURCE_TYPE_MISMATCH" - [:issue 0 :diagnostics] := "Resource type `Observation` doesn't match the endpoint type `Patient`.")))) - - (testing "Returns Error violated referential integrity" - (with-handler [handler] - [] - (let [{:keys [status body]} - @(handler - {::reitit/match {:data {:fhir.resource/type "Observation"}} - :body {:fhir/type :fhir/Observation :id "0" - :subject #fhir/Reference{:reference "Patient/0"}}})] + (given body + :fhir/type := :fhir/OperationOutcome + [:issue 0 :severity] := #fhir/code"error" + [:issue 0 :code] := #fhir/code"invariant" + [:issue 0 :details :coding 0 :system] := #fhir/uri"http://terminology.hl7.org/CodeSystem/operation-outcome" + [:issue 0 :details :coding 0 :code] := #fhir/code"MSG_RESOURCE_TYPE_MISMATCH" + [:issue 0 :diagnostics] := "Resource type `Observation` doesn't match the endpoint type `Patient`.")))) + + (testing "violated referential integrity" + (with-handler [handler] + [] + (let [{:keys [status body]} + @(handler + {::reitit/match observation-match + :body {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}})] - (is (= 409 status)) + (is (= 409 status)) - (given body - :fhir/type := :fhir/OperationOutcome - [:issue 0 :severity] := #fhir/code"error" - [:issue 0 :code] := #fhir/code"conflict" - [:issue 0 :diagnostics] := - "Referential integrity violated. Resource `Patient/0` doesn't exist.")))) + (given body + :fhir/type := :fhir/OperationOutcome + [:issue 0 :severity] := #fhir/code"error" + [:issue 0 :code] := #fhir/code"conflict" + [:issue 0 :diagnostics] := "Referential integrity violated. Resource `Patient/0` doesn't exist."))))) - (testing "On newly created resource" + (testing "on newly created resource" (testing "with no Prefer header" (with-handler [handler] [] @@ -328,4 +338,32 @@ :fhir/type := :fhir/OperationOutcome [:issue 0 :severity] := #fhir/code"error" [:issue 0 :code] := #fhir/code"conflict" - [:issue 0 :diagnostics] := "Conditional create of a Patient with query `birthdate=2020` failed because at least the two matches `Patient/0/_history/1` and `Patient/1/_history/1` were found."))))))) + [:issue 0 :diagnostics] := "Conditional create of a Patient with query `birthdate=2020` failed because at least the two matches `Patient/0/_history/1` and `Patient/1/_history/1` were found.")))))) + + (testing "with disabled referential integrity check" + (with-system [{handler :blaze.interaction/create} (create-system {:enforce-referential-integrity false})] + (let [{:keys [status headers body]} + @((-> handler wrap-defaults wrap-error) + {::reitit/match observation-match + :body {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}})] + + (is (= 201 status)) + + (testing "Location header" + (is (= (str base-url "/Observation/AAAAAAAAAAAAAAAA/_history/1") + (get headers "Location")))) + + (testing "Transaction time in Last-Modified header" + (is (= "Thu, 1 Jan 1970 00:00:00 GMT" (get headers "Last-Modified")))) + + (testing "Version in ETag header" + ;; 1 is the T of the transaction of the resource creation + (is (= "W/\"1\"" (get headers "ETag")))) + + (given body + :fhir/type := :fhir/Observation + :id := "AAAAAAAAAAAAAAAA" + [:meta :versionId] := #fhir/id"1" + [:meta :lastUpdated] := Instant/EPOCH + [:subject :reference] := "Patient/0"))))) diff --git a/modules/interaction/test/blaze/interaction/update_test.clj b/modules/interaction/test/blaze/interaction/update_test.clj index 09a1018f6..25f211408 100644 --- a/modules/interaction/test/blaze/interaction/update_test.clj +++ b/modules/interaction/test/blaze/interaction/update_test.clj @@ -6,13 +6,14 @@ https://www.hl7.org/fhir/http.html#ops" (:require [blaze.anomaly-spec] - [blaze.db.api-stub :refer [mem-node-system with-system-data]] + [blaze.db.api-stub + :refer [create-mem-node-system with-system-data]] [blaze.executors :as ex] [blaze.fhir.response.create-spec] [blaze.fhir.spec.type] [blaze.interaction.update] [blaze.middleware.fhir.error :refer [wrap-error]] - [blaze.test-util :refer [given-thrown]] + [blaze.test-util :refer [given-thrown with-system]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -42,7 +43,8 @@ (def router (reitit/router - [["/Patient" {:name :Patient/type}]] + [["/Patient" {:name :Patient/type}] + ["/Observation" {:name :Observation/type}]] {:syntax :bracket})) @@ -54,6 +56,10 @@ (reitit/map->Match {:data {:fhir.resource/type "Patient"}})) +(def observation-match + (reitit/map->Match {:data {:fhir.resource/type "Observation"}})) + + (deftest init-test (testing "nil config" (given-thrown (ig/init {:blaze.interaction/update nil}) @@ -77,14 +83,18 @@ [:explain ::s/problems 1 :val] := ::invalid))) -(def system - (assoc mem-node-system +(defn create-system [node-config] + (assoc (create-mem-node-system node-config) :blaze.interaction/update {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor)} :blaze.test/executor {})) +(def system + (create-system {})) + + (defn wrap-defaults [handler] (fn [request] (handler @@ -101,123 +111,123 @@ (deftest handler-test - (testing "on missing body" - (with-handler [handler] - [] - (let [{:keys [status body]} - @(handler - {:path-params {:id "0"} - ::reitit/match patient-match})] + (testing "erros on" + (testing "missing body" + (with-handler [handler] + [] + (let [{:keys [status body]} + @(handler + {:path-params {:id "0"} + ::reitit/match patient-match})] - (testing "returns error" - (is (= 400 status)) + (testing "returns error" + (is (= 400 status)) - (given body - :fhir/type := :fhir/OperationOutcome - [:issue 0 :severity] := #fhir/code"error" - [:issue 0 :code] := #fhir/code"invalid" - [:issue 0 :diagnostics] := "Missing HTTP body."))))) - - (testing "on type mismatch" - (with-handler [handler] - [] - (let [{:keys [status body]} - @(handler - {:path-params {:id "0"} - ::reitit/match patient-match - :body {:fhir/type :fhir/Observation}})] + (given body + :fhir/type := :fhir/OperationOutcome + [:issue 0 :severity] := #fhir/code"error" + [:issue 0 :code] := #fhir/code"invalid" + [:issue 0 :diagnostics] := "Missing HTTP body."))))) - (testing "returns error" - (is (= 400 status)) + (testing "type mismatch" + (with-handler [handler] + [] + (let [{:keys [status body]} + @(handler + {:path-params {:id "0"} + ::reitit/match patient-match + :body {:fhir/type :fhir/Observation}})] - (given body - :fhir/type := :fhir/OperationOutcome - [:issue 0 :severity] := #fhir/code"error" - [:issue 0 :code] := #fhir/code"invariant" - [:issue 0 :details :coding 0 :system] := operation-outcome - [:issue 0 :details :coding 0 :code] := #fhir/code"MSG_RESOURCE_TYPE_MISMATCH" - [:issue 0 :diagnostics] := "Invalid update interaction of a Observation at a Patient endpoint."))))) - - (testing "on missing id" - (with-handler [handler] - [] - (let [{:keys [status body]} - @(handler - {:path-params {:id "0"} - ::reitit/match patient-match - :body {:fhir/type :fhir/Patient}})] + (testing "returns error" + (is (= 400 status)) - (testing "returns error" - (is (= 400 status)) + (given body + :fhir/type := :fhir/OperationOutcome + [:issue 0 :severity] := #fhir/code"error" + [:issue 0 :code] := #fhir/code"invariant" + [:issue 0 :details :coding 0 :system] := operation-outcome + [:issue 0 :details :coding 0 :code] := #fhir/code"MSG_RESOURCE_TYPE_MISMATCH" + [:issue 0 :diagnostics] := "Invalid update interaction of a Observation at a Patient endpoint."))))) + + (testing "missing id" + (with-handler [handler] + [] + (let [{:keys [status body]} + @(handler + {:path-params {:id "0"} + ::reitit/match patient-match + :body {:fhir/type :fhir/Patient}})] - (given body - :fhir/type := :fhir/OperationOutcome - [:issue 0 :severity] := #fhir/code"error" - [:issue 0 :code] := #fhir/code"required" - [:issue 0 :details :coding 0 :system] := operation-outcome - [:issue 0 :details :coding 0 :code] := #fhir/code"MSG_RESOURCE_ID_MISSING" - [:issue 0 :diagnostics] := "Missing resource id."))))) - - - (testing "on ID mismatch" - (with-handler [handler] - [] - (let [{:keys [status body]} - @(handler - {:path-params {:id "0"} - ::reitit/match patient-match - :body {:fhir/type :fhir/Patient :id "1"}})] + (testing "returns error" + (is (= 400 status)) + + (given body + :fhir/type := :fhir/OperationOutcome + [:issue 0 :severity] := #fhir/code"error" + [:issue 0 :code] := #fhir/code"required" + [:issue 0 :details :coding 0 :system] := operation-outcome + [:issue 0 :details :coding 0 :code] := #fhir/code"MSG_RESOURCE_ID_MISSING" + [:issue 0 :diagnostics] := "Missing resource id."))))) + + (testing "ID mismatch" + (with-handler [handler] + [] + (let [{:keys [status body]} + @(handler + {:path-params {:id "0"} + ::reitit/match patient-match + :body {:fhir/type :fhir/Patient :id "1"}})] - (testing "returns error" - (is (= 400 status)) + (testing "returns error" + (is (= 400 status)) - (given body - :fhir/type := :fhir/OperationOutcome - [:issue 0 :severity] := #fhir/code"error" - [:issue 0 :code] := #fhir/code"invariant" - [:issue 0 :details :coding 0 :system] := operation-outcome - [:issue 0 :details :coding 0 :code] := #fhir/code"MSG_RESOURCE_ID_MISMATCH" - [:issue 0 :diagnostics] := "The resource id `1` doesn't match the endpoints id `0`."))))) - - (testing "on optimistic locking failure" - (with-handler [handler] - [[[:create {:fhir/type :fhir/Patient :id "0"}]] - [[:put {:fhir/type :fhir/Patient :id "0"}]]] - - (let [{:keys [status body]} - @(handler - {:path-params {:id "0"} - ::reitit/match patient-match - :headers {"if-match" "W/\"1\""} - :body {:fhir/type :fhir/Patient :id "0"}})] + (given body + :fhir/type := :fhir/OperationOutcome + [:issue 0 :severity] := #fhir/code"error" + [:issue 0 :code] := #fhir/code"invariant" + [:issue 0 :details :coding 0 :system] := operation-outcome + [:issue 0 :details :coding 0 :code] := #fhir/code"MSG_RESOURCE_ID_MISMATCH" + [:issue 0 :diagnostics] := "The resource id `1` doesn't match the endpoints id `0`."))))) + + (testing "optimistic locking failure" + (with-handler [handler] + [[[:create {:fhir/type :fhir/Patient :id "0"}]] + [[:put {:fhir/type :fhir/Patient :id "0"}]]] - (testing "returns error" - (is (= 412 status)) + (let [{:keys [status body]} + @(handler + {:path-params {:id "0"} + ::reitit/match patient-match + :headers {"if-match" "W/\"1\""} + :body {:fhir/type :fhir/Patient :id "0"}})] - (given body - :fhir/type := :fhir/OperationOutcome - [:issue 0 :severity] := #fhir/code"error" - [:issue 0 :code] := #fhir/code"conflict" - [:issue 0 :diagnostics] := "Precondition `W/\"1\"` failed on `Patient/0`."))))) - - (testing "on violated referential integrity" - (with-handler [handler] - [] - (let [{:keys [status body]} - @(handler - {:path-params {:id "0"} - ::reitit/match {:data {:fhir.resource/type "Observation"}} - :body {:fhir/type :fhir/Observation :id "0" - :subject #fhir/Reference{:reference "Patient/0"}}})] + (testing "returns error" + (is (= 412 status)) - (testing "returns error" - (is (= 409 status)) + (given body + :fhir/type := :fhir/OperationOutcome + [:issue 0 :severity] := #fhir/code"error" + [:issue 0 :code] := #fhir/code"conflict" + [:issue 0 :diagnostics] := "Precondition `W/\"1\"` failed on `Patient/0`."))))) - (given body - :fhir/type := :fhir/OperationOutcome - [:issue 0 :severity] := #fhir/code"error" - [:issue 0 :code] := #fhir/code"conflict" - [:issue 0 :diagnostics] := "Referential integrity violated. Resource `Patient/0` doesn't exist."))))) + (testing "violated referential integrity" + (with-handler [handler] + [] + (let [{:keys [status body]} + @(handler + {:path-params {:id "0"} + ::reitit/match observation-match + :body {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}})] + + (testing "returns error" + (is (= 409 status)) + + (given body + :fhir/type := :fhir/OperationOutcome + [:issue 0 :severity] := #fhir/code"error" + [:issue 0 :code] := #fhir/code"conflict" + [:issue 0 :diagnostics] := "Referential integrity violated. Resource `Patient/0` doesn't exist.")))))) (testing "on newly created resource" (testing "with no Prefer header" @@ -371,4 +381,35 @@ :id := "0" :birthDate := #fhir/date"2020" [:meta :versionId] := #fhir/id"2" - [:meta :lastUpdated] := Instant/EPOCH))))))) + [:meta :lastUpdated] := Instant/EPOCH)))))) + + (testing "with disabled referential integrity check" + (with-system [{handler :blaze.interaction/update} (create-system {:enforce-referential-integrity false})] + (let [{:keys [status headers body]} + @((-> handler wrap-defaults wrap-error) + {:path-params {:id "0"} + ::reitit/match observation-match + :body {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}})] + + (testing "Returns 201" + (is (= 201 status))) + + (testing "Location header" + (is (= "base-url-134013/Observation/0/_history/1" (get headers "Location")))) + + (testing "Transaction time in Last-Modified header" + (is (= "Thu, 1 Jan 1970 00:00:00 GMT" (get headers "Last-Modified")))) + + (testing "VersionId in ETag header" + (is (= "W/\"1\"" (get headers "ETag")))) + + (testing "Location header" + (is (= "base-url-134013/Observation/0/_history/1" (get headers "Location")))) + + (testing "Contains the resource as body" + (given body + :fhir/type := :fhir/Observation + :id := "0" + [:meta :versionId] := #fhir/id"1" + [:meta :lastUpdated] := Instant/EPOCH)))))) diff --git a/modules/page-store-cassandra/src/blaze/page_store/cassandra.clj b/modules/page-store-cassandra/src/blaze/page_store/cassandra.clj index 5d96c54e0..de083315c 100644 --- a/modules/page-store-cassandra/src/blaze/page_store/cassandra.clj +++ b/modules/page-store-cassandra/src/blaze/page_store/cassandra.clj @@ -116,7 +116,7 @@ ::cass/request-timeout])) -(defn init-msg [config] +(defn- init-msg [config] (str "Open Cassandra page store with the following settings: " (cass/format-config config))) diff --git a/modules/rest-api/src/blaze/rest_api.clj b/modules/rest-api/src/blaze/rest_api.clj index 79a7acc89..255bb6dee 100644 --- a/modules/rest-api/src/blaze/rest_api.clj +++ b/modules/rest-api/src/blaze/rest_api.clj @@ -2,6 +2,7 @@ (:require [blaze.async.comp :as ac] [blaze.db.search-param-registry.spec] + [blaze.db.spec] [blaze.executors :as ex] [blaze.handler.util :as handler-util] [blaze.middleware.fhir.error :refer [wrap-error]] @@ -111,18 +112,19 @@ [:blaze.rest-api.json-parse/executor] :req-un [:blaze/base-url - ::version + :blaze/version :blaze.rest-api/structure-definitions :blaze.db/node :blaze.db/search-param-registry] :opt-un - [::context-path + [:blaze/context-path ::auth-backends ::search-system-handler ::transaction-handler ::history-system-handler ::resource-patterns - ::operations])) + ::operations + :blaze.db/enforce-referential-integrity])) (defmethod ig/init-key :blaze/rest-api diff --git a/modules/rest-api/src/blaze/rest_api/capabilities.clj b/modules/rest-api/src/blaze/rest_api/capabilities.clj index faa104d23..55cbab276 100644 --- a/modules/rest-api/src/blaze/rest_api/capabilities.clj +++ b/modules/rest-api/src/blaze/rest_api/capabilities.clj @@ -17,8 +17,10 @@ (defn- capability-resource - {:arglists '([resource-patterns operations search-param-registry structure-definition])} - [resource-patterns operations search-param-registry + {:arglists '([context structure-definition])} + [{:keys [resource-patterns operations search-param-registry + enforce-referential-integrity] + :or {enforce-referential-integrity true}} {:keys [name] :as structure-definition}] (when-let [{:blaze.rest-api.resource-pattern/keys [interactions]} @@ -58,9 +60,11 @@ :conditionalUpdate false :conditionalDelete #fhir/code"not-supported" :referencePolicy - [#fhir/code"literal" - #fhir/code"enforced" + (cond-> + [#fhir/code"literal" #fhir/code"local"] + enforce-referential-integrity + (conj #fhir/code"enforced")) :searchParam (transduce (map @@ -89,17 +93,16 @@ (defn capabilities-handler + {:arglists '([context])} [{:keys [version context-path structure-definitions - search-param-registry search-system-handler transaction-handler - history-system-handler - resource-patterns - operations] - :or {context-path ""}}] + history-system-handler] + :or {context-path ""} + :as context}] (let [capability-statement {:fhir/type :fhir/CapabilityStatement :status #fhir/code"active" @@ -108,7 +111,7 @@ :copyright #fhir/markdown"Copyright 2019 - 2021 The Samply Community\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License." :kind #fhir/code"instance" - :date #fhir/dateTime"2021-12-02" + :date #fhir/dateTime"2021-12-03" :software {:name "Blaze" :version version} @@ -125,7 +128,7 @@ [] (comp u/structure-definition-filter - (keep #(capability-resource resource-patterns operations search-param-registry %))) + (keep (partial capability-resource context))) structure-definitions) :interaction (cond-> [] diff --git a/modules/rest-api/src/blaze/rest_api/spec.clj b/modules/rest-api/src/blaze/rest_api/spec.clj index b0094f53d..68cc7270c 100644 --- a/modules/rest-api/src/blaze/rest_api/spec.clj +++ b/modules/rest-api/src/blaze/rest_api/spec.clj @@ -94,14 +94,6 @@ (s/coll-of :blaze.rest-api/compartment)) -(s/def :blaze.rest-api/version - string?) - - -(s/def :blaze.rest-api/context-path - string?) - - (s/def :blaze.rest-api.operation/code string?) diff --git a/modules/rest-api/test/blaze/rest_api/capabilities/spec.clj b/modules/rest-api/test/blaze/rest_api/capabilities/spec.clj new file mode 100644 index 000000000..ed96c0e53 --- /dev/null +++ b/modules/rest-api/test/blaze/rest_api/capabilities/spec.clj @@ -0,0 +1,17 @@ +(ns blaze.rest-api.capabilities.spec + (:require + [blaze.db.search-param-registry.spec] + [blaze.rest-api.spec] + [blaze.spec] + [clojure.spec.alpha :as s])) + + +(s/def :blaze.rest-api.capabilities/context + (s/keys + :req-un + [:blaze/version + :blaze.rest-api/structure-definitions + :blaze.db/search-param-registry] + :opt-un + [:blaze/context-path + :blaze.db/enforce-referential-integrity])) diff --git a/modules/rest-api/test/blaze/rest_api/capabilities_spec.clj b/modules/rest-api/test/blaze/rest_api/capabilities_spec.clj new file mode 100644 index 000000000..831b56fe1 --- /dev/null +++ b/modules/rest-api/test/blaze/rest_api/capabilities_spec.clj @@ -0,0 +1,9 @@ +(ns blaze.rest-api.capabilities-spec + (:require + [blaze.rest-api.capabilities :as capabilities] + [blaze.rest-api.capabilities.spec] + [clojure.spec.alpha :as s])) + + +(s/fdef capabilities/capabilities-handler + :args (s/cat :context ::capabilities/context)) diff --git a/modules/rest-api/test/blaze/rest_api/capabilities_test.clj b/modules/rest-api/test/blaze/rest_api/capabilities_test.clj index 0e860c06f..71ef5a5a8 100644 --- a/modules/rest-api/test/blaze/rest_api/capabilities_test.clj +++ b/modules/rest-api/test/blaze/rest_api/capabilities_test.clj @@ -3,6 +3,7 @@ [blaze.db.impl.search-param] [blaze.db.search-param-registry :as sr] [blaze.rest-api.capabilities :as capabilities] + [blaze.rest-api.capabilities-spec] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] [juxt.iota :refer [given]] @@ -99,7 +100,30 @@ :body) :fhir/type := :fhir/CapabilityStatement [:rest 0 :resource 0 :type] := #fhir/code"Patient" - [:rest 0 :resource 0 :interaction 0 :code] := #fhir/code"read")) + [:rest 0 :resource 0 :interaction 0 :code] := #fhir/code"read" + [:rest 0 :resource 0 :referencePolicy] :? (partial some #{#fhir/code"enforced"})) + + (testing "with disabled referential integrity check" + (given + (-> @((capabilities/capabilities-handler + {:version "version-131640" + :structure-definitions + [{:kind "resource" :name "Patient"}] + :search-param-registry search-param-registry + :resource-patterns + [#:blaze.rest-api.resource-pattern + {:type "Patient" + :interactions + {:read + #:blaze.rest-api.interaction + {:handler (fn [_])}}}] + :enforce-referential-integrity false}) + {}) + :body) + :fhir/type := :fhir/CapabilityStatement + [:rest 0 :resource 0 :type] := #fhir/code"Patient" + [:rest 0 :resource 0 :interaction 0 :code] := #fhir/code"read" + [:rest 0 :resource 0 :referencePolicy] :? (comp not (partial some #{#fhir/code"enforced"}))))) (testing "Observation interaction" (given diff --git a/modules/rest-api/test/blaze/rest_api_test.clj b/modules/rest-api/test/blaze/rest_api_test.clj index 810e72353..8fc7c066f 100644 --- a/modules/rest-api/test/blaze/rest_api_test.clj +++ b/modules/rest-api/test/blaze/rest_api_test.clj @@ -267,7 +267,20 @@ [:explain ::s/problems 2 :pred] := `(fn ~'[%] (contains? ~'% :version)) [:explain ::s/problems 3 :pred] := `(fn ~'[%] (contains? ~'% :structure-definitions)) [:explain ::s/problems 4 :pred] := `(fn ~'[%] (contains? ~'% :node)) - [:explain ::s/problems 5 :pred] := `(fn ~'[%] (contains? ~'% :search-param-registry))))) + [:explain ::s/problems 5 :pred] := `(fn ~'[%] (contains? ~'% :search-param-registry)))) + + (testing "invalid enforce-referential-integrity" + (given-thrown (ig/init {:blaze/rest-api {:enforce-referential-integrity ::invalid}}) + :key := :blaze/rest-api + :reason := ::ig/build-failed-spec + [:explain ::s/problems 0 :pred] := `(fn ~'[%] (contains? ~'% :blaze.rest-api.json-parse/executor)) + [:explain ::s/problems 1 :pred] := `(fn ~'[%] (contains? ~'% :base-url)) + [:explain ::s/problems 2 :pred] := `(fn ~'[%] (contains? ~'% :version)) + [:explain ::s/problems 3 :pred] := `(fn ~'[%] (contains? ~'% :structure-definitions)) + [:explain ::s/problems 4 :pred] := `(fn ~'[%] (contains? ~'% :node)) + [:explain ::s/problems 5 :pred] := `(fn ~'[%] (contains? ~'% :search-param-registry)) + [:explain ::s/problems 6 :pred] := `boolean? + [:explain ::s/problems 6 :val] := ::invalid))) (def system diff --git a/modules/spec/src/blaze/spec.clj b/modules/spec/src/blaze/spec.clj index dfc0d9abd..7bb193ae4 100644 --- a/modules/spec/src/blaze/spec.clj +++ b/modules/spec/src/blaze/spec.clj @@ -11,6 +11,10 @@ (s/and string? (complement #(str/ends-with? % "/")))) +(s/def :blaze/version + string?) + + (s/def :blaze/context-path (s/and string? diff --git a/perf-test/gatling/pom.xml b/perf-test/gatling/pom.xml index 05eab9395..636c77bda 100644 --- a/perf-test/gatling/pom.xml +++ b/perf-test/gatling/pom.xml @@ -5,7 +5,7 @@ samply.blaze gatling - 0.13.5 + 0.14.0 1.8 diff --git a/pom.xml b/pom.xml index 8d38b736f..f83ee2929 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 samply blaze - 0.13.5 + 0.14.0 blaze A FHIR Store with internal, fast CQL Evaluation Engine diff --git a/resources/blaze.edn b/resources/blaze.edn index fea7e2a7b..848ef7439 100644 --- a/resources/blaze.edn +++ b/resources/blaze.edn @@ -69,7 +69,8 @@ :def-uri "http://hl7.org/fhir/OperationDefinition/Measure-evaluate-measure" :resource-types ["Measure"] :type-handler #blaze/ref :blaze.fhir.operation.evaluate-measure/handler - :instance-handler #blaze/ref :blaze.fhir.operation.evaluate-measure/handler}]} + :instance-handler #blaze/ref :blaze.fhir.operation.evaluate-measure/handler}] + :enforce-referential-integrity #blaze/cfg ["ENFORCE_REFERENTIAL_INTEGRITY" boolean? true]} ;; ;; FHIR Interactions @@ -178,7 +179,8 @@ :indexer-executor #blaze/ref :blaze.db.node/indexer-executor :resource-store #blaze/ref :blaze.db/resource-cache :kv-store #blaze/ref :blaze.db/index-kv-store - :search-param-registry #blaze/ref :blaze.db/search-param-registry} + :search-param-registry #blaze/ref :blaze.db/search-param-registry + :enforce-referential-integrity #blaze/cfg ["ENFORCE_REFERENTIAL_INTEGRITY" boolean? true]} :blaze.db.node/indexer-executor {} diff --git a/src/blaze/system.clj b/src/blaze/system.clj index 97120c2d6..67c9b6ffd 100644 --- a/src/blaze/system.clj +++ b/src/blaze/system.clj @@ -87,7 +87,7 @@ (def ^:private root-config - {:blaze/version "0.13.5" + {:blaze/version "0.14.0" :blaze/clock {}