Refactor and fix functionality dealing with ReadPartitionIdRequestDetails (#5691)
* Throw exception when resourceType of parameter value is invalid when performing FHIR search with non-chained reference * Fix changelog issue id and spotless warning * Cleanup unnecessary test * Validate resourceType only when using relative reference * Fix test for search using _type parameter * Refactor and fix functionality dealing with ReadPartitionIdRequestDetails * Spotless fixes * Revert some of the refactoring changes to BaseRequestPartitionHelperSvc and fix tests * Small cleanup * Missing change * Small changes * Fix tests and add a few more * Spotless fix * Address code review comments * Some polishing on the interface annotations and documentation * Spotless fix * Fix test * Fix tests and test method rename * Ensure SearchParameterMap is not null --------- Co-authored-by: Martha Mitran <martha.mitran@smilecdr.com>
This commit is contained in:
parent
c8d6e9fb73
commit
e5d410d10b
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.batch2.model.JobInstance;
|
|||
import ca.uhn.fhir.batch2.model.JobInstanceStartRequest;
|
||||
import ca.uhn.fhir.batch2.model.StatusEnum;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.batch.models.Batch2JobStartResponse;
|
||||
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
|
@ -106,6 +107,7 @@ public class BulkImportCommandTest {
|
|||
writeNdJsonFileToTempDirectory(fileContents1, "file1.json");
|
||||
writeNdJsonFileToTempDirectory(fileContents2, "file2.json");
|
||||
|
||||
when(myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(any(), any())).thenReturn(RequestPartitionId.allPartitions());
|
||||
when(myJobCoordinator.startInstance(any(), any())).thenReturn(createJobStartResponse("THE-JOB-ID"));
|
||||
|
||||
// Start the command in a separate thread
|
||||
|
@ -149,6 +151,7 @@ public class BulkImportCommandTest {
|
|||
|
||||
when(myJobCoordinator.startInstance(any(), any()))
|
||||
.thenReturn(createJobStartResponse("THE-JOB-ID"));
|
||||
when(myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(any(), any())).thenReturn(RequestPartitionId.allPartitions());
|
||||
|
||||
// Start the command in a separate thread
|
||||
new Thread(() -> App.main(new String[]{
|
||||
|
@ -189,6 +192,7 @@ public class BulkImportCommandTest {
|
|||
writeNdJsonFileToTempDirectory(fileContents1, "file1.json");
|
||||
writeNdJsonFileToTempDirectory(fileContents2, "file2.json");
|
||||
|
||||
when(myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(any(), any())).thenReturn(RequestPartitionId.allPartitions());
|
||||
when(myJobCoordinator.startInstance(any(), any())).thenReturn(createJobStartResponse("THE-JOB-ID"));
|
||||
|
||||
// Start the command in a separate thread
|
||||
|
|
|
@ -30,7 +30,6 @@ import ca.uhn.fhir.i18n.Msg;
|
|||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
|
@ -1249,9 +1248,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public IBundleProvider history(Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails) {
|
||||
StopWatch w = new StopWatch();
|
||||
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forHistory(myResourceName, null);
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, details);
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForHistory(
|
||||
theRequestDetails, myResourceName, null);
|
||||
IBundleProvider retVal = myTransactionService
|
||||
.withRequest(theRequestDetails)
|
||||
.withRequestPartitionId(requestPartitionId)
|
||||
|
@ -1270,9 +1269,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
final IIdType theId, final Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequest) {
|
||||
StopWatch w = new StopWatch();
|
||||
|
||||
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forHistory(myResourceName, theId);
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequest(theRequest, details);
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForHistory(
|
||||
theRequest, myResourceName, theId);
|
||||
IBundleProvider retVal = myTransactionService
|
||||
.withRequest(theRequest)
|
||||
.withRequestPartitionId(requestPartitionId)
|
||||
|
@ -1300,9 +1299,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
final HistorySearchDateRangeParam theHistorySearchDateRangeParam,
|
||||
RequestDetails theRequest) {
|
||||
StopWatch w = new StopWatch();
|
||||
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forHistory(myResourceName, theId);
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequest(theRequest, details);
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForHistory(
|
||||
theRequest, myResourceName, theId);
|
||||
IBundleProvider retVal = myTransactionService
|
||||
.withRequest(theRequest)
|
||||
.withRequestPartitionId(requestPartitionId)
|
||||
|
@ -1349,10 +1348,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
addAllResourcesTypesToReindex(theBase, theRequestDetails, params);
|
||||
}
|
||||
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forOperation(null, null, ProviderConstants.OPERATION_REINDEX);
|
||||
RequestPartitionId requestPartition =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, details);
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, ProviderConstants.OPERATION_REINDEX);
|
||||
params.setRequestPartitionId(requestPartition);
|
||||
|
||||
JobInstanceStartRequest request = new JobInstanceStartRequest();
|
||||
|
@ -1976,7 +1974,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForSearchType(
|
||||
theRequest, getResourceName(), theParams, null);
|
||||
theRequest, getResourceName(), theParams);
|
||||
IBundleProvider retVal = mySearchCoordinatorSvc.registerSearch(
|
||||
this, theParams, getResourceName(), cacheControlDirective, theRequest, requestPartitionId);
|
||||
|
||||
|
@ -2145,7 +2143,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
BiFunction<RequestDetails, Stream<JpaPid>, Stream<V>> transform) {
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForSearchType(
|
||||
theRequest, myResourceName, theParams, null);
|
||||
theRequest, myResourceName, theParams);
|
||||
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ package ca.uhn.fhir.jpa.dao;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||
|
@ -158,9 +157,9 @@ public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends B
|
|||
@Override
|
||||
public IBundleProvider history(Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails) {
|
||||
StopWatch w = new StopWatch();
|
||||
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forHistory(null, null);
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, details);
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForHistory(
|
||||
theRequestDetails, null, null);
|
||||
IBundleProvider retVal = myTransactionService
|
||||
.withRequest(theRequestDetails)
|
||||
.withRequestPartitionId(requestPartitionId)
|
||||
|
|
|
@ -65,7 +65,7 @@ public class JpaResourceDaoObservation<T extends IBaseResource> extends BaseHapi
|
|||
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForSearchType(
|
||||
theRequestDetails, getResourceName(), theSearchParameterMap, null);
|
||||
theRequestDetails, getResourceName(), theSearchParameterMap);
|
||||
return mySearchCoordinatorSvc.registerSearch(
|
||||
this,
|
||||
theSearchParameterMap,
|
||||
|
@ -128,7 +128,7 @@ public class JpaResourceDaoObservation<T extends IBaseResource> extends BaseHapi
|
|||
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForSearchType(
|
||||
theRequestDetails, getResourceName(), theSearchParameterMap, null);
|
||||
theRequestDetails, getResourceName(), theSearchParameterMap);
|
||||
|
||||
List<List<IQueryParameterType>> patientParams = new ArrayList<>();
|
||||
if (theSearchParameterMap.get(getPatientParamName()) != null) {
|
||||
|
|
|
@ -106,7 +106,7 @@ public class JpaResourceDaoPatient<T extends IBaseResource> extends BaseHapiFhir
|
|||
}
|
||||
|
||||
RequestPartitionId requestPartitionId = myPartitionHelperSvc.determineReadPartitionForRequestForSearchType(
|
||||
theRequest, getResourceName(), paramMap, null);
|
||||
theRequest, getResourceName(), paramMap);
|
||||
|
||||
adjustCount(theRequest, paramMap);
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ package ca.uhn.fhir.jpa.dao.expunge;
|
|||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
|
||||
import ca.uhn.fhir.jpa.entity.Batch2JobInstanceEntity;
|
||||
|
@ -135,10 +134,9 @@ public class ExpungeEverythingService implements IExpungeEverythingService {
|
|||
|
||||
ourLog.info("BEGINNING GLOBAL $expunge");
|
||||
Propagation propagation = Propagation.REQUIRES_NEW;
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forOperation(null, null, ProviderConstants.OPERATION_EXPUNGE);
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequest(theRequest, details);
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(
|
||||
theRequest, ProviderConstants.OPERATION_EXPUNGE);
|
||||
|
||||
deleteAll(theRequest, propagation, requestPartitionId, counter);
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ package ca.uhn.fhir.jpa.search.reindex;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
|
@ -33,6 +32,9 @@ import ca.uhn.fhir.jpa.dao.IJpaStorageResourceParser;
|
|||
import ca.uhn.fhir.jpa.dao.tx.IHapiTransactionService;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.SearchParamPresentEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.*;
|
||||
import ca.uhn.fhir.jpa.partition.BaseRequestPartitionHelperSvc;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||
|
@ -236,8 +238,7 @@ public class InstanceReindexServiceImpl implements IInstanceReindexService {
|
|||
|
||||
@Nonnull
|
||||
private RequestPartitionId determinePartition(RequestDetails theRequestDetails, IIdType theResourceId) {
|
||||
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forRead(theResourceId);
|
||||
return myPartitionHelperSvc.determineReadPartitionForRequest(theRequestDetails, details);
|
||||
return myPartitionHelperSvc.determineReadPartitionForRequestForRead(theRequestDetails, theResourceId);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
|
|
@ -25,7 +25,6 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.batch.models.Batch2JobStartResponse;
|
||||
import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
|
||||
|
@ -184,7 +183,8 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
|||
MdmTransactionContext theMdmTransactionContext,
|
||||
RequestDetails theRequestDetails) {
|
||||
RequestPartitionId theReadPartitionId =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequest(theRequestDetails, null);
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, ProviderConstants.MDM_QUERY_LINKS);
|
||||
Page<MdmLinkJson> resultPage;
|
||||
if (theReadPartitionId.hasPartitionIds()) {
|
||||
theMdmQuerySearchParameters.setPartitionIds(theReadPartitionId.getPartitionIds());
|
||||
|
@ -242,7 +242,8 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
|||
String theRequestResourceType) {
|
||||
Page<MdmLinkJson> resultPage;
|
||||
RequestPartitionId readPartitionId =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequest(theRequestDetails, null);
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, ProviderConstants.MDM_DUPLICATE_GOLDEN_RESOURCES);
|
||||
|
||||
if (readPartitionId.isAllPartitions()) {
|
||||
resultPage = myMdmLinkQuerySvc.getDuplicateGoldenResources(
|
||||
|
@ -318,10 +319,9 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
|||
params.setBatchSize(theBatchSize.getValue().intValue());
|
||||
}
|
||||
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forOperation(null, null, ProviderConstants.OPERATION_MDM_CLEAR);
|
||||
RequestPartitionId requestPartition =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequest(theRequestDetails, details);
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, ProviderConstants.OPERATION_MDM_CLEAR);
|
||||
params.setRequestPartitionId(requestPartition);
|
||||
|
||||
JobInstanceStartRequest request = new JobInstanceStartRequest();
|
||||
|
|
|
@ -38,6 +38,8 @@ public class MdmResourceDaoSvcTest extends BaseMdmR4Test {
|
|||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
private PatientIdPartitionInterceptor myPatientIdPartitionInterceptor;
|
||||
|
||||
@Override
|
||||
@AfterEach
|
||||
public void after() throws IOException {
|
||||
|
@ -104,9 +106,8 @@ public class MdmResourceDaoSvcTest extends BaseMdmR4Test {
|
|||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myPartitionSettings.setUnnamedPartitionMode(true);
|
||||
myPartitionSettings.setIncludePartitionInSearchHashes(false);
|
||||
|
||||
PatientIdPartitionInterceptor interceptor = new PatientIdPartitionInterceptor(myFhirContext, mySearchParamExtractor, myPartitionSettings);
|
||||
myInterceptorRegistry.registerInterceptor(interceptor);
|
||||
myPatientIdPartitionInterceptor = new PatientIdPartitionInterceptor(getFhirContext(), mySearchParamExtractor, myPartitionSettings);
|
||||
myInterceptorRegistry.registerInterceptor(myPatientIdPartitionInterceptor);
|
||||
|
||||
try {
|
||||
StringOrListParam patientIds = new StringOrListParam();
|
||||
|
@ -154,7 +155,7 @@ public class MdmResourceDaoSvcTest extends BaseMdmR4Test {
|
|||
Patient patient = (Patient) result.getAllResources().get(0);
|
||||
assertTrue(patient.getId().contains(firstId.getValue()));
|
||||
} finally {
|
||||
myInterceptorRegistry.unregisterInterceptor(interceptor);
|
||||
myInterceptorRegistry.unregisterInterceptor(myPatientIdPartitionInterceptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,18 +108,9 @@ public class ReadPartitionIdRequestDetails extends PartitionIdRequestDetails {
|
|||
return forRead(theId.getResourceType(), theId, false);
|
||||
}
|
||||
|
||||
public static ReadPartitionIdRequestDetails forOperation(
|
||||
@Nullable String theResourceType, @Nullable IIdType theId, @Nonnull String theExtendedOperationName) {
|
||||
RestOperationTypeEnum op;
|
||||
if (theId != null) {
|
||||
op = RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE;
|
||||
} else if (theResourceType != null) {
|
||||
op = RestOperationTypeEnum.EXTENDED_OPERATION_TYPE;
|
||||
} else {
|
||||
op = RestOperationTypeEnum.EXTENDED_OPERATION_SERVER;
|
||||
}
|
||||
|
||||
return new ReadPartitionIdRequestDetails(theResourceType, op, null, null, null, null, theExtendedOperationName);
|
||||
public static ReadPartitionIdRequestDetails forServerOperation(@Nonnull String theOperationName) {
|
||||
return new ReadPartitionIdRequestDetails(
|
||||
null, RestOperationTypeEnum.EXTENDED_OPERATION_SERVER, null, null, null, null, theOperationName);
|
||||
}
|
||||
|
||||
public static ReadPartitionIdRequestDetails forRead(
|
||||
|
@ -135,7 +126,7 @@ public class ReadPartitionIdRequestDetails extends PartitionIdRequestDetails {
|
|||
theResourceType,
|
||||
RestOperationTypeEnum.SEARCH_TYPE,
|
||||
null,
|
||||
theParams,
|
||||
theParams != null ? theParams : SearchParameterMap.newSynchronous(),
|
||||
theConditionalOperationTargetOrNull,
|
||||
null,
|
||||
null);
|
||||
|
|
|
@ -34,39 +34,119 @@ public interface IRequestPartitionHelperSvc {
|
|||
|
||||
@Nonnull
|
||||
RequestPartitionId determineReadPartitionForRequest(
|
||||
@Nullable RequestDetails theRequest, ReadPartitionIdRequestDetails theDetails);
|
||||
@Nullable RequestDetails theRequest, @Nonnull ReadPartitionIdRequestDetails theDetails);
|
||||
|
||||
/**
|
||||
* Determine partition to use when performing a server operation such as $bulk-import, $bulk-export, $reindex etc.
|
||||
* @param theRequest the request details from the context of the call
|
||||
* @param theOperationName the explicit name of the operation
|
||||
* @return the partition id which should be used for the operation
|
||||
*/
|
||||
@Nonnull
|
||||
default RequestPartitionId determineReadPartitionForRequestForServerOperation(
|
||||
@Nullable RequestDetails theRequest, @Nonnull String theOperationName) {
|
||||
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forServerOperation(theOperationName);
|
||||
return determineReadPartitionForRequest(theRequest, details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine partition to use when performing database reads based on a resource instance.
|
||||
* @param theRequest the request details from the context of the call
|
||||
* @param theId the id of the resource instance
|
||||
* @return the partition id which should be used for the database read
|
||||
*/
|
||||
@Nonnull
|
||||
default RequestPartitionId determineReadPartitionForRequestForRead(
|
||||
RequestDetails theRequest, String theResourceType, @Nonnull IIdType theId) {
|
||||
@Nullable RequestDetails theRequest, @Nonnull IIdType theId) {
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forRead(theId.getResourceType(), theId, theId.hasVersionIdPart());
|
||||
return determineReadPartitionForRequest(theRequest, details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine partition to use when performing database reads against a certain resource type based on a resource instance.
|
||||
* @param theRequest the request details from the context of the call
|
||||
* @param theResourceType the resource type
|
||||
* @param theId the id of the resource instance
|
||||
* @return the partition id which should be used for the database read
|
||||
*/
|
||||
@Nonnull
|
||||
default RequestPartitionId determineReadPartitionForRequestForRead(
|
||||
@Nullable RequestDetails theRequest, @Nonnull String theResourceType, @Nonnull IIdType theId) {
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forRead(theResourceType, theId, theId.hasVersionIdPart());
|
||||
return determineReadPartitionForRequest(theRequest, details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine partition to use when performing a database search against a certain resource type.
|
||||
* @param theRequest the request details from the context of the call
|
||||
* @param theResourceType the resource type
|
||||
* @return the partition id which should be used for the database search
|
||||
*/
|
||||
@Nonnull
|
||||
default RequestPartitionId determineReadPartitionForRequestForSearchType(
|
||||
@Nullable RequestDetails theRequest, @Nonnull String theResourceType) {
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forSearchType(theResourceType, SearchParameterMap.newSynchronous(), null);
|
||||
return determineReadPartitionForRequest(theRequest, details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine partition to use when performing a database search based on a resource type and other search parameters.
|
||||
* @param theRequest the request details from the context of the call
|
||||
* @param theResourceType the resource type
|
||||
* @param theParams the search parameters
|
||||
* @return the partition id which should be used for the database search
|
||||
*/
|
||||
@Nonnull
|
||||
default RequestPartitionId determineReadPartitionForRequestForSearchType(
|
||||
@Nullable RequestDetails theRequest,
|
||||
@Nonnull String theResourceType,
|
||||
@Nonnull SearchParameterMap theParams) {
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forSearchType(theResourceType, theParams, null);
|
||||
return determineReadPartitionForRequest(theRequest, details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine partition to use when performing a database search based on a resource type, search parameters and a conditional target resource (if available).
|
||||
* @param theRequest the request details from the context of the call
|
||||
* @param theResourceType the resource type
|
||||
* @param theParams the search parameters
|
||||
* @param theConditionalOperationTargetOrNull the conditional target resource
|
||||
* @return the partition id which should be used for the database search
|
||||
*/
|
||||
@Nonnull
|
||||
default RequestPartitionId determineReadPartitionForRequestForSearchType(
|
||||
RequestDetails theRequest,
|
||||
String theResourceType,
|
||||
SearchParameterMap theParams,
|
||||
IBaseResource theConditionalOperationTargetOrNull) {
|
||||
SearchParameterMap searchParameterMap = theParams != null ? theParams : SearchParameterMap.newSynchronous();
|
||||
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forSearchType(
|
||||
theResourceType, theParams, theConditionalOperationTargetOrNull);
|
||||
theResourceType, searchParameterMap, theConditionalOperationTargetOrNull);
|
||||
return determineReadPartitionForRequest(theRequest, details);
|
||||
}
|
||||
|
||||
RequestPartitionId determineGenericPartitionForRequest(RequestDetails theRequestDetails);
|
||||
|
||||
/**
|
||||
* Determine partition to use when performing the history operation based on a resource type and resource instance.
|
||||
* @param theRequest the request details from the context of the call
|
||||
* @param theResourceType the resource type
|
||||
* @param theIdType the id of the resource instance
|
||||
* @return the partition id which should be used for the history operation
|
||||
*/
|
||||
@Nonnull
|
||||
default RequestPartitionId determineReadPartitionForRequestForHistory(
|
||||
RequestDetails theRequest, String theResourceType, IIdType theIdType) {
|
||||
@Nullable RequestDetails theRequest, String theResourceType, IIdType theIdType) {
|
||||
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forHistory(theResourceType, theIdType);
|
||||
return determineReadPartitionForRequest(theRequest, details);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
default void validateHasPartitionPermissions(
|
||||
RequestDetails theRequest, String theResourceType, RequestPartitionId theRequestPartitionId) {}
|
||||
@Nonnull RequestDetails theRequest, String theResourceType, RequestPartitionId theRequestPartitionId) {}
|
||||
|
||||
@Nonnull
|
||||
RequestPartitionId determineCreatePartitionForRequest(
|
||||
|
|
|
@ -136,7 +136,7 @@ public class SubscriptionMatcherInterceptor {
|
|||
// Even though the resource is being written, the subscription will be interacting with it by effectively
|
||||
// "reading" it so we set the RequestPartitionId as a read request
|
||||
RequestPartitionId requestPartitionId = myRequestPartitionHelperSvc.determineReadPartitionForRequestForRead(
|
||||
theRequest, theNewResource.getIdElement().getResourceType(), theNewResource.getIdElement());
|
||||
theRequest, theNewResource.getIdElement());
|
||||
return new ResourceModifiedMessage(
|
||||
myFhirContext, theNewResource, theOperationType, theRequest, requestPartitionId);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import ca.uhn.fhir.util.JsonUtil;
|
|||
import ca.uhn.fhir.util.SearchParameterUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
|
@ -62,7 +63,6 @@ import org.slf4j.LoggerFactory;
|
|||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -71,7 +71,6 @@ import java.util.Set;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -1245,7 +1244,7 @@ public class BulkDataExportProviderTest {
|
|||
|
||||
private class MyRequestPartitionHelperSvc extends RequestPartitionHelperSvc {
|
||||
@Override
|
||||
public @NotNull RequestPartitionId determineReadPartitionForRequest(RequestDetails theRequest, ReadPartitionIdRequestDetails theDetails) {
|
||||
public @NotNull RequestPartitionId determineReadPartitionForRequest(@Nonnull RequestDetails theRequest, @Nonnull ReadPartitionIdRequestDetails theDetails) {
|
||||
assert theRequest != null;
|
||||
if (myPartitionName.equals(theRequest.getTenantId())) {
|
||||
return myRequestPartitionId;
|
||||
|
@ -1255,7 +1254,7 @@ public class BulkDataExportProviderTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void validateHasPartitionPermissions(RequestDetails theRequest, String theResourceType, RequestPartitionId theRequestPartitionId) {
|
||||
public void validateHasPartitionPermissions(@Nonnull RequestDetails theRequest, String theResourceType, RequestPartitionId theRequestPartitionId) {
|
||||
if (!myPartitionName.equals(theRequest.getTenantId()) && theRequest.getTenantId() != null) {
|
||||
throw new ForbiddenOperationException("User does not have access to resources on the requested partition");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package ca.uhn.fhir.jpa.bulk;
|
||||
|
||||
import ca.uhn.fhir.jpa.interceptor.PatientIdPartitionInterceptor;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.server.provider.BulkDataExportProvider;
|
||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
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.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class BulkExportWithPatientIdPartitioningTest extends BaseResourceProviderR4Test {
|
||||
private final Logger ourLog = LoggerFactory.getLogger(BulkExportWithPatientIdPartitioningTest.class);
|
||||
|
||||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
private PatientIdPartitionInterceptor myPatientIdPartitionInterceptor;
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
myPatientIdPartitionInterceptor = new PatientIdPartitionInterceptor(getFhirContext(), mySearchParamExtractor, myPartitionSettings);
|
||||
myInterceptorRegistry.registerInterceptor(myPatientIdPartitionInterceptor);
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myPartitionSettings.setUnnamedPartitionMode(true);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void after() {
|
||||
myInterceptorRegistry.unregisterInterceptor(myPatientIdPartitionInterceptor);
|
||||
myPartitionSettings.setPartitioningEnabled(new PartitionSettings().isPartitioningEnabled());
|
||||
myPartitionSettings.setUnnamedPartitionMode(new PartitionSettings().isUnnamedPartitionMode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSystemBulkExport_withResourceType_success() throws IOException {
|
||||
HttpPost post = new HttpPost(myServer.getBaseUrl() + "/" + ProviderConstants.OPERATION_EXPORT);
|
||||
post.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC);
|
||||
post.addHeader(BulkDataExportProvider.PARAM_EXPORT_TYPE, "Patient");
|
||||
post.addHeader(BulkDataExportProvider.PARAM_EXPORT_TYPE_FILTER, "Patient?");
|
||||
|
||||
try (CloseableHttpResponse postResponse = myServer.getHttpClient().execute(post)) {
|
||||
ourLog.info("Response: {}", postResponse);
|
||||
assertEquals(202, postResponse.getStatusLine().getStatusCode());
|
||||
assertEquals("Accepted", postResponse.getStatusLine().getReasonPhrase());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSystemBulkExport_withResourceType_pollSuccessful() throws IOException {
|
||||
HttpPost post = new HttpPost(myServer.getBaseUrl() + "/" + ProviderConstants.OPERATION_EXPORT);
|
||||
post.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC);
|
||||
post.addHeader(BulkDataExportProvider.PARAM_EXPORT_TYPE, "Patient"); // ignored when computing partition
|
||||
post.addHeader(BulkDataExportProvider.PARAM_EXPORT_TYPE_FILTER, "Patient?");
|
||||
|
||||
String locationUrl;
|
||||
|
||||
try (CloseableHttpResponse postResponse = myServer.getHttpClient().execute(post)) {
|
||||
ourLog.info("Response: {}", postResponse);
|
||||
assertEquals(202, postResponse.getStatusLine().getStatusCode());
|
||||
assertEquals("Accepted", postResponse.getStatusLine().getReasonPhrase());
|
||||
|
||||
Header locationHeader = postResponse.getFirstHeader(Constants.HEADER_CONTENT_LOCATION);
|
||||
assertNotNull(locationHeader);
|
||||
locationUrl = locationHeader.getValue();
|
||||
}
|
||||
|
||||
HttpGet get = new HttpGet(locationUrl);
|
||||
try (CloseableHttpResponse postResponse = myServer.getHttpClient().execute(get)) {
|
||||
ourLog.info("Response: {}", postResponse);
|
||||
assertEquals(202, postResponse.getStatusLine().getStatusCode());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package ca.uhn.fhir.jpa.bulk.imprt2;
|
||||
|
||||
import ca.uhn.fhir.batch2.api.IJobCoordinator;
|
||||
import ca.uhn.fhir.batch2.api.IJobMaintenanceService;
|
||||
import ca.uhn.fhir.batch2.jobs.imprt.BulkImportAppCtx;
|
||||
import ca.uhn.fhir.batch2.jobs.imprt.BulkImportFileServlet;
|
||||
import ca.uhn.fhir.batch2.jobs.imprt.BulkImportJobParameters;
|
||||
import ca.uhn.fhir.batch2.model.JobInstance;
|
||||
import ca.uhn.fhir.batch2.model.JobInstanceStartRequest;
|
||||
import ca.uhn.fhir.batch2.model.StatusEnum;
|
||||
import ca.uhn.fhir.jpa.batch.models.Batch2JobStartResponse;
|
||||
import ca.uhn.fhir.jpa.interceptor.PatientIdPartitionInterceptor;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
|
||||
import ca.uhn.fhir.test.utilities.server.HttpServletExtension;
|
||||
import ca.uhn.fhir.util.JsonUtil;
|
||||
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.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.blankOrNullString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* This test class has just one test. It can potentially be moved
|
||||
*/
|
||||
public class BulkImportWithPatientIdPartitioningTest extends BaseJpaR4Test {
|
||||
private static final String USERNAME = "username";
|
||||
private static final String PASSWORD = "password";
|
||||
private static final BulkImportFileServlet ourBulkImportFileServlet = new BulkImportFileServlet(USERNAME, PASSWORD);
|
||||
|
||||
@RegisterExtension
|
||||
public static HttpServletExtension myHttpServletExtension = new HttpServletExtension().withServlet(ourBulkImportFileServlet);
|
||||
|
||||
@Autowired
|
||||
private IJobCoordinator myJobCoordinator;
|
||||
@Autowired
|
||||
private IJobMaintenanceService myJobCleanerService;
|
||||
|
||||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
private PatientIdPartitionInterceptor myPatientIdPartitionInterceptor;
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
myPatientIdPartitionInterceptor = new PatientIdPartitionInterceptor(getFhirContext(), mySearchParamExtractor, myPartitionSettings);
|
||||
myInterceptorRegistry.registerInterceptor(myPatientIdPartitionInterceptor);
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myPartitionSettings.setUnnamedPartitionMode(true);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void after() {
|
||||
myInterceptorRegistry.unregisterInterceptor(myPatientIdPartitionInterceptor);
|
||||
myPartitionSettings.setPartitioningEnabled(new PartitionSettings().isPartitioningEnabled());
|
||||
myPartitionSettings.setUnnamedPartitionMode(new PartitionSettings().isUnnamedPartitionMode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBulkImport_withOneResource_successful() {
|
||||
// Setup
|
||||
|
||||
Patient p = new Patient().setActive(true);
|
||||
p.setId("P1");
|
||||
String fileContents = getFhirContext().newJsonParser().encodeResourceToString(p);
|
||||
String id = ourBulkImportFileServlet.registerFileByContents(fileContents);
|
||||
|
||||
BulkImportJobParameters parameters = new BulkImportJobParameters();
|
||||
parameters.setHttpBasicCredentials(USERNAME + ":" + PASSWORD);
|
||||
parameters.addNdJsonUrl(myHttpServletExtension.getBaseUrl() + "/download?index=" + id);
|
||||
|
||||
JobInstanceStartRequest request = new JobInstanceStartRequest();
|
||||
request.setJobDefinitionId(BulkImportAppCtx.JOB_BULK_IMPORT_PULL);
|
||||
request.setParameters(parameters);
|
||||
|
||||
// Execute
|
||||
|
||||
Batch2JobStartResponse startResponse = myJobCoordinator.startInstance(request);
|
||||
String instanceId = startResponse.getInstanceId();
|
||||
assertThat(instanceId, not(blankOrNullString()));
|
||||
ourLog.info("Execution got ID: {}", instanceId);
|
||||
|
||||
// Verify
|
||||
|
||||
await().atMost(120, TimeUnit.SECONDS).until(() -> {
|
||||
myJobCleanerService.runMaintenancePass();
|
||||
JobInstance instance = myJobCoordinator.getInstance(instanceId);
|
||||
return instance.getStatus();
|
||||
}, equalTo(StatusEnum.COMPLETED));
|
||||
|
||||
runInTransaction(() -> {
|
||||
assertEquals(1, myResourceTableDao.count());
|
||||
});
|
||||
|
||||
runInTransaction(() -> {
|
||||
JobInstance instance = myJobCoordinator.getInstance(instanceId);
|
||||
ourLog.info("Instance details:\n{}", JsonUtil.serialize(instance, true));
|
||||
assertEquals(0, instance.getErrorCount());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package ca.uhn.fhir.jpa.interceptor;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
|
||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.r4.model.Annotation;
|
||||
|
@ -16,28 +16,26 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class PatientCompartmentEnforcingInterceptorTest extends BaseJpaR4Test {
|
||||
public class PatientCompartmentEnforcingInterceptorTest extends BaseResourceProviderR4Test {
|
||||
|
||||
public static final int ALTERNATE_DEFAULT_ID = -1;
|
||||
private PatientIdPartitionInterceptor mySvc;
|
||||
private ForceOffsetSearchModeInterceptor myForceOffsetSearchModeInterceptor;
|
||||
private PatientCompartmentEnforcingInterceptor myUpdateCrossPartitionInterceptor;
|
||||
|
||||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
private ForceOffsetSearchModeInterceptor myForceOffsetSearchModeInterceptor;
|
||||
private PatientIdPartitionInterceptor myPatientIdPartitionInterceptor;
|
||||
private PatientCompartmentEnforcingInterceptor mySvc;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
mySvc = new PatientIdPartitionInterceptor(myFhirContext, mySearchParamExtractor, myPartitionSettings);
|
||||
myForceOffsetSearchModeInterceptor = new ForceOffsetSearchModeInterceptor();
|
||||
myUpdateCrossPartitionInterceptor = new PatientCompartmentEnforcingInterceptor(
|
||||
myFhirContext, mySearchParamExtractor);
|
||||
myPatientIdPartitionInterceptor = new PatientIdPartitionInterceptor(getFhirContext(), mySearchParamExtractor, myPartitionSettings);
|
||||
mySvc = new PatientCompartmentEnforcingInterceptor(getFhirContext(), mySearchParamExtractor);
|
||||
|
||||
myInterceptorRegistry.registerInterceptor(mySvc);
|
||||
myInterceptorRegistry.registerInterceptor(myPatientIdPartitionInterceptor);
|
||||
myInterceptorRegistry.registerInterceptor(myForceOffsetSearchModeInterceptor);
|
||||
myInterceptorRegistry.registerInterceptor(myUpdateCrossPartitionInterceptor);
|
||||
myInterceptorRegistry.registerInterceptor(mySvc);
|
||||
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myPartitionSettings.setUnnamedPartitionMode(true);
|
||||
|
@ -46,9 +44,9 @@ public class PatientCompartmentEnforcingInterceptorTest extends BaseJpaR4Test {
|
|||
|
||||
@AfterEach
|
||||
public void after() {
|
||||
myInterceptorRegistry.unregisterInterceptor(mySvc);
|
||||
myInterceptorRegistry.unregisterInterceptor(myPatientIdPartitionInterceptor);
|
||||
myInterceptorRegistry.unregisterInterceptor(myForceOffsetSearchModeInterceptor);
|
||||
myInterceptorRegistry.unregisterInterceptor(myUpdateCrossPartitionInterceptor);
|
||||
myInterceptorRegistry.unregisterInterceptor(mySvc);
|
||||
|
||||
myPartitionSettings.setPartitioningEnabled(false);
|
||||
myPartitionSettings.setUnnamedPartitionMode(new PartitionSettings().isUnnamedPartitionMode());
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package ca.uhn.fhir.jpa.interceptor;
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
|
@ -12,10 +10,8 @@ import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
|||
import ca.uhn.fhir.jpa.util.SqlQuery;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.bulk.BulkExportJobParameters;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
|
@ -40,7 +36,6 @@ import org.junit.jupiter.api.AfterEach;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
@ -56,19 +51,13 @@ import static org.hamcrest.Matchers.matchesPattern;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
public class PatientIdPartitionInterceptorTest extends BaseResourceProviderR4Test {
|
||||
public static final int ALTERNATE_DEFAULT_ID = -1;
|
||||
|
||||
private ForceOffsetSearchModeInterceptor myForceOffsetSearchModeInterceptor;
|
||||
|
||||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
@SpyBean
|
||||
@Autowired
|
||||
private ForceOffsetSearchModeInterceptor myForceOffsetSearchModeInterceptor;
|
||||
private PatientIdPartitionInterceptor mySvc;
|
||||
|
||||
@Override
|
||||
|
@ -76,6 +65,7 @@ public class PatientIdPartitionInterceptorTest extends BaseResourceProviderR4Tes
|
|||
public void before() throws Exception {
|
||||
super.before();
|
||||
myForceOffsetSearchModeInterceptor = new ForceOffsetSearchModeInterceptor();
|
||||
mySvc = new PatientIdPartitionInterceptor(getFhirContext(), mySearchParamExtractor, myPartitionSettings);
|
||||
|
||||
myInterceptorRegistry.registerInterceptor(mySvc);
|
||||
myInterceptorRegistry.registerInterceptor(myForceOffsetSearchModeInterceptor);
|
||||
|
@ -553,19 +543,7 @@ public class PatientIdPartitionInterceptorTest extends BaseResourceProviderR4Tes
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIdentifyForRead_serverOperation_returnsAllPartitions() {
|
||||
ReadPartitionIdRequestDetails readRequestDetails = ReadPartitionIdRequestDetails.forOperation(null, null, ProviderConstants.OPERATION_EXPORT);
|
||||
RequestPartitionId requestPartitionId = mySvc.identifyForRead(readRequestDetails, mySrd);
|
||||
assertEquals(requestPartitionId, RequestPartitionId.allPartitions());
|
||||
assertEquals(RestOperationTypeEnum.EXTENDED_OPERATION_SERVER, readRequestDetails.getRestOperationType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSystemBulkExport_withPatientIdPartitioningWithNoResourceType_usesNonPatientSpecificPartition() throws IOException {
|
||||
final BulkExportJobParameters options = new BulkExportJobParameters();
|
||||
options.setExportStyle(BulkExportJobParameters.ExportStyle.SYSTEM);
|
||||
options.setOutputFormat(Constants.CT_FHIR_NDJSON);
|
||||
|
||||
public void testSystemOperation_withNoResourceType_success() throws IOException {
|
||||
HttpPost post = new HttpPost(myServer.getBaseUrl() + "/" + ProviderConstants.OPERATION_EXPORT);
|
||||
post.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC);
|
||||
|
||||
|
@ -574,7 +552,5 @@ public class PatientIdPartitionInterceptorTest extends BaseResourceProviderR4Tes
|
|||
assertEquals(202, postResponse.getStatusLine().getStatusCode());
|
||||
assertEquals("Accepted", postResponse.getStatusLine().getReasonPhrase());
|
||||
}
|
||||
|
||||
verify(mySvc).provideNonPatientSpecificQueryResponse(any());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ import ca.uhn.fhir.util.ClasspathUtil;
|
|||
import org.hl7.fhir.utilities.npm.NpmPackage;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -30,8 +28,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class JpaPackageCacheTest extends BaseJpaR4Test {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(JpaPackageCacheTest.class);
|
||||
@Autowired
|
||||
private IHapiPackageCacheManager myPackageCacheManager;
|
||||
@Autowired
|
||||
|
@ -45,6 +41,8 @@ public class JpaPackageCacheTest extends BaseJpaR4Test {
|
|||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
private PatientIdPartitionInterceptor myPatientIdPartitionInterceptor;
|
||||
|
||||
@AfterEach
|
||||
public void disablePartitioning() {
|
||||
myPartitionSettings.setPartitioningEnabled(false);
|
||||
|
@ -79,8 +77,8 @@ public class JpaPackageCacheTest extends BaseJpaR4Test {
|
|||
public void testSaveAndDeletePackagePartitionsEnabled() throws IOException {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myPartitionSettings.setDefaultPartitionId(1);
|
||||
PatientIdPartitionInterceptor patientIdPartitionInterceptor = new PatientIdPartitionInterceptor(myFhirContext, mySearchParamExtractor, myPartitionSettings);
|
||||
myInterceptorService.registerInterceptor(patientIdPartitionInterceptor);
|
||||
myPatientIdPartitionInterceptor = new PatientIdPartitionInterceptor(getFhirContext(), mySearchParamExtractor, myPartitionSettings);
|
||||
myInterceptorService.registerInterceptor(myPatientIdPartitionInterceptor);
|
||||
myInterceptorService.registerInterceptor(myRequestTenantPartitionInterceptor);
|
||||
try {
|
||||
try (InputStream stream = ClasspathUtil.loadResourceAsStream("/packages/basisprofil.de.tar.gz")) {
|
||||
|
@ -108,7 +106,7 @@ public class JpaPackageCacheTest extends BaseJpaR4Test {
|
|||
List<String> deleteOutcomeMsgs = deleteOutcomeJson.getMessage();
|
||||
assertEquals("Deleting package basisprofil.de#0.2.40", deleteOutcomeMsgs.get(0));
|
||||
} finally {
|
||||
myInterceptorService.unregisterInterceptor(patientIdPartitionInterceptor);
|
||||
myInterceptorService.unregisterInterceptor(myPatientIdPartitionInterceptor);
|
||||
myInterceptorService.unregisterInterceptor(myRequestTenantPartitionInterceptor);
|
||||
}
|
||||
}
|
||||
|
@ -119,8 +117,8 @@ public class JpaPackageCacheTest extends BaseJpaR4Test {
|
|||
myPartitionSettings.setDefaultPartitionId(0);
|
||||
boolean isUnnamed = myPartitionSettings.isUnnamedPartitionMode();
|
||||
myPartitionSettings.setUnnamedPartitionMode(true);
|
||||
PatientIdPartitionInterceptor patientIdPartitionInterceptor = new PatientIdPartitionInterceptor(myFhirContext, mySearchParamExtractor, myPartitionSettings);
|
||||
myInterceptorService.registerInterceptor(patientIdPartitionInterceptor);
|
||||
myPatientIdPartitionInterceptor = new PatientIdPartitionInterceptor(getFhirContext(), mySearchParamExtractor, myPartitionSettings);
|
||||
myInterceptorService.registerInterceptor(myPatientIdPartitionInterceptor);
|
||||
myInterceptorService.registerInterceptor(myRequestTenantPartitionInterceptor);
|
||||
try {
|
||||
try (InputStream stream = ClasspathUtil.loadResourceAsStream("/packages/hl7.fhir.uv.shorthand-0.12.0.tgz")) {
|
||||
|
@ -147,7 +145,7 @@ public class JpaPackageCacheTest extends BaseJpaR4Test {
|
|||
assertEquals("Deleting package hl7.fhir.uv.shorthand#0.12.0", deleteOutcomeMsgs.get(0));
|
||||
} finally {
|
||||
myPartitionSettings.setUnnamedPartitionMode(isUnnamed);
|
||||
myInterceptorService.unregisterInterceptor(patientIdPartitionInterceptor);
|
||||
myInterceptorService.unregisterInterceptor(myPatientIdPartitionInterceptor);
|
||||
myInterceptorService.unregisterInterceptor(myRequestTenantPartitionInterceptor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import ca.uhn.fhir.rest.api.Constants;
|
|||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
|
@ -34,11 +35,8 @@ import org.mockito.Mock;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.matchesPattern;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -194,8 +192,7 @@ public class CrossPartitionReferencesTest extends BaseJpaR5Test {
|
|||
when(myCrossPartitionReferencesDetectedInterceptor.handle(any(),any())).thenAnswer(t->{
|
||||
CrossPartitionReferenceDetails theDetails = t.getArgument(1, CrossPartitionReferenceDetails.class);
|
||||
IIdType targetId = theDetails.getPathAndRef().getRef().getReferenceElement();
|
||||
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forRead(targetId);
|
||||
RequestPartitionId referenceTargetPartition = myPartitionHelperSvc.determineReadPartitionForRequest(theDetails.getRequestDetails(), details);
|
||||
RequestPartitionId referenceTargetPartition = myPartitionHelperSvc.determineReadPartitionForRequestForRead(theDetails.getRequestDetails(), targetId.getResourceType(), targetId);
|
||||
|
||||
IResourceLookup targetResource = myTransactionService
|
||||
.withRequest(theDetails.getRequestDetails())
|
||||
|
|
|
@ -72,7 +72,7 @@ public class MdmSearchExpandingInterceptor {
|
|||
theRequestDetails == null ? new SystemRequestDetails() : theRequestDetails;
|
||||
final RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequestForSearchType(
|
||||
requestDetailsToUse, requestDetailsToUse.getResourceName(), theSearchParameterMap, null);
|
||||
requestDetailsToUse, requestDetailsToUse.getResourceName(), theSearchParameterMap);
|
||||
for (Map.Entry<String, List<List<IQueryParameterType>>> set : theSearchParameterMap.entrySet()) {
|
||||
String paramName = set.getKey();
|
||||
List<List<IQueryParameterType>> andList = set.getValue();
|
||||
|
|
|
@ -21,7 +21,6 @@ package ca.uhn.fhir.mdm.provider;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc;
|
||||
|
@ -143,13 +142,11 @@ public class MdmControllerHelper {
|
|||
public IBaseBundle getMatchesAndPossibleMatchesForResource(
|
||||
IAnyResource theResource, String theResourceType, RequestDetails theRequestDetails) {
|
||||
RequestPartitionId requestPartitionId;
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forSearchType(theResourceType, null, null);
|
||||
if (myMdmSettings.getSearchAllPartitionForMatch()) {
|
||||
requestPartitionId = RequestPartitionId.allPartitions();
|
||||
} else {
|
||||
requestPartitionId =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequest(theRequestDetails, details);
|
||||
requestPartitionId = myRequestPartitionHelperSvc.determineReadPartitionForRequestForSearchType(
|
||||
theRequestDetails, theResourceType);
|
||||
}
|
||||
List<MatchedTarget> matches =
|
||||
myMdmMatchFinderSvc.getMatchedTargets(theResourceType, theResource, requestPartitionId);
|
||||
|
|
|
@ -106,7 +106,7 @@ public class MdmSubmitSvcImpl implements IMdmSubmitSvc {
|
|||
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequestForSearchType(
|
||||
theRequestDetails, theSourceResourceType, spMap, null);
|
||||
theRequestDetails, theSourceResourceType, spMap);
|
||||
return submitAllMatchingResourcesToMdmChannel(spMap, searchBuilder, requestPartitionId);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import ca.uhn.fhir.i18n.Msg;
|
|||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
|
@ -186,12 +185,10 @@ public class BulkDataExportProvider {
|
|||
theOptions.setResourceTypes(resourceTypes);
|
||||
}
|
||||
|
||||
ReadPartitionIdRequestDetails theDetails =
|
||||
ReadPartitionIdRequestDetails.forOperation(null, null, ProviderConstants.OPERATION_EXPORT);
|
||||
|
||||
// Determine and validate partition permissions (if needed).
|
||||
RequestPartitionId partitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, theDetails);
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, ProviderConstants.OPERATION_EXPORT);
|
||||
myRequestPartitionHelperService.validateHasPartitionPermissions(theRequestDetails, "Binary", partitionId);
|
||||
theOptions.setPartitionId(partitionId);
|
||||
|
||||
|
@ -472,7 +469,8 @@ public class BulkDataExportProvider {
|
|||
if (parameters.getPartitionId() != null) {
|
||||
// Determine and validate permissions for partition (if needed)
|
||||
RequestPartitionId partitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, null);
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, ProviderConstants.OPERATION_EXPORT_POLL_STATUS);
|
||||
myRequestPartitionHelperService.validateHasPartitionPermissions(theRequestDetails, "Binary", partitionId);
|
||||
if (!parameters.getPartitionId().equals(partitionId)) {
|
||||
throw new InvalidRequestException(
|
||||
|
|
|
@ -27,7 +27,6 @@ import ca.uhn.fhir.i18n.Msg;
|
|||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.batch.models.Batch2JobStartResponse;
|
||||
|
@ -103,11 +102,10 @@ public class DeleteExpungeJobSubmitterImpl implements IDeleteExpungeJobSubmitter
|
|||
.forEach(deleteExpungeJobParameters::addPartitionedUrl);
|
||||
deleteExpungeJobParameters.setBatchSize(theBatchSize);
|
||||
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forOperation(null, null, ProviderConstants.OPERATION_DELETE_EXPUNGE);
|
||||
// Also set toplevel partition in case there are no urls
|
||||
// Also set top level partition in case there are no urls
|
||||
RequestPartitionId requestPartition =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequest(theRequestDetails, details);
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, ProviderConstants.OPERATION_DELETE_EXPUNGE);
|
||||
deleteExpungeJobParameters.setRequestPartitionId(requestPartition);
|
||||
deleteExpungeJobParameters.setCascade(theCascade);
|
||||
deleteExpungeJobParameters.setCascadeMaxRounds(theCascadeMaxRounds);
|
||||
|
|
|
@ -157,8 +157,9 @@ public class BulkDataImportProvider {
|
|||
}
|
||||
|
||||
RequestPartitionId partitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, null);
|
||||
if (partitionId != null && !partitionId.isAllPartitions()) {
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, JpaConstants.OPERATION_IMPORT);
|
||||
if (!partitionId.isAllPartitions()) {
|
||||
myRequestPartitionHelperService.validateHasPartitionPermissions(theRequestDetails, "Binary", partitionId);
|
||||
jobParameters.setPartitionId(partitionId);
|
||||
}
|
||||
|
@ -234,7 +235,8 @@ public class BulkDataImportProvider {
|
|||
if (parameters != null && parameters.getPartitionId() != null) {
|
||||
// Determine and validate permissions for partition (if needed)
|
||||
RequestPartitionId partitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, null);
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, JpaConstants.OPERATION_IMPORT);
|
||||
myRequestPartitionHelperService.validateHasPartitionPermissions(theRequestDetails, "Binary", partitionId);
|
||||
if (!partitionId.equals(parameters.getPartitionId())) {
|
||||
throw new InvalidRequestException(
|
||||
|
|
|
@ -23,7 +23,6 @@ import ca.uhn.fhir.batch2.api.IJobCoordinator;
|
|||
import ca.uhn.fhir.batch2.jobs.parameters.UrlPartitioner;
|
||||
import ca.uhn.fhir.batch2.model.JobInstanceStartRequest;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.dao.ReindexParameters;
|
||||
import ca.uhn.fhir.jpa.batch.models.Batch2JobStartResponse;
|
||||
|
@ -129,10 +128,9 @@ public class ReindexProvider {
|
|||
.forEach(params::addPartitionedUrl);
|
||||
}
|
||||
|
||||
ReadPartitionIdRequestDetails details =
|
||||
ReadPartitionIdRequestDetails.forOperation(null, null, ProviderConstants.OPERATION_REINDEX);
|
||||
RequestPartitionId requestPartition =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequest(theRequestDetails, details);
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(
|
||||
theRequestDetails, ProviderConstants.OPERATION_REINDEX);
|
||||
params.setRequestPartitionId(requestPartition);
|
||||
|
||||
JobInstanceStartRequest request = new JobInstanceStartRequest();
|
||||
|
|
|
@ -18,6 +18,7 @@ import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
|
|||
import ca.uhn.fhir.test.utilities.HttpClientExtension;
|
||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||
import com.google.common.base.Charsets;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
|
@ -50,7 +51,6 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
|
@ -399,7 +399,7 @@ public class BulkDataImportProviderTest {
|
|||
private class MyRequestPartitionHelperSvc implements IRequestPartitionHelperSvc {
|
||||
@Nonnull
|
||||
@Override
|
||||
public RequestPartitionId determineReadPartitionForRequest(@Nullable RequestDetails theRequest, ReadPartitionIdRequestDetails theDetails) {
|
||||
public RequestPartitionId determineReadPartitionForRequest(@Nullable RequestDetails theRequest, @Nonnull ReadPartitionIdRequestDetails theDetails) {
|
||||
assert theRequest != null;
|
||||
if (myPartitionName.equals(theRequest.getTenantId())) {
|
||||
return myRequestPartitionId;
|
||||
|
@ -409,7 +409,7 @@ public class BulkDataImportProviderTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void validateHasPartitionPermissions(RequestDetails theRequest, String theResourceType, RequestPartitionId theRequestPartitionId) {
|
||||
public void validateHasPartitionPermissions(@Nonnull RequestDetails theRequest, String theResourceType, RequestPartitionId theRequestPartitionId) {
|
||||
if (!myPartitionName.equals(theRequest.getTenantId()) && theRequest.getTenantId() != null) {
|
||||
throw new ForbiddenOperationException("User does not have access to resources on the requested partition");
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ public class ReindexProviderTest {
|
|||
|
||||
when(myJobCoordinator.startInstance(isNotNull(), any()))
|
||||
.thenReturn(createJobStartResponse());
|
||||
when(myRequestPartitionHelperSvc.determineReadPartitionForRequest(any(), any())).thenReturn(RequestPartitionId.allPartitions());
|
||||
when(myRequestPartitionHelperSvc.determineReadPartitionForRequestForServerOperation(any(), any())).thenReturn(RequestPartitionId.allPartitions());
|
||||
}
|
||||
|
||||
private Batch2JobStartResponse createJobStartResponse() {
|
||||
|
|
|
@ -38,10 +38,7 @@ public class UrlPartitioner {
|
|||
ResourceSearch resourceSearch = myMatchUrlService.getResourceSearch(theUrl);
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperSvc.determineReadPartitionForRequestForSearchType(
|
||||
theRequestDetails,
|
||||
resourceSearch.getResourceName(),
|
||||
resourceSearch.getSearchParameterMap(),
|
||||
null);
|
||||
theRequestDetails, resourceSearch.getResourceName(), resourceSearch.getSearchParameterMap());
|
||||
PartitionedUrl retval = new PartitionedUrl();
|
||||
retval.setUrl(theUrl);
|
||||
retval.setRequestPartitionId(requestPartitionId);
|
||||
|
|
|
@ -320,8 +320,8 @@ public class DaoRegistryGraphQLStorageServices implements IGraphQLStorageService
|
|||
CacheControlDirective cacheControlDirective = new CacheControlDirective();
|
||||
cacheControlDirective.parse(requestDetails.getHeaders(Constants.HEADER_CACHE_CONTROL));
|
||||
|
||||
RequestPartitionId requestPartitionId = myPartitionHelperSvc.determineReadPartitionForRequestForSearchType(
|
||||
requestDetails, theType, params, null);
|
||||
RequestPartitionId requestPartitionId =
|
||||
myPartitionHelperSvc.determineReadPartitionForRequestForSearchType(requestDetails, theType, params);
|
||||
response = mySearchCoordinatorSvc.registerSearch(
|
||||
getDao(theType), params, theType, cacheControlDirective, requestDetails, requestPartitionId);
|
||||
|
||||
|
|
|
@ -36,17 +36,18 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
|||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
|
@ -67,13 +68,6 @@ public class PatientIdPartitionInterceptor {
|
|||
@Autowired
|
||||
private PartitionSettings myPartitionSettings;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public PatientIdPartitionInterceptor() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -81,7 +75,6 @@ public class PatientIdPartitionInterceptor {
|
|||
FhirContext theFhirContext,
|
||||
ISearchParamExtractor theSearchParamExtractor,
|
||||
PartitionSettings thePartitionSettings) {
|
||||
this();
|
||||
myFhirContext = theFhirContext;
|
||||
mySearchParamExtractor = theSearchParamExtractor;
|
||||
myPartitionSettings = thePartitionSettings;
|
||||
|
@ -116,8 +109,7 @@ public class PatientIdPartitionInterceptor {
|
|||
|
||||
@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_READ)
|
||||
public RequestPartitionId identifyForRead(
|
||||
ReadPartitionIdRequestDetails theReadDetails, RequestDetails theRequestDetails) {
|
||||
|
||||
@Nonnull ReadPartitionIdRequestDetails theReadDetails, RequestDetails theRequestDetails) {
|
||||
List<RuntimeSearchParam> compartmentSps = Collections.emptyList();
|
||||
if (!isEmpty(theReadDetails.getResourceType())) {
|
||||
RuntimeResourceDefinition resourceDef =
|
||||
|
@ -140,10 +132,9 @@ public class PatientIdPartitionInterceptor {
|
|||
break;
|
||||
case SEARCH_TYPE:
|
||||
SearchParameterMap params = theReadDetails.getSearchParams();
|
||||
|
||||
assert params != null;
|
||||
if ("Patient".equals(theReadDetails.getResourceType())) {
|
||||
List<String> idParts = getResourceIdList(params, "_id", "Patient", false);
|
||||
|
||||
if (idParts.size() == 1) {
|
||||
return provideCompartmentMemberInstanceResponse(theRequestDetails, idParts.get(0));
|
||||
} else {
|
||||
|
@ -160,16 +151,12 @@ public class PatientIdPartitionInterceptor {
|
|||
|
||||
break;
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
String extendedOp = theReadDetails.getExtendedOperationName();
|
||||
if (ProviderConstants.OPERATION_EXPORT.equals(extendedOp)) {
|
||||
return provideNonPatientSpecificQueryResponse(theReadDetails);
|
||||
}
|
||||
break;
|
||||
return provideNonPatientSpecificQueryResponse(theReadDetails);
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
|
||||
if (isEmpty(theReadDetails.getResourceType())) {
|
||||
if (isBlank(theReadDetails.getResourceType())) {
|
||||
return provideNonCompartmentMemberTypeResponse(null);
|
||||
}
|
||||
|
||||
|
@ -184,31 +171,29 @@ public class PatientIdPartitionInterceptor {
|
|||
|
||||
private List<String> getResourceIdList(
|
||||
SearchParameterMap theParams, String theParamName, String theResourceType, boolean theExpectOnlyOneBool) {
|
||||
List<String> idParts = new ArrayList<>();
|
||||
List<List<IQueryParameterType>> idParamAndList = theParams.get(theParamName);
|
||||
if (idParamAndList != null) {
|
||||
for (List<IQueryParameterType> idParamOrList : idParamAndList) {
|
||||
for (IQueryParameterType idParam : idParamOrList) {
|
||||
if (isNotBlank(idParam.getQueryParameterQualifier())) {
|
||||
throw new MethodNotAllowedException(
|
||||
Msg.code(1322) + "The parameter " + theParamName + idParam.getQueryParameterQualifier()
|
||||
+ " is not supported in patient compartment mode");
|
||||
}
|
||||
if (idParam instanceof ReferenceParam) {
|
||||
String chain = ((ReferenceParam) idParam).getChain();
|
||||
if (chain != null) {
|
||||
throw new MethodNotAllowedException(Msg.code(1323) + "The parameter " + theParamName + "."
|
||||
+ chain + " is not supported in patient compartment mode");
|
||||
}
|
||||
}
|
||||
if (idParamAndList == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
IdType id = new IdType(idParam.getValueAsQueryToken(myFhirContext));
|
||||
if (!id.hasResourceType() || id.getResourceType().equals(theResourceType)) {
|
||||
idParts.add(id.getIdPart());
|
||||
}
|
||||
List<String> idParts = new ArrayList<>();
|
||||
idParamAndList.stream().flatMap(Collection::stream).forEach(idParam -> {
|
||||
if (isNotBlank(idParam.getQueryParameterQualifier())) {
|
||||
throw new MethodNotAllowedException(Msg.code(1322) + "The parameter " + theParamName
|
||||
+ idParam.getQueryParameterQualifier() + " is not supported in patient compartment mode");
|
||||
}
|
||||
if (idParam instanceof ReferenceParam) {
|
||||
String chain = ((ReferenceParam) idParam).getChain();
|
||||
if (chain != null) {
|
||||
throw new MethodNotAllowedException(Msg.code(1323) + "The parameter " + theParamName + "." + chain
|
||||
+ " is not supported in patient compartment mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
IdType id = new IdType(idParam.getValueAsQueryToken(myFhirContext));
|
||||
if (!id.hasResourceType() || id.getResourceType().equals(theResourceType)) {
|
||||
idParts.add(id.getIdPart());
|
||||
}
|
||||
});
|
||||
|
||||
if (theExpectOnlyOneBool && idParts.size() > 1) {
|
||||
throw new MethodNotAllowedException(Msg.code(1324) + "Multiple values for parameter " + theParamName
|
||||
|
|
|
@ -94,10 +94,10 @@ public abstract class BaseRequestPartitionHelperSvc implements IRequestPartition
|
|||
@Nonnull
|
||||
@Override
|
||||
public RequestPartitionId determineReadPartitionForRequest(
|
||||
@Nullable RequestDetails theRequest, ReadPartitionIdRequestDetails theDetails) {
|
||||
@Nullable RequestDetails theRequest, @Nonnull ReadPartitionIdRequestDetails theDetails) {
|
||||
RequestPartitionId requestPartitionId;
|
||||
|
||||
String resourceType = theDetails != null ? theDetails.getResourceType() : null;
|
||||
String resourceType = theDetails.getResourceType();
|
||||
boolean nonPartitionableResource = !isResourcePartitionable(resourceType);
|
||||
if (myPartitionSettings.isPartitioningEnabled()) {
|
||||
|
||||
|
@ -313,7 +313,7 @@ public abstract class BaseRequestPartitionHelperSvc implements IRequestPartition
|
|||
|
||||
@Override
|
||||
public void validateHasPartitionPermissions(
|
||||
RequestDetails theRequest, String theResourceType, RequestPartitionId theRequestPartitionId) {
|
||||
@Nonnull RequestDetails theRequest, String theResourceType, RequestPartitionId theRequestPartitionId) {
|
||||
if (myInterceptorBroadcaster.hasHooks(Pointcut.STORAGE_PARTITION_SELECTED)) {
|
||||
RuntimeResourceDefinition runtimeResourceDefinition = null;
|
||||
if (theResourceType != null) {
|
||||
|
|
Loading…
Reference in New Issue