3524 export poll status returning the wrong partition in the url (#3526)

* test added and bulk data export provider fixed

* add test and change jira number

* change test

* modify tests
This commit is contained in:
samuelwlee2 2022-04-23 10:47:04 -06:00 committed by GitHub
parent 5ccb4effb0
commit 4c9667c92a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 2 deletions

View File

@ -0,0 +1,4 @@
type: fix
issue: 3524
jira: SMILE-3672
title: "Previously if partitioning was enabled, the URL returned from `$export-poll-status` provided a location in the wrong partition. This has been fixed and all Bulk Exports will be stored in the `DEFAULT` partition."

View File

@ -1,15 +1,27 @@
package ca.uhn.fhir.jpa.provider.r4; package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.jpa.batch.config.BatchConstants;
import ca.uhn.fhir.jpa.bulk.export.api.IBulkDataExportJobSchedulingHelper;
import ca.uhn.fhir.jpa.bulk.export.api.IBulkDataExportSvc;
import ca.uhn.fhir.jpa.bulk.export.model.BulkExportJobStatusEnum;
import ca.uhn.fhir.jpa.bulk.export.model.BulkExportResponseJson;
import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider;
import ca.uhn.fhir.jpa.entity.PartitionEntity; import ca.uhn.fhir.jpa.entity.PartitionEntity;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.partition.SystemRequestDetails; import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.bulk.BulkDataExportOptions;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.test.utilities.ITestDataBuilder; import ca.uhn.fhir.test.utilities.ITestDataBuilder;
import ca.uhn.fhir.util.JsonUtil;
import com.google.common.collect.Sets;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle;
@ -18,17 +30,23 @@ import org.hl7.fhir.r4.model.Condition;
import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Patient;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date; import java.util.Date;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
@ -36,6 +54,11 @@ import static org.junit.jupiter.api.Assertions.fail;
@SuppressWarnings("Duplicates") @SuppressWarnings("Duplicates")
public class MultitenantServerR4Test extends BaseMultitenantResourceProviderR4Test implements ITestDataBuilder { public class MultitenantServerR4Test extends BaseMultitenantResourceProviderR4Test implements ITestDataBuilder {
@Autowired
private IBulkDataExportSvc myBulkDataExportSvc;
@Autowired
private IBulkDataExportJobSchedulingHelper myBulkDataExportJobSchedulingHelper;
@Override @Override
@AfterEach @AfterEach
public void after() throws Exception { public void after() throws Exception {
@ -370,6 +393,56 @@ public class MultitenantServerR4Test extends BaseMultitenantResourceProviderR4Te
assertThat(response.getEntry(), hasSize(2)); assertThat(response.getEntry(), hasSize(2));
} }
@Test
public void testBulkExportForDifferentPartitions() throws IOException {
setBulkDataExportProvider();
testBulkExport(TENANT_A);
testBulkExport(TENANT_B);
testBulkExport(JpaConstants.DEFAULT_PARTITION_NAME);
}
private void testBulkExport(String createInPartition) throws IOException {
// Create a patient
IBaseResource patientA = buildPatient(withActiveTrue());
SystemRequestDetails requestDetails = new SystemRequestDetails();
requestDetails.setTenantId(createInPartition);
myPatientDao.create((Patient) patientA, requestDetails);
// Create a bulk job
BulkDataExportOptions options = new BulkDataExportOptions();
options.setResourceTypes(Sets.newHashSet("Patient"));
options.setExportStyle(BulkDataExportOptions.ExportStyle.SYSTEM);
IBulkDataExportSvc.JobInfo jobDetails = myBulkDataExportSvc.submitJob(options, false, requestDetails);
assertNotNull(jobDetails.getJobId());
// Run a scheduled pass to build the export and wait for completion
myBulkDataExportJobSchedulingHelper.startSubmittedJobs();
myBatchJobHelper.awaitAllBulkJobCompletions(
BatchConstants.BULK_EXPORT_JOB_NAME
);
//perform export-poll-status
HttpGet get = new HttpGet(buildExportUrl(createInPartition, jobDetails.getJobId()));
try (CloseableHttpResponse response = ourHttpClient.execute(get)) {
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
BulkExportResponseJson responseJson = JsonUtil.deserialize(responseString, BulkExportResponseJson.class);
assertThat(responseJson.getOutput().get(0).getUrl(), containsString(JpaConstants.DEFAULT_PARTITION_NAME + "/Binary/"));
}
}
private void setBulkDataExportProvider() {
BulkDataExportProvider provider = new BulkDataExportProvider();
provider.setBulkDataExportSvcForUnitTests(myBulkDataExportSvc);
provider.setFhirContextForUnitTest(myFhirContext);
ourRestServer.registerProvider(provider);
}
private String buildExportUrl(String createInPartition, String jobId) {
return myClient.getServerBase() + "/" + createInPartition + "/" + JpaConstants.OPERATION_EXPORT_POLL_STATUS + "?"
+ JpaConstants.PARAM_EXPORT_POLL_STATUS_JOB_ID + "=" + jobId;
}
private void createConditionWithAllowedUnqualified(IIdType idA) { private void createConditionWithAllowedUnqualified(IIdType idA) {
myPartitionSettings.setAllowReferencesAcrossPartitions(PartitionSettings.CrossPartitionReferenceMode.ALLOWED_UNQUALIFIED); myPartitionSettings.setAllowReferencesAcrossPartitions(PartitionSettings.CrossPartitionReferenceMode.ALLOWED_UNQUALIFIED);
IIdType idB = createResource("Condition", withTenant(TENANT_A), withObservationCode("http://cs", "A")); IIdType idB = createResource("Condition", withTenant(TENANT_A), withObservationCode("http://cs", "A"));

View File

@ -106,6 +106,15 @@ public class BulkDataExportProvider {
return StringUtils.removeEnd(theRequestDetails.getServerBaseForRequest(), "/"); return StringUtils.removeEnd(theRequestDetails.getServerBaseForRequest(), "/");
} }
private String getDefaultPartitionServerBase(ServletRequestDetails theRequestDetails) {
if (theRequestDetails.getTenantId() == null || theRequestDetails.getTenantId().equals(JpaConstants.DEFAULT_PARTITION_NAME)) {
return getServerBase(theRequestDetails);
}
else {
return StringUtils.removeEnd(theRequestDetails.getServerBaseForRequest().replace(theRequestDetails.getTenantId(), JpaConstants.DEFAULT_PARTITION_NAME), "/");
}
}
/** /**
* Group/Id/$export * Group/Id/$export
*/ */
@ -197,7 +206,7 @@ public class BulkDataExportProvider {
bulkResponseDocument.setTransactionTime(status.getStatusTime()); bulkResponseDocument.setTransactionTime(status.getStatusTime());
bulkResponseDocument.setRequest(status.getRequest()); bulkResponseDocument.setRequest(status.getRequest());
for (IBulkDataExportSvc.FileEntry nextFile : status.getFiles()) { for (IBulkDataExportSvc.FileEntry nextFile : status.getFiles()) {
String serverBase = getServerBase(theRequestDetails); String serverBase = getDefaultPartitionServerBase(theRequestDetails);
String nextUrl = serverBase + "/" + nextFile.getResourceId().toUnqualifiedVersionless().getValue(); String nextUrl = serverBase + "/" + nextFile.getResourceId().toUnqualifiedVersionless().getValue();
bulkResponseDocument bulkResponseDocument
.addOutput() .addOutput()