diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/5242-mdm-clear-should-expunge-redirected-golden-resources.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/5242-mdm-clear-should-expunge-redirected-golden-resources.yaml new file mode 100644 index 00000000000..4b7972fd8b2 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/5242-mdm-clear-should-expunge-redirected-golden-resources.yaml @@ -0,0 +1,5 @@ +--- +type: fix +issue: 5242 +title: "Previously, `$mdm-clear` failed to expunge `REDIRECTED` golden resources which left them as orphans. This is now fixed." + diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceSearchSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceSearchSvcImpl.java index 794e1994637..c7e967075d6 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceSearchSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceSearchSvcImpl.java @@ -36,7 +36,7 @@ import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.server.SystemRequestDetails; import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; import ca.uhn.fhir.rest.param.DateRangeParam; -import ca.uhn.fhir.rest.param.TokenParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import ca.uhn.fhir.util.DateRangeUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; @@ -82,8 +82,11 @@ public class GoldenResourceSearchSvcImpl implements IGoldenResourceSearchSvc { DateRangeParam chunkDateRange = DateRangeUtil.narrowDateRange(searchParamMap.getLastUpdated(), theStart, theEnd); searchParamMap.setLastUpdated(chunkDateRange); - searchParamMap.add( - "_tag", new TokenParam(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_GOLDEN_RECORD)); + + TokenOrListParam goldenRecordStatusToken = new TokenOrListParam() + .add(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_GOLDEN_RECORD_REDIRECTED) + .add(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_GOLDEN_RECORD); + searchParamMap.add(Constants.PARAM_TAG, goldenRecordStatusToken); IFhirResourceDao dao = myDaoRegistry.getResourceDao(theResourceType); SystemRequestDetails request = new SystemRequestDetails(); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderClearLinkR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderClearLinkR4Test.java index 30751141e00..11384438ca4 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderClearLinkR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderClearLinkR4Test.java @@ -8,6 +8,7 @@ import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum; import ca.uhn.fhir.mdm.batch2.clear.MdmClearStep; import ca.uhn.fhir.mdm.model.MdmTransactionContext; import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; @@ -17,7 +18,10 @@ import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.read.ListAppender; import org.hl7.fhir.instance.model.api.IAnyResource; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.hapi.rest.server.helper.BatchHelperR4; +import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.DecimalType; import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Patient; @@ -175,11 +179,49 @@ public class MdmProviderClearLinkR4Test extends BaseLinkR4Test { assertNoHistoricalLinksExist(List.of(myPractitionerGoldenResourceId.getValueAsString(), mySourcePatientId.getValueAsString()), new ArrayList<>()); } + @Test + public void testClearAllLinks_deletesRedirectedGoldenResources() { + createPatientAndUpdateLinks(buildJanePatient()); + assertLinkCount(3); + + List allGoldenPatients = getAllGoldenPatients(); + assertThat(allGoldenPatients, hasSize(2)); + + IIdType redirectedGoldenPatientId = allGoldenPatients.get(0).getIdElement().toVersionless(); + IIdType goldenPatientId = allGoldenPatients.get(1).getIdElement().toVersionless(); + + myMdmProvider.mergeGoldenResources(new StringType(redirectedGoldenPatientId.getValueAsString()), + new StringType(goldenPatientId.getValueAsString()), + null, + myRequestDetails); + + Patient redirectedGoldenPatient = myPatientDao.read(redirectedGoldenPatientId, myRequestDetails); + List patientTags = redirectedGoldenPatient.getMeta().getTag(); + assertTrue(patientTags.stream() + .anyMatch(tag -> tag.getCode().equals(MdmConstants.CODE_GOLDEN_RECORD_REDIRECTED))); + + assertLinkCount(4); + clearMdmLinks(); + assertNoLinksExist(); + + try { + myPatientDao.read(redirectedGoldenPatientId, myRequestDetails); + fail(); + } catch (ResourceNotFoundException e) { + assertEquals(Constants.STATUS_HTTP_404_NOT_FOUND, e.getStatusCode()); + assertNoGoldenPatientsExist(); + } + } + private void assertNoLinksExist() { assertNoPatientLinksExist(); assertNoPractitionerLinksExist(); } + private void assertNoGoldenPatientsExist() { + assertThat(getAllGoldenPatients(), hasSize(0)); + } + private void assertNoPatientLinksExist() { assertThat(getPatientLinks(), hasSize(0)); }