Fix tests for expiring search results
This commit is contained in:
parent
dd5580ed2d
commit
fa2950dacb
|
@ -99,7 +99,7 @@ public class DaoConfig {
|
|||
private int myMaximumExpansionSize = 5000;
|
||||
private int myMaximumSearchResultCountInTransaction = DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT_IN_TRANSACTION;
|
||||
private ResourceEncodingEnum myResourceEncoding = ResourceEncodingEnum.JSONC;
|
||||
private Long myReuseCachedSearchResultsForMillis;
|
||||
private Long myReuseCachedSearchResultsForMillis = DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS;
|
||||
private boolean mySchedulingDisabled;
|
||||
private boolean mySubscriptionEnabled;
|
||||
private long mySubscriptionPollDelay = 1000;
|
||||
|
|
|
@ -334,117 +334,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchReusesResultsEnabled() throws Exception {
|
||||
List<IBaseResource> resources = new ArrayList<IBaseResource>();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
Organization org = new Organization();
|
||||
org.setName("HELLO");
|
||||
resources.add(org);
|
||||
}
|
||||
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
|
||||
|
||||
myDaoConfig.setReuseCachedSearchResultsForMillis(1000L);
|
||||
|
||||
Bundle result1 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid1 = toSearchUuidFromLinkNext(result1);
|
||||
Search search1 = newTxTemplate().execute(new TransactionCallback<Search>() {
|
||||
@Override
|
||||
public Search doInTransaction(TransactionStatus theStatus) {
|
||||
return mySearchEntityDao.findByUuid(uuid1);
|
||||
}
|
||||
});
|
||||
Date lastReturned1 = search1.getSearchLastReturned();
|
||||
|
||||
Bundle result2 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid2 = toSearchUuidFromLinkNext(result2);
|
||||
Search search2 = newTxTemplate().execute(new TransactionCallback<Search>() {
|
||||
@Override
|
||||
public Search doInTransaction(TransactionStatus theStatus) {
|
||||
return mySearchEntityDao.findByUuid(uuid2);
|
||||
}
|
||||
});
|
||||
Date lastReturned2 = search2.getSearchLastReturned();
|
||||
|
||||
assertTrue(lastReturned2.getTime() > lastReturned1.getTime());
|
||||
|
||||
Thread.sleep(1500);
|
||||
|
||||
Bundle result3 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
String uuid3 = toSearchUuidFromLinkNext(result3);
|
||||
|
||||
assertEquals(uuid1, uuid2);
|
||||
assertNotEquals(uuid1, uuid3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchReusesResultsDisabled() throws Exception {
|
||||
List<IBaseResource> resources = new ArrayList<IBaseResource>();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
Organization org = new Organization();
|
||||
org.setName("HELLO");
|
||||
resources.add(org);
|
||||
}
|
||||
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
|
||||
|
||||
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
|
||||
|
||||
Bundle result1 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid1 = toSearchUuidFromLinkNext(result1);
|
||||
|
||||
Bundle result2 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid2 = toSearchUuidFromLinkNext(result2);
|
||||
|
||||
Bundle result3 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
String uuid3 = toSearchUuidFromLinkNext(result3);
|
||||
|
||||
assertNotEquals(uuid1, uuid2);
|
||||
assertNotEquals(uuid1, uuid3);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #438
|
||||
*/
|
||||
|
@ -517,6 +406,24 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
Validate.notNull(input);
|
||||
ourClient.create().resource(input).execute().getResource();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateConditional() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
|
||||
MethodOutcome output1 = ourClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute();
|
||||
|
||||
patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
|
||||
MethodOutcome output2 = ourClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute();
|
||||
|
||||
assertEquals(output1.getId().getIdPart(), output2.getId().getIdPart());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateIncludesRequestValidatorInterceptorOutcome() throws IOException {
|
||||
|
@ -548,23 +455,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateConditional() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
|
||||
MethodOutcome output1 = ourClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute();
|
||||
|
||||
patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
|
||||
MethodOutcome output2 = ourClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute();
|
||||
|
||||
assertEquals(output1.getId().getIdPart(), output2.getId().getIdPart());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testCreateQuestionnaireResponseWithValidation() throws IOException {
|
||||
|
@ -888,17 +778,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteReturnsOperationOutcome() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("FAM");
|
||||
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
IBaseOperationOutcome resp = ourClient.delete().resourceById(id).execute();
|
||||
OperationOutcome oo = (OperationOutcome) resp;
|
||||
assertThat(oo.getIssueFirstRep().getDiagnostics(), startsWith("Successfully deleted 1 resource(s) in "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteResourceConditional1() throws IOException {
|
||||
String methodName = "testDeleteResourceConditional1";
|
||||
|
@ -1027,24 +906,15 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue #52
|
||||
*/
|
||||
@Test
|
||||
public void testProcedureRequestResources() throws Exception {
|
||||
IGenericClient client = ourClient;
|
||||
|
||||
int initialSize = client.search().forResource(ProcedureRequest.class).returnBundle(Bundle.class).execute().getEntry().size();
|
||||
|
||||
ProcedureRequest res = new ProcedureRequest();
|
||||
res.addIdentifier().setSystem("urn:foo").setValue("123");
|
||||
|
||||
client.create().resource(res).execute();
|
||||
|
||||
int newSize = client.search().forResource(ProcedureRequest.class).returnBundle(Bundle.class).execute().getEntry().size();
|
||||
|
||||
assertEquals(1, newSize - initialSize);
|
||||
public void testDeleteReturnsOperationOutcome() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("FAM");
|
||||
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
IBaseOperationOutcome resp = ourClient.delete().resourceById(id).execute();
|
||||
OperationOutcome oo = (OperationOutcome) resp;
|
||||
assertThat(oo.getIssueFirstRep().getDiagnostics(), startsWith("Successfully deleted 1 resource(s) in "));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1285,31 +1155,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
// private void delete(String theResourceType, String theParamName, String theParamValue) {
|
||||
// Bundle resources;
|
||||
// do {
|
||||
// IQuery<Bundle> forResource = ourClient.search().forResource(theResourceType);
|
||||
// if (theParamName != null) {
|
||||
// forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
|
||||
// }
|
||||
// resources = forResource.execute();
|
||||
// for (IResource next : resources.toListOfResources()) {
|
||||
// ourLog.info("Deleting resource: {}", next.getId());
|
||||
// ourClient.delete().resource(next).execute();
|
||||
// }
|
||||
// } while (resources.size() > 0);
|
||||
// }
|
||||
//
|
||||
// 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();
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* See #147"Patient"
|
||||
*/
|
||||
|
@ -1432,6 +1277,31 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
// private void delete(String theResourceType, String theParamName, String theParamValue) {
|
||||
// Bundle resources;
|
||||
// do {
|
||||
// IQuery<Bundle> forResource = ourClient.search().forResource(theResourceType);
|
||||
// if (theParamName != null) {
|
||||
// forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
|
||||
// }
|
||||
// resources = forResource.execute();
|
||||
// for (IResource next : resources.toListOfResources()) {
|
||||
// ourLog.info("Deleting resource: {}", next.getId());
|
||||
// ourClient.delete().resource(next).execute();
|
||||
// }
|
||||
// } while (resources.size() > 0);
|
||||
// }
|
||||
//
|
||||
// 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 testEverythingPatientOperation() throws Exception {
|
||||
String methodName = "testEverythingOperation";
|
||||
|
@ -2271,6 +2141,26 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue #52
|
||||
*/
|
||||
@Test
|
||||
public void testProcedureRequestResources() throws Exception {
|
||||
IGenericClient client = ourClient;
|
||||
|
||||
int initialSize = client.search().forResource(ProcedureRequest.class).returnBundle(Bundle.class).execute().getEntry().size();
|
||||
|
||||
ProcedureRequest res = new ProcedureRequest();
|
||||
res.addIdentifier().setSystem("urn:foo").setValue("123");
|
||||
|
||||
client.create().resource(res).execute();
|
||||
|
||||
int newSize = client.search().forResource(ProcedureRequest.class).returnBundle(Bundle.class).execute().getEntry().size();
|
||||
|
||||
assertEquals(1, newSize - initialSize);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for issue #60
|
||||
*/
|
||||
|
@ -2813,6 +2703,147 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
assertTrue(new InstantDt(value) + " should be before " + new InstantDt(after), value.before(after));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchReusesNoParams() throws Exception {
|
||||
List<IBaseResource> resources = new ArrayList<IBaseResource>();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
Organization org = new Organization();
|
||||
org.setName("HELLO");
|
||||
resources.add(org);
|
||||
}
|
||||
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
|
||||
|
||||
myDaoConfig.setReuseCachedSearchResultsForMillis(1000L);
|
||||
|
||||
Bundle result1 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid1 = toSearchUuidFromLinkNext(result1);
|
||||
|
||||
Bundle result2 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid2 = toSearchUuidFromLinkNext(result2);
|
||||
|
||||
assertEquals(uuid1, uuid2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchReusesResultsDisabled() throws Exception {
|
||||
List<IBaseResource> resources = new ArrayList<IBaseResource>();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
Organization org = new Organization();
|
||||
org.setName("HELLO");
|
||||
resources.add(org);
|
||||
}
|
||||
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
|
||||
|
||||
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
|
||||
|
||||
Bundle result1 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid1 = toSearchUuidFromLinkNext(result1);
|
||||
|
||||
Bundle result2 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid2 = toSearchUuidFromLinkNext(result2);
|
||||
|
||||
Bundle result3 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
String uuid3 = toSearchUuidFromLinkNext(result3);
|
||||
|
||||
assertNotEquals(uuid1, uuid2);
|
||||
assertNotEquals(uuid1, uuid3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchReusesResultsEnabled() throws Exception {
|
||||
List<IBaseResource> resources = new ArrayList<IBaseResource>();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
Organization org = new Organization();
|
||||
org.setName("HELLO");
|
||||
resources.add(org);
|
||||
}
|
||||
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
|
||||
|
||||
myDaoConfig.setReuseCachedSearchResultsForMillis(1000L);
|
||||
|
||||
Bundle result1 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid1 = toSearchUuidFromLinkNext(result1);
|
||||
Search search1 = newTxTemplate().execute(new TransactionCallback<Search>() {
|
||||
@Override
|
||||
public Search doInTransaction(TransactionStatus theStatus) {
|
||||
return mySearchEntityDao.findByUuid(uuid1);
|
||||
}
|
||||
});
|
||||
Date lastReturned1 = search1.getSearchLastReturned();
|
||||
|
||||
Bundle result2 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
final String uuid2 = toSearchUuidFromLinkNext(result2);
|
||||
Search search2 = newTxTemplate().execute(new TransactionCallback<Search>() {
|
||||
@Override
|
||||
public Search doInTransaction(TransactionStatus theStatus) {
|
||||
return mySearchEntityDao.findByUuid(uuid2);
|
||||
}
|
||||
});
|
||||
Date lastReturned2 = search2.getSearchLastReturned();
|
||||
|
||||
assertTrue(lastReturned2.getTime() > lastReturned1.getTime());
|
||||
|
||||
Thread.sleep(1500);
|
||||
|
||||
Bundle result3 = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.where(Organization.NAME.matches().value("HELLO"))
|
||||
.count(5)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
String uuid3 = toSearchUuidFromLinkNext(result3);
|
||||
|
||||
assertEquals(uuid1, uuid2);
|
||||
assertNotEquals(uuid1, uuid3);
|
||||
}
|
||||
|
||||
/**
|
||||
* See #316
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,7 @@ public class ExampleServerIT {
|
|||
|
||||
@Test
|
||||
public void testCreateAndRead() throws IOException {
|
||||
ourLog.info("Base URL is: http://localhost:" + ourPort + "/baseDstu3");
|
||||
String methodName = "testCreateResourceConditional";
|
||||
|
||||
Patient pt = new Patient();
|
||||
|
|
|
@ -7,6 +7,40 @@
|
|||
</properties>
|
||||
<body>
|
||||
<release version="2.5" date="TBD">
|
||||
<action type="fix">
|
||||
<![CDATA[
|
||||
This release includes significant performance enhancements for the
|
||||
JPA server. Most importantly, the way that searches are performed
|
||||
has been re-written to allow the server to perform better when
|
||||
the database has a large number of results in it.
|
||||
<br/><br/>
|
||||
<ul>
|
||||
<li>
|
||||
Searches with multiple search parameters of different
|
||||
datatypes (e.g. find patients by name and date of birth)
|
||||
were previously joined in Java code, now the join is
|
||||
performed by the database which is faster
|
||||
</li>
|
||||
<li>
|
||||
Searches which returned lots of results previously has all
|
||||
results streamed into memory before anything was returned to
|
||||
the client. This is particularly slow if you do a search for
|
||||
(say) "get me all patients" since potentially thousands or
|
||||
even millions of patients' IDs were loaded into memory
|
||||
before anything gets returned to the client. HAPI FHIR
|
||||
now has a multithreaded search coordinator which returns
|
||||
results to the client as soon as they are available
|
||||
</li>
|
||||
</ul>
|
||||
<br/><br/>
|
||||
Existing users should delete the
|
||||
<code>HFJ_SEARCH</code>,
|
||||
<code>HFJ_SEARCH_INCLUDE</code>,
|
||||
and
|
||||
<code>HFJ_SEARCH_RESULT</code>
|
||||
tables from your database before upgrading.
|
||||
]]>
|
||||
</action>
|
||||
<action type="fix" issue="590">
|
||||
AuthorizationInterceptor did not correctly handle paging requests
|
||||
(e.g. requests for the second page of results for a search operation).
|
||||
|
|
Loading…
Reference in New Issue