From 16194a63079c001473e4d2bd435750ff3c059607 Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Tue, 5 Aug 2025 11:26:32 -0400 Subject: [PATCH 1/2] Try to reproduce weird bug we saw in Mass-Ingestion. --- .../fhir/jpa/dao/r4/MassIngestionR4Test.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/MassIngestionR4Test.java diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/MassIngestionR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/MassIngestionR4Test.java new file mode 100644 index 000000000000..7d76e462f9a3 --- /dev/null +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/MassIngestionR4Test.java @@ -0,0 +1,67 @@ +package ca.uhn.fhir.jpa.dao.r4; + +import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; +import ca.uhn.fhir.jpa.model.dao.JpaPid; +import ca.uhn.fhir.jpa.test.BaseJpaR4Test; +import ca.uhn.fhir.rest.api.server.SystemRequestDetails; +import ca.uhn.fhir.util.BundleBuilder; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Patient; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.transaction.support.TransactionTemplate; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class MassIngestionR4Test extends BaseJpaR4Test { + private static final Logger ourLog = LoggerFactory.getLogger(MassIngestionR4Test.class); + @BeforeEach + void beforeEach() { + myStorageSettings.setMassIngestionMode(true); + } + + @AfterEach + public void afterEach() { + myStorageSettings.setMassIngestionMode(new JpaStorageSettings().isMassIngestionMode()); + } + + @Test + void testUpdateWithClientAssignedId_canFindBySearch() { + // given + Patient p = new Patient(); + p.setId("client-id"); + // first update is create. V1 + myPatientDao.update(p, mySrd); + assertEquals("1", p.getMeta().getVersionId()); + + // Second update should update. Create V2 + Patient pUpdated = new Patient(); + pUpdated.setId("client-id"); + pUpdated.setActive(true); + Bundle b = new BundleBuilder(myFhirContext).addTransactionUpdateEntry(pUpdated).andThen().getBundleTyped(); + var txResult = mySystemDao.transaction(new SystemRequestDetails(), b); + //myPatientDao.update(pUpdated, new SystemRequestDetails()); + assertEquals("2", pUpdated.getMeta().getVersionId()); + + new TransactionTemplate(myTxManager).executeWithoutResult(t -> { + JpaPid pid = myIdHelperService.getPidOrNull(null, pUpdated); + var versions = myResourceHistoryTableDao.findAllVersionsForResourceIdInOrder(pid.toFk()); + assertThat(versions).hasSize(2); + ourLog.info("{}", versions); + }); + + // when + var resources = myTestDaoSearch.searchForResources("Patient?active=true"); + + // then + assertThat(resources).isNotEmpty() + .first() + .describedAs("search should find resource body.") + .isNotNull(); + } + +} From ce6c6308999f9656ab6e5e6e53f441ac2b191c27 Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Tue, 5 Aug 2025 13:44:27 -0400 Subject: [PATCH 2/2] Try to reproduce weird bug we saw in Mass-Ingestion. --- .../fhir/jpa/dao/r4/MassIngestionR4Test.java | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/MassIngestionR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/MassIngestionR4Test.java index 7d76e462f9a3..681d7f4f4e68 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/MassIngestionR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/MassIngestionR4Test.java @@ -1,8 +1,11 @@ package ca.uhn.fhir.jpa.dao.r4; +import ca.uhn.fhir.interceptor.model.RequestPartitionId; import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; import ca.uhn.fhir.jpa.model.dao.JpaPid; import ca.uhn.fhir.jpa.test.BaseJpaR4Test; +import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.api.server.SystemRequestDetails; import ca.uhn.fhir.util.BundleBuilder; import org.hl7.fhir.r4.model.Bundle; @@ -15,13 +18,16 @@ import org.springframework.transaction.support.TransactionTemplate; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; public class MassIngestionR4Test extends BaseJpaR4Test { private static final Logger ourLog = LoggerFactory.getLogger(MassIngestionR4Test.class); + private IParser myParser; + @BeforeEach void beforeEach() { + myParser = myFhirContext.newJsonParser(); myStorageSettings.setMassIngestionMode(true); + myStorageSettings.setAutoCreatePlaceholderReferenceTargets(true); } @AfterEach @@ -31,37 +37,36 @@ public void afterEach() { @Test void testUpdateWithClientAssignedId_canFindBySearch() { - // given - Patient p = new Patient(); - p.setId("client-id"); - // first update is create. V1 - myPatientDao.update(p, mySrd); - assertEquals("1", p.getMeta().getVersionId()); - - // Second update should update. Create V2 + // given a bundle creating a patient with a client assigned ID Patient pUpdated = new Patient(); pUpdated.setId("client-id"); pUpdated.setActive(true); Bundle b = new BundleBuilder(myFhirContext).addTransactionUpdateEntry(pUpdated).andThen().getBundleTyped(); - var txResult = mySystemDao.transaction(new SystemRequestDetails(), b); - //myPatientDao.update(pUpdated, new SystemRequestDetails()); - assertEquals("2", pUpdated.getMeta().getVersionId()); + String bString = myParser.encodeResourceToString(b); + var txResult = mySystemDao.transaction(new SystemRequestDetails(), myParser.parseResource(Bundle.class, bString)); + var txResult2 = mySystemDao.transaction(new SystemRequestDetails(), myParser.parseResource(Bundle.class, bString)); + + // when + var resources = myTestDaoSearch.searchForResources("Patient?active=true"); + + // then new TransactionTemplate(myTxManager).executeWithoutResult(t -> { - JpaPid pid = myIdHelperService.getPidOrNull(null, pUpdated); + JpaPid pid = myIdHelperService.getPidOrThrowException(RequestPartitionId.allPartitions(), new IdDt("Patient/client-id")); + var resourceTable = myResourceTableDao.findById(pid); + assertThat(resourceTable.get().getVersion()).isEqualTo(2); + var versions = myResourceHistoryTableDao.findAllVersionsForResourceIdInOrder(pid.toFk()); assertThat(versions).hasSize(2); ourLog.info("{}", versions); }); - // when - var resources = myTestDaoSearch.searchForResources("Patient?active=true"); - - // then assertThat(resources).isNotEmpty() .first() .describedAs("search should find resource body.") .isNotNull(); + + } }