Improve paging in JPA server for _history operation
This commit is contained in:
parent
ef23b45d25
commit
0dd6364fe5
|
@ -0,0 +1,9 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.java]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = tab
|
|
@ -201,7 +201,12 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer preferredPageSize() {
|
public Integer preferredPageSize() {
|
||||||
return null;
|
return resources.preferredPageSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUuid() {
|
||||||
|
return resources.getUuid();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
|
public abstract class BasePagingProvider implements IPagingProvider {
|
||||||
|
|
||||||
|
private int myDefaultPageSize = 10;
|
||||||
|
private int myMaximumPageSize = 50;
|
||||||
|
|
||||||
|
public BasePagingProvider() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDefaultPageSize() {
|
||||||
|
return myDefaultPageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaximumPageSize() {
|
||||||
|
return myMaximumPageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BasePagingProvider setDefaultPageSize(int theDefaultPageSize) {
|
||||||
|
Validate.isTrue(theDefaultPageSize > 0, "size must be greater than 0");
|
||||||
|
myDefaultPageSize = theDefaultPageSize;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BasePagingProvider setMaximumPageSize(int theMaximumPageSize) {
|
||||||
|
Validate.isTrue(theMaximumPageSize > 0, "size must be greater than 0");
|
||||||
|
myMaximumPageSize = theMaximumPageSize;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -64,6 +64,11 @@ public class BundleProviders {
|
||||||
public Integer preferredPageSize() {
|
public Integer preferredPageSize() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUuid() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,9 @@ import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
public class FifoMemoryPagingProvider implements IPagingProvider {
|
public class FifoMemoryPagingProvider extends BasePagingProvider implements IPagingProvider {
|
||||||
|
|
||||||
private LinkedHashMap<String, IBundleProvider> myBundleProviders;
|
private LinkedHashMap<String, IBundleProvider> myBundleProviders;
|
||||||
private int myDefaultPageSize=10;
|
|
||||||
private int myMaximumPageSize=50;
|
|
||||||
private int mySize;
|
private int mySize;
|
||||||
|
|
||||||
public FifoMemoryPagingProvider(int theSize) {
|
public FifoMemoryPagingProvider(int theSize) {
|
||||||
|
@ -39,33 +37,11 @@ public class FifoMemoryPagingProvider implements IPagingProvider {
|
||||||
myBundleProviders = new LinkedHashMap<String, IBundleProvider>(mySize);
|
myBundleProviders = new LinkedHashMap<String, IBundleProvider>(mySize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getDefaultPageSize() {
|
|
||||||
return myDefaultPageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaximumPageSize() {
|
|
||||||
return myMaximumPageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized IBundleProvider retrieveResultList(String theId) {
|
public synchronized IBundleProvider retrieveResultList(String theId) {
|
||||||
return myBundleProviders.get(theId);
|
return myBundleProviders.get(theId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FifoMemoryPagingProvider setDefaultPageSize(int theDefaultPageSize) {
|
|
||||||
Validate.isTrue(theDefaultPageSize > 0, "size must be greater than 0");
|
|
||||||
myDefaultPageSize = theDefaultPageSize;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FifoMemoryPagingProvider setMaximumPageSize(int theMaximumPageSize) {
|
|
||||||
Validate.isTrue(theMaximumPageSize > 0, "size must be greater than 0");
|
|
||||||
myMaximumPageSize = theMaximumPageSize;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized String storeResultList(IBundleProvider theList) {
|
public synchronized String storeResultList(IBundleProvider theList) {
|
||||||
while (myBundleProviders.size() > mySize) {
|
while (myBundleProviders.size() > mySize) {
|
||||||
|
|
|
@ -62,4 +62,15 @@ public interface IBundleProvider {
|
||||||
*/
|
*/
|
||||||
InstantDt getPublished();
|
InstantDt getPublished();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the UUID associated with this search. Note that this
|
||||||
|
* does not need to return a non-null value unless it a
|
||||||
|
* {@link IPagingProvider} is being used that requires UUIDs
|
||||||
|
* being returned.
|
||||||
|
* <p>
|
||||||
|
* Otherwise you may simply return {@code null}
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public String getUuid();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,4 +66,9 @@ public class SimpleBundleProvider implements IBundleProvider {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUuid() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,20 +56,34 @@ public abstract class BaseSearchParamRegistry implements ISearchParamRegistry {
|
||||||
// nothing by default
|
// nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Map<String, RuntimeSearchParam>> getBuiltInSearchParams() {
|
@Override
|
||||||
|
public Map<String, Map<String, RuntimeSearchParam>> getActiveSearchParams() {
|
||||||
return myBuiltInSearchParams;
|
return myBuiltInSearchParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String,RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
|
public Map<String, RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
|
||||||
Validate.notBlank(theResourceName, "theResourceName must not be blank or null");
|
Validate.notBlank(theResourceName, "theResourceName must not be blank or null");
|
||||||
|
|
||||||
return myBuiltInSearchParams.get(theResourceName);
|
return myBuiltInSearchParams.get(theResourceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<RuntimeSearchParam> getAllSearchParams(String theResourceName) {
|
||||||
|
Validate.notBlank(theResourceName, "theResourceName must not be null or blank");
|
||||||
|
|
||||||
|
Map<String, RuntimeSearchParam> map = myBuiltInSearchParams.get(theResourceName);
|
||||||
|
map = ObjectUtils.defaultIfNull(map, EMPTY_SP_MAP);
|
||||||
|
return Collections.unmodifiableCollection(map.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Map<String, RuntimeSearchParam>> getBuiltInSearchParams() {
|
||||||
|
return myBuiltInSearchParams;
|
||||||
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void postConstruct() {
|
public void postConstruct() {
|
||||||
Map<String, Map<String, RuntimeSearchParam>> resourceNameToSearchParams = new HashMap<String, Map<String,RuntimeSearchParam>>();
|
Map<String, Map<String, RuntimeSearchParam>> resourceNameToSearchParams = new HashMap<String, Map<String, RuntimeSearchParam>>();
|
||||||
|
|
||||||
for (IFhirResourceDao<?> nextDao : myDaos) {
|
for (IFhirResourceDao<?> nextDao : myDaos) {
|
||||||
RuntimeResourceDefinition nextResDef = myCtx.getResourceDefinition(nextDao.getResourceType());
|
RuntimeResourceDefinition nextResDef = myCtx.getResourceDefinition(nextDao.getResourceType());
|
||||||
|
@ -85,13 +99,4 @@ public abstract class BaseSearchParamRegistry implements ISearchParamRegistry {
|
||||||
myBuiltInSearchParams = Collections.unmodifiableMap(resourceNameToSearchParams);
|
myBuiltInSearchParams = Collections.unmodifiableMap(resourceNameToSearchParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<RuntimeSearchParam> getAllSearchParams(String theResourceName) {
|
|
||||||
Validate.notBlank(theResourceName, "theResourceName must not be null or blank");
|
|
||||||
|
|
||||||
Map<String, RuntimeSearchParam> map = myBuiltInSearchParams.get(theResourceName);
|
|
||||||
map = ObjectUtils.defaultIfNull(map, EMPTY_SP_MAP);
|
|
||||||
return Collections.unmodifiableCollection(map.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,12 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
|
|
||||||
public interface ISearchParamRegistry {
|
public interface ISearchParamRegistry {
|
||||||
|
|
||||||
|
void forceRefresh();
|
||||||
|
|
||||||
|
Map<String, Map<String, RuntimeSearchParam>> getActiveSearchParams();
|
||||||
|
|
||||||
Map<String,RuntimeSearchParam> getActiveSearchParams(String theResourceName);
|
Map<String,RuntimeSearchParam> getActiveSearchParams(String theResourceName);
|
||||||
|
|
||||||
Collection<RuntimeSearchParam> getAllSearchParams(String theResourceName);
|
Collection<RuntimeSearchParam> getAllSearchParams(String theResourceName);
|
||||||
|
|
||||||
void forceRefresh();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2309,6 +2309,11 @@ public class SearchBuilder {
|
||||||
public int size() {
|
public int size() {
|
||||||
return myPids.size();
|
return myPids.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUuid() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.search;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
@ -30,10 +31,12 @@ import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.dao.IDao;
|
import ca.uhn.fhir.jpa.dao.IDao;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||||
|
import ca.uhn.fhir.rest.server.BasePagingProvider;
|
||||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||||
|
|
||||||
public class DatabaseBackedPagingProvider extends FifoMemoryPagingProvider {
|
public class DatabaseBackedPagingProvider extends BasePagingProvider implements IPagingProvider {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PlatformTransactionManager thePlatformTransactionManager;
|
private PlatformTransactionManager thePlatformTransactionManager;
|
||||||
|
@ -46,29 +49,36 @@ public class DatabaseBackedPagingProvider extends FifoMemoryPagingProvider {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IFhirSystemDao<?, ?> theDao;
|
private IFhirSystemDao<?, ?> theDao;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @deprecated Use {@link DatabaseBackedPagingProvider} as this constructor has no purpose
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public DatabaseBackedPagingProvider(int theSize) {
|
public DatabaseBackedPagingProvider(int theSize) {
|
||||||
super(theSize);
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public DatabaseBackedPagingProvider() {
|
||||||
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized IBundleProvider retrieveResultList(String theId) {
|
public synchronized IBundleProvider retrieveResultList(String theId) {
|
||||||
IBundleProvider retVal = super.retrieveResultList(theId);
|
|
||||||
if (retVal == null) {
|
|
||||||
PersistedJpaBundleProvider provider = new PersistedJpaBundleProvider(theId, theDao);
|
PersistedJpaBundleProvider provider = new PersistedJpaBundleProvider(theId, theDao);
|
||||||
if (!provider.ensureSearchEntityLoaded()) {
|
if (!provider.ensureSearchEntityLoaded()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
retVal = provider;
|
return provider;
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized String storeResultList(IBundleProvider theList) {
|
public synchronized String storeResultList(IBundleProvider theList) {
|
||||||
if (theList instanceof PersistedJpaBundleProvider) {
|
String uuid = theList.getUuid();
|
||||||
return ((PersistedJpaBundleProvider)theList).getSearchUuid();
|
Validate.notNull(uuid);
|
||||||
}
|
return uuid;
|
||||||
return super.storeResultList(theList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,7 @@ package ca.uhn.fhir.jpa.search;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
import java.util.*;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.NoResultException;
|
import javax.persistence.NoResultException;
|
||||||
|
@ -49,11 +43,7 @@ import ca.uhn.fhir.jpa.dao.IDao;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchBuilder;
|
import ca.uhn.fhir.jpa.dao.SearchBuilder;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
import ca.uhn.fhir.jpa.entity.*;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
|
||||||
import ca.uhn.fhir.jpa.entity.SearchResult;
|
|
||||||
import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
|
|
||||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||||
|
|
||||||
|
@ -220,7 +210,7 @@ public final class PersistedJpaBundleProvider implements IBundleProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSearchUuid() {
|
public String getUuid() {
|
||||||
return myUuid;
|
return myUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,11 @@ public class SearchParamExtractorDstu3Test {
|
||||||
public Collection<RuntimeSearchParam> getAllSearchParams(String theResourceName) {
|
public Collection<RuntimeSearchParam> getAllSearchParams(String theResourceName) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Map<String, RuntimeSearchParam>> getActiveSearchParams() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(ourCtx, ourValidationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(ourCtx, ourValidationSupport, searchParamRegistry);
|
||||||
|
|
|
@ -575,6 +575,11 @@ public class SearchDstu2Test {
|
||||||
public int size() {
|
public int size() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUuid() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,13 @@
|
||||||
JPA server did not return an OperationOutcome in the response for
|
JPA server did not return an OperationOutcome in the response for
|
||||||
a normal delete operation.
|
a normal delete operation.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
Fix an issue in JPA server where _history results were kept in memory instead
|
||||||
|
of being spooled to the database as they should be. Note that as a part of this fix
|
||||||
|
a new method was added to
|
||||||
|
<![CDATA[<code>IBundleProvider</code> called <code>getUuid()</code>]]>. This
|
||||||
|
method may return <![CDATA[<code>null</code>]]> in any current cases.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="2.2" date="2016-12-20">
|
<release version="2.2" date="2016-12-20">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
Loading…
Reference in New Issue