Merge remote-tracking branch 'origin/master' into pw/searchparam-reindex-configuration

# Conflicts:
#	src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
This commit is contained in:
Patrick Werner
2025-10-30 10:18:58 +01:00
7 changed files with 554 additions and 10 deletions

View File

@@ -61,7 +61,15 @@ public class AppProperties {
private Boolean filter_search_enabled = true;
private Boolean graphql_enabled = false;
private Boolean binary_storage_enabled = false;
private Integer inline_resource_storage_below_size = 0;
public enum BinaryStorageMode {
DATABASE,
FILESYSTEM
}
private BinaryStorageMode binary_storage_mode = BinaryStorageMode.DATABASE;
private String binary_storage_filesystem_base_directory;
private Integer inline_resource_storage_below_size;
private Boolean bulk_export_enabled = false;
private Boolean bulk_import_enabled = false;
private Boolean default_pretty_print = true;
@@ -119,6 +127,8 @@ public class AppProperties {
private Boolean match_url_cache_enabled = false;
private Boolean index_storage_optimized = false;
private Boolean mark_resources_for_reindexing_upon_search_parameter_change = true;
private Integer reindex_thread_count = null;
private Integer expunge_thread_count = null;
public List<String> getCustomInterceptorClasses() {
return custom_interceptor_classes;
@@ -484,6 +494,22 @@ public class AppProperties {
this.binary_storage_enabled = binary_storage_enabled;
}
public BinaryStorageMode getBinary_storage_mode() {
return binary_storage_mode;
}
public void setBinary_storage_mode(BinaryStorageMode binary_storage_mode) {
this.binary_storage_mode = binary_storage_mode;
}
public String getBinary_storage_filesystem_base_directory() {
return binary_storage_filesystem_base_directory;
}
public void setBinary_storage_filesystem_base_directory(String binary_storage_filesystem_base_directory) {
this.binary_storage_filesystem_base_directory = binary_storage_filesystem_base_directory;
}
public Integer getInline_resource_storage_below_size() {
return inline_resource_storage_below_size;
}
@@ -796,6 +822,22 @@ public class AppProperties {
mark_resources_for_reindexing_upon_search_parameter_change;
}
public Integer getReindex_thread_count() {
return reindex_thread_count;
}
public void setReindex_thread_count(Integer reindex_thread_count) {
this.reindex_thread_count = reindex_thread_count;
}
public Integer getExpunge_thread_count() {
return expunge_thread_count;
}
public void setExpunge_thread_count(Integer expunge_thread_count) {
this.expunge_thread_count = expunge_thread_count;
}
public JpaStorageSettings.StoreMetaSourceInformationEnum getStore_meta_source_information() {
return store_meta_source_information;
}

View File

@@ -1,8 +1,8 @@
package ca.uhn.fhir.jpa.starter.common;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
import ca.uhn.fhir.jpa.binary.api.IBinaryStorageSvc;
import ca.uhn.fhir.jpa.binstore.DatabaseBinaryContentStorageSvcImpl;
import ca.uhn.fhir.jpa.binstore.FilesystemBinaryStorageSvcImpl;
import ca.uhn.fhir.jpa.config.HibernatePropertiesProvider;
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.config.PartitionSettings.CrossPartitionReferenceMode;
@@ -19,10 +19,12 @@ import com.google.common.base.Strings;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.context.annotation.*;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.Assert;
import java.util.HashSet;
import java.util.stream.Collectors;
@@ -38,6 +40,7 @@ import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
public class FhirServerConfigCommon {
private static final Logger ourLog = LoggerFactory.getLogger(FhirServerConfigCommon.class);
private static final int DEFAULT_FILESYSTEM_INLINE_THRESHOLD = 102_400;
public FhirServerConfigCommon(AppProperties appProperties) {
ourLog.info(
@@ -224,8 +227,9 @@ public class FhirServerConfigCommon {
jpaStorageSettings.setLastNEnabled(true);
}
if (appProperties.getInline_resource_storage_below_size() != 0) {
jpaStorageSettings.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size());
Integer inlineResourceThreshold = resolveInlineResourceThreshold(appProperties);
if (inlineResourceThreshold != null && inlineResourceThreshold != 0) {
jpaStorageSettings.setInlineResourceTextBelowSize(inlineResourceThreshold);
}
jpaStorageSettings.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled());
@@ -284,6 +288,21 @@ public class FhirServerConfigCommon {
jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
jpaStorageSettings.setIndexIdentifierOfType(appProperties.getEnable_index_of_type());
// Configure thread counts for reindex and expunge operations
if (appProperties.getReindex_thread_count() != null) {
jpaStorageSettings.setReindexThreadCount(appProperties.getReindex_thread_count());
ourLog.info(
"Server configured to use {} threads for reindex operations",
appProperties.getReindex_thread_count());
}
if (appProperties.getExpunge_thread_count() != null) {
jpaStorageSettings.setExpungeThreadCount(appProperties.getExpunge_thread_count());
ourLog.info(
"Server configured to use {} threads for expunge operations",
appProperties.getExpunge_thread_count());
}
return jpaStorageSettings;
}
@@ -341,16 +360,50 @@ public class FhirServerConfigCommon {
return new JpaHibernatePropertiesProvider(myEntityManagerFactory);
}
@Lazy
@Bean
public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) {
DatabaseBinaryContentStorageSvcImpl binaryStorageSvc = new DatabaseBinaryContentStorageSvcImpl();
@ConditionalOnProperty(prefix = "hapi.fhir", name = "binary_storage_mode", havingValue = "FILESYSTEM")
public FilesystemBinaryStorageSvcImpl filesystemBinaryStorageSvc(AppProperties appProperties) {
String baseDirectory = appProperties.getBinary_storage_filesystem_base_directory();
Assert.hasText(
baseDirectory,
"binary_storage_filesystem_base_directory must be provided when binary_storage_mode=FILESYSTEM");
if (appProperties.getMax_binary_size() != null) {
binaryStorageSvc.setMaximumBinarySize(appProperties.getMax_binary_size());
FilesystemBinaryStorageSvcImpl filesystemSvc = new FilesystemBinaryStorageSvcImpl(baseDirectory);
Integer inlineResourceThreshold = resolveInlineResourceThreshold(appProperties);
int minimumBinarySize =
inlineResourceThreshold == null ? DEFAULT_FILESYSTEM_INLINE_THRESHOLD : inlineResourceThreshold;
filesystemSvc.setMinimumBinarySize(minimumBinarySize);
Integer maxBinarySize = appProperties.getMax_binary_size();
if (maxBinarySize != null) {
filesystemSvc.setMaximumBinarySize(maxBinarySize.longValue());
}
return binaryStorageSvc;
return filesystemSvc;
}
@Bean
@ConditionalOnProperty(
prefix = "hapi.fhir",
name = "binary_storage_mode",
havingValue = "DATABASE",
matchIfMissing = true)
public DatabaseBinaryContentStorageSvcImpl databaseBinaryStorageSvc(AppProperties appProperties) {
DatabaseBinaryContentStorageSvcImpl databaseSvc = new DatabaseBinaryContentStorageSvcImpl();
Integer maxBinarySize = appProperties.getMax_binary_size();
if (maxBinarySize != null) {
databaseSvc.setMaximumBinarySize(maxBinarySize.longValue());
}
return databaseSvc;
}
private Integer resolveInlineResourceThreshold(AppProperties appProperties) {
Integer inlineResourceThreshold = appProperties.getInline_resource_storage_below_size();
if (inlineResourceThreshold == null
&& appProperties.getBinary_storage_mode() == AppProperties.BinaryStorageMode.FILESYSTEM) {
return DEFAULT_FILESYSTEM_INLINE_THRESHOLD;
}
return inlineResourceThreshold;
}
@Bean

View File

@@ -279,6 +279,11 @@ hapi:
# filter_search_enabled: true
# graphql_enabled: true
# Thread pool configuration for maintenance operations
# Defaults to Runtime.getRuntime().availableProcessors() if not specified
# reindex_thread_count: 4 # Number of threads to use for reindex operations
# expunge_thread_count: 4 # Number of threads to use for expunge operations
# -------------------------------------------------------------------------------
# G. Narrative & Validation
# -------------------------------------------------------------------------------
@@ -381,6 +386,14 @@ hapi:
# max_page_size: 200
# retain_cached_searches_mins: 60
# reuse_cached_search_results_millis: 60000
# validation:
# requests_enabled: true
# responses_enabled: true
# binary_storage_enabled: true
# binary_storage_mode: FILESYSTEM
# binary_storage_filesystem_base_directory: /binstore
# When binary_storage_mode is FILESYSTEM and this value is not set,
# the starter defaults to 102400 bytes so smaller binaries stay inline.
inline_resource_storage_below_size: 4000
# -------------------------------------------------------------------------------