Work on #164 - Correct performance issue

This commit is contained in:
James Agnew 2015-05-15 15:14:55 -04:00
parent fbcd15a16d
commit da3ec668de
5 changed files with 162 additions and 175 deletions

View File

@ -368,18 +368,6 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName, String theParamName, Class<? extends BaseResourceIndexedSearchParam> theParamTable) {
String resourceType = getContext().getResourceDefinition(getResourceType()).getName();
{ // TODO: rmeove this!
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Object> cq = builder.createQuery();
Root<? extends BaseResourceIndexedSearchParam> subQfrom = cq.from(theParamTable);
cq.select(subQfrom);
Predicate subQname = builder.equal(subQfrom.get("myParamName"), theParamName);
Predicate subQtype = builder.equal(subQfrom.get("myResourceType"), resourceType);
cq.where(builder.and(subQtype, subQname));
List<Object> results = myEntityManager.createQuery(cq).getResultList();
ourLog.info("All results: {}", results);
}
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
Root<ResourceTable> from = cq.from(ResourceTable.class);
@ -424,12 +412,13 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
subQ.where(createResourceLinkPathPredicate(theParamName, builder, subQfrom));
Predicate joinPredicate = builder.not(builder.in(from.get("myId")).value(subQ));
Predicate typePredicate = builder.equal(from.get("myResourceType"), myResourceName);
if (thePids.size() > 0) {
Predicate inPids = (from.get("myId").in(thePids));
cq.where(builder.and(inPids, joinPredicate));
cq.where(builder.and(inPids, typePredicate, joinPredicate));
} else {
cq.where(joinPredicate);
cq.where(builder.and(typePredicate, joinPredicate));
}
TypedQuery<Long> q = myEntityManager.createQuery(cq);

View File

@ -1676,7 +1676,7 @@ public class FhirResourceDaoDstu2Test {
@Test
public void testSearchWithMissingReference() {
IdDt orgId = ourOrganizationDao.create(new Organization()).getId();
IdDt orgId = ourOrganizationDao.create(new Organization()).getId().toUnqualifiedVersionless();
IdDt notMissing;
IdDt missing;
{
@ -1710,6 +1710,7 @@ public class FhirResourceDaoDstu2Test {
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
assertThat(patients, containsInRelativeOrder(missing));
assertThat(patients, not(containsInRelativeOrder(notMissing)));
assertThat(patients, not(containsInRelativeOrder(orgId)));
}
}

View File

@ -53,70 +53,31 @@ public class ResourceProviderDstu1Test {
private static ClassPathXmlApplicationContext ourAppCtx;
private static IGenericClient ourClient;
private static DaoConfig ourDaoConfig;
private static FhirContext ourFhirCtx;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu1Test.class);
private static IFhirResourceDao<Organization> ourOrganizationDao;
// private static IFhirResourceDao<Observation> ourObservationDao;
// private static IFhirResourceDao<Patient> ourPatientDao;
// private static IFhirResourceDao<Questionnaire> ourQuestionnaireDao;
private static Server ourServer;
private static IFhirResourceDao<Organization> ourOrganizationDao;
private static DaoConfig ourDaoConfig;
// private static JpaConformanceProvider ourConfProvider;
/**
* Test for issue #60
*/
@Test
public void testStoreUtf8Characters() throws Exception {
Organization org = new Organization();
org.setName("測試醫院");
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
// Read back directly from the DAO
{
Organization returned = ourOrganizationDao.read(orgId);
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
ourLog.info(val);
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
}
// Read back through the HTTP API
{
Organization returned = ourClient.read(Organization.class, orgId);
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
ourLog.info(val);
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
private void delete(String theResourceType, String theParamName, String theParamValue) {
Bundle resources = ourClient.search().forResource(theResourceType).where(new StringClientParam(theParamName).matches().value(theParamValue)).execute();
for (IResource next : resources.toListOfResources()) {
ourLog.info("Deleting resource: {}", next.getId());
ourClient.delete().resource(next).execute();
}
}
@Test
public void testSearchWithInclude() throws Exception {
Organization org = new Organization();
org.addIdentifier().setSystem("urn:system").setValue( "testSearchWithInclude01");
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
Patient pat = new Patient();
pat.addIdentifier().setSystem("urn:system").setValue("testSearchWithInclude02");
pat.getManagingOrganization().setReference(orgId);
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
//@formatter:off
Bundle found = ourClient
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("urn:system","testSearchWithInclude02"))
.include(Patient.INCLUDE_MANAGINGORGANIZATION)
.execute();
//@formatter:on
assertEquals(2, found.size());
assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
assertEquals(null, found.getEntries().get(0).getSearchMode().getValueAsEnum());
assertEquals(null, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
assertEquals(Organization.class, found.getEntries().get(1).getResource().getClass());
assertEquals(null, found.getEntries().get(1).getSearchMode().getValueAsEnum());
assertEquals(null, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue) {
Bundle resources = ourClient.search().forResource(theResourceType).where(new TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
for (IResource next : resources.toListOfResources()) {
ourLog.info("Deleting resource: {}", next.getId());
ourClient.delete().resource(next).execute();
}
}
@ -143,96 +104,6 @@ public class ResourceProviderDstu1Test {
}
/**
* See issue #52
*/
@Test
public void testImagingStudyResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(ImagingStudy.class).execute().size();
String resBody = IOUtils.toString(ResourceProviderDstu1Test.class.getResource("/imagingstudy.json"));
client.create().resource(resBody).execute();
int newSize = client.search().forResource(ImagingStudy.class).execute().size();
assertEquals(1, newSize - initialSize);
}
/**
* See issue #52
*/
@Test
public void testDocumentManifestResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(DocumentManifest.class).execute().size();
String resBody = IOUtils.toString(ResourceProviderDstu1Test.class.getResource("/documentmanifest.json"));
client.create().resource(resBody).execute();
int newSize = client.search().forResource(DocumentManifest.class).execute().size();
assertEquals(1, newSize - initialSize);
}
/**
* See issue #52
*/
@Test
public void testDocumentReferenceResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(DocumentReference.class).execute().size();
String resBody = IOUtils.toString(ResourceProviderDstu1Test.class.getResource("/documentreference.json"));
client.create().resource(resBody).execute();
int newSize = client.search().forResource(DocumentReference.class).execute().size();
assertEquals(1, newSize - initialSize);
}
/**
* See issue #52
*/
@Test
public void testDiagnosticOrderResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(DiagnosticOrder.class).execute().size();
DiagnosticOrder res = new DiagnosticOrder();
res.addIdentifier().setSystem("urn:foo").setValue( "123");
client.create().resource(res).execute();
int newSize = client.search().forResource(DiagnosticOrder.class).execute().size();
assertEquals(1, newSize - initialSize);
}
private void delete(String theResourceType, String theParamName, String theParamValue) {
Bundle resources = ourClient.search().forResource(theResourceType).where(new StringClientParam(theParamName).matches().value(theParamValue)).execute();
for (IResource next : resources.toListOfResources()) {
ourLog.info("Deleting resource: {}", next.getId());
ourClient.delete().resource(next).execute();
}
}
private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue) {
Bundle resources = ourClient.search().forResource(theResourceType).where(new TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
for (IResource next : resources.toListOfResources()) {
ourLog.info("Deleting resource: {}", next.getId());
ourClient.delete().resource(next).execute();
}
}
@Test
public void testCreateWithClientSuppliedId() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testCreateWithId01");
@ -302,6 +173,80 @@ public class ResourceProviderDstu1Test {
}
/**
* See issue #52
*/
@Test
public void testDiagnosticOrderResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(DiagnosticOrder.class).execute().size();
DiagnosticOrder res = new DiagnosticOrder();
res.addIdentifier().setSystem("urn:foo").setValue( "123");
client.create().resource(res).execute();
int newSize = client.search().forResource(DiagnosticOrder.class).execute().size();
assertEquals(1, newSize - initialSize);
}
/**
* See issue #52
*/
@Test
public void testDocumentManifestResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(DocumentManifest.class).execute().size();
String resBody = IOUtils.toString(ResourceProviderDstu1Test.class.getResource("/documentmanifest.json"));
client.create().resource(resBody).execute();
int newSize = client.search().forResource(DocumentManifest.class).execute().size();
assertEquals(1, newSize - initialSize);
}
/**
* See issue #52
*/
@Test
public void testDocumentReferenceResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(DocumentReference.class).execute().size();
String resBody = IOUtils.toString(ResourceProviderDstu1Test.class.getResource("/documentreference.json"));
client.create().resource(resBody).execute();
int newSize = client.search().forResource(DocumentReference.class).execute().size();
assertEquals(1, newSize - initialSize);
}
/**
* See issue #52
*/
@Test
public void testImagingStudyResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(ImagingStudy.class).execute().size();
String resBody = IOUtils.toString(ResourceProviderDstu1Test.class.getResource("/imagingstudy.json"));
client.create().resource(resBody).execute();
int newSize = client.search().forResource(ImagingStudy.class).execute().size();
assertEquals(1, newSize - initialSize);
}
@Test
public void testSaveAndRetrieveExistingNarrative() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSaveAndRetrieveExistingNarrative01");
@ -418,6 +363,61 @@ public class ResourceProviderDstu1Test {
}
@Test
public void testSearchWithInclude() throws Exception {
Organization org = new Organization();
org.addIdentifier().setSystem("urn:system").setValue( "testSearchWithInclude01");
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
Patient pat = new Patient();
pat.addIdentifier().setSystem("urn:system").setValue("testSearchWithInclude02");
pat.getManagingOrganization().setReference(orgId);
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
//@formatter:off
Bundle found = ourClient
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("urn:system","testSearchWithInclude02"))
.include(Patient.INCLUDE_MANAGINGORGANIZATION)
.execute();
//@formatter:on
assertEquals(2, found.size());
assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
assertEquals(null, found.getEntries().get(0).getSearchMode().getValueAsEnum());
assertEquals(null, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
assertEquals(Organization.class, found.getEntries().get(1).getResource().getClass());
assertEquals(null, found.getEntries().get(1).getSearchMode().getValueAsEnum());
assertEquals(null, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
}
/**
* Test for issue #60
*/
@Test
public void testStoreUtf8Characters() throws Exception {
Organization org = new Organization();
org.setName("測試醫院");
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
// Read back directly from the DAO
{
Organization returned = ourOrganizationDao.read(orgId);
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
ourLog.info(val);
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
}
// Read back through the HTTP API
{
Organization returned = ourClient.read(Organization.class, orgId);
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
ourLog.info(val);
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
}
}
@Test
public void testTryToCreateResourceWithReferenceThatDoesntExist() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testTryToCreateResourceWithReferenceThatDoesntExist01");

View File

@ -398,6 +398,14 @@ public class ResourceProviderDstu2Test {
ourLog.info("Starting testSearchWithMissing");
String methodName = "testSearchWithMissing";
List<IResource> resources = new ArrayList<IResource>();
for (int i = 0; i < 20; i++) {
Organization org = new Organization();
org.setName(methodName + "_0" + i);
resources.add(org);
}
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
Organization org = new Organization();
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
org.setName(methodName + "name");
@ -413,45 +421,31 @@ public class ResourceProviderDstu2Test {
.search()
.forResource(Organization.class)
.where(Organization.NAME.isMissing(false))
.limitTo(100)
.prettyPrint()
.execute();
//@formatter:on
List<IdDt> list = toIdListUnqualifiedVersionless(found);
ourLog.info(methodName + ": " + list.toString());
assertThat(list, containsInRelativeOrder(orgNotMissing));
assertThat("Wanted " + orgNotMissing + " but got: " + list, list, containsInRelativeOrder(orgNotMissing));
assertThat(list, not(containsInRelativeOrder(orgMissing)));
}
/*
* The next search seems to not always work on the first try. I've checked the SQL that gets generated by
* hibernate and it appears to be correct, and I've verified that everything that's in the database
* is good too. I'm surmising that some weird interplat between the way Derby flushes to disk and the
* way the nested query that gets used works is causing a timing issue. Bottom line, this seems to
* succeed after a few tries....
*/
for (int i = 0;i < 5; i++)
{
//@formatter:off
Bundle found = ourClient
.search()
.forResource(Organization.class)
.where(Organization.NAME.isMissing(true))
.limitTo(100)
.prettyPrint()
.execute();
//@formatter:on
List<IdDt> list = toIdListUnqualifiedVersionless(found);
if (!list.contains(orgMissing)) {
if (i < 5) {
Thread.sleep(1000);
continue;
}
}
ourLog.info(methodName + " found: " + list.toString() + " - Wanted " + orgMissing + " but not " + orgNotMissing);
assertThat(list, not(containsInRelativeOrder(orgNotMissing)));
assertThat("Wanted " + orgMissing + " but found: " + list, list, containsInRelativeOrder(orgMissing));
}
}
private List<IdDt> toIdListUnqualifiedVersionless(Bundle found) {

View File

@ -15,6 +15,9 @@
had tags but no other meta elements. Thanks to Bill de Beaubien and
Claude Nanjo for finding this.
</action>
<action type="fix" issue="164">
Correct performance issue with :missing=true search requests where the parameter is a resource link. Thanks to wanghaisheng for all his help in testing this.
</action>
</release>
<release version="1.0" date="2015-May-8">
<action type="add">