Ensure "Device" is not considered as a resource type for R5 (#5909)

* Preliminary fix.

* Refine fix.  Refine existing tests.  Rename existing test to R4.  Disable tests that don't work due to newly discovered bug with R5 POST poll.  Reverse logging changes and TODOs.

* Reverse more logging changes.

* Check for whitelist of FHIR versions that support device in patient compartment.

* Refine solution.  Add a new test.

* Add changelog.

* Code review fix.
This commit is contained in:
Luke deGruchy 2024-05-08 15:45:56 -04:00 committed by GitHub
parent ae67e7b55e
commit c87b5b1d2a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 1398 additions and 6 deletions

View File

@ -0,0 +1,5 @@
---
type: fix
issue: 5913
title: "Bulk export was failing with a HAPI-2222 error with the persistence module configured for R5.
This has been fixed."

View File

@ -45,7 +45,6 @@ import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.InstantType; import org.hl7.fhir.r4.model.InstantType;
import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.StringType;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -97,10 +96,10 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class BulkDataExportProviderTest { public class BulkDataExportProviderR4Test {
private static final String A_JOB_ID = "0000000-AAAAAA"; private static final String A_JOB_ID = "0000000-AAAAAA";
private static final Logger ourLog = LoggerFactory.getLogger(BulkDataExportProviderTest.class); private static final Logger ourLog = LoggerFactory.getLogger(BulkDataExportProviderR4Test.class);
private static final String GROUP_ID = "Group/G2401"; private static final String GROUP_ID = "Group/G2401";
private static final String G_JOB_ID = "0000000-GGGGGG"; private static final String G_JOB_ID = "0000000-GGGGGG";
@Spy @Spy
@ -1298,7 +1297,7 @@ public class BulkDataExportProviderTest {
private class MyRequestPartitionHelperSvc extends RequestPartitionHelperSvc { private class MyRequestPartitionHelperSvc extends RequestPartitionHelperSvc {
@Override @Override
public @NotNull RequestPartitionId determineReadPartitionForRequest(@Nonnull RequestDetails theRequest, @Nonnull ReadPartitionIdRequestDetails theDetails) { public @Nonnull RequestPartitionId determineReadPartitionForRequest(@Nonnull RequestDetails theRequest, @Nonnull ReadPartitionIdRequestDetails theDetails) {
assert theRequest != null; assert theRequest != null;
if (myPartitionName.equals(theRequest.getTenantId())) { if (myPartitionName.equals(theRequest.getTenantId())) {
return myRequestPartitionId; return myRequestPartitionId;

View File

@ -25,6 +25,7 @@ import ca.uhn.fhir.batch2.model.JobInstance;
import ca.uhn.fhir.batch2.model.JobInstanceStartRequest; import ca.uhn.fhir.batch2.model.JobInstanceStartRequest;
import ca.uhn.fhir.batch2.model.StatusEnum; import ca.uhn.fhir.batch2.model.StatusEnum;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
@ -99,6 +100,13 @@ public class BulkDataExportProvider {
public static final String UNSUPPORTED_BINARY_TYPE = "Binary"; public static final String UNSUPPORTED_BINARY_TYPE = "Binary";
private static final Logger ourLog = getLogger(BulkDataExportProvider.class); private static final Logger ourLog = getLogger(BulkDataExportProvider.class);
private static final Set<FhirVersionEnum> PATIENT_COMPARTMENT_FHIR_VERSIONS_SUPPORT_DEVICE = Set.of(
FhirVersionEnum.DSTU2,
FhirVersionEnum.DSTU2_1,
FhirVersionEnum.DSTU2_HL7ORG,
FhirVersionEnum.DSTU3,
FhirVersionEnum.R4,
FhirVersionEnum.R4B);
@Autowired @Autowired
private IInterceptorBroadcaster myInterceptorBroadcaster; private IInterceptorBroadcaster myInterceptorBroadcaster;
@ -344,10 +352,18 @@ public class BulkDataExportProvider {
} }
private Set<String> getPatientCompartmentResources() { private Set<String> getPatientCompartmentResources() {
return getPatientCompartmentResources(myFhirContext);
}
@VisibleForTesting
Set<String> getPatientCompartmentResources(FhirContext theFhirContext) {
if (myCompartmentResources == null) { if (myCompartmentResources == null) {
myCompartmentResources = myCompartmentResources =
new HashSet<>(SearchParameterUtil.getAllResourceTypesThatAreInPatientCompartment(myFhirContext)); new HashSet<>(SearchParameterUtil.getAllResourceTypesThatAreInPatientCompartment(theFhirContext));
myCompartmentResources.add("Device"); if (isDeviceResourceSupportedForPatientCompartmentForFhirVersion(
theFhirContext.getVersion().getVersion())) {
myCompartmentResources.add("Device");
}
} }
return myCompartmentResources; return myCompartmentResources;
} }
@ -803,4 +819,9 @@ public class BulkDataExportProvider {
throw new InvalidRequestException(Msg.code(513) + "Must request async processing for " + theOperationName); throw new InvalidRequestException(Msg.code(513) + "Must request async processing for " + theOperationName);
} }
} }
private static boolean isDeviceResourceSupportedForPatientCompartmentForFhirVersion(
FhirVersionEnum theFhirVersionEnum) {
return PATIENT_COMPARTMENT_FHIR_VERSIONS_SUPPORT_DEVICE.contains(theFhirVersionEnum);
}
} }

View File

@ -0,0 +1,47 @@
package ca.uhn.fhir.batch2.jobs.export;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Set;
import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.not;
@ExtendWith(MockitoExtension.class)
class BulkDataExportProviderTest {
private static final Set<FhirVersionEnum> PATIENT_COMPARTMENT_FHIR_VERSIONS_SUPPORT_DEVICE = Set.of(FhirVersionEnum.DSTU2, FhirVersionEnum.DSTU2_1, FhirVersionEnum.DSTU2_HL7ORG, FhirVersionEnum.DSTU3, FhirVersionEnum.R4, FhirVersionEnum.R4B);
private static Stream<Arguments> fhirContexts() {
return Stream.of(
Arguments.arguments(FhirContext.forDstu2()),
Arguments.arguments(FhirContext.forDstu2Cached()),
Arguments.arguments(FhirContext.forDstu2Hl7Org()),
Arguments.arguments(FhirContext.forDstu2Hl7OrgCached()),
Arguments.arguments(FhirContext.forDstu3()),
Arguments.arguments(FhirContext.forDstu3Cached()),
Arguments.arguments(FhirContext.forR4()),
Arguments.arguments(FhirContext.forR4Cached()),
Arguments.arguments(FhirContext.forR4B()),
Arguments.arguments(FhirContext.forR4BCached()),
Arguments.arguments(FhirContext.forR5()),
Arguments.arguments(FhirContext.forR5Cached())
);
}
@ParameterizedTest
@MethodSource("fhirContexts")
void checkDeviceIsSupportedInPatientCompartment(FhirContext theFhirContext) {
assertThat(new BulkDataExportProvider().getPatientCompartmentResources(theFhirContext),
PATIENT_COMPARTMENT_FHIR_VERSIONS_SUPPORT_DEVICE.contains(theFhirContext.getVersion().getVersion())
? hasItem("Device")
: not(hasItem("Device")));
}
}