Complete change, changelog, test (#5035)

* Complete change, changelog, test

* whitespace

* Update hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/StorageSettings.java

Co-authored-by: James Agnew <jamesagnew@gmail.com>

---------

Co-authored-by: James Agnew <jamesagnew@gmail.com>
This commit is contained in:
Tadgh 2023-06-28 10:14:22 -04:00 committed by GitHub
parent 73d6997d21
commit 9fb718820d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 0 deletions

View File

@ -0,0 +1,5 @@
---
type: add
title: "A new configuration option, `JpaStorageSettings#setOnlyAllowInMemorySubscriptions(boolean)` can now prevent the creation of Subscriptions
that would need to be matched in the database. If enabled, only Subscriptions which can be evaluated IN-MEMORY are permitted to be created."

View File

@ -118,11 +118,37 @@ public class StorageSettings {
private boolean myIndexIdentifierOfType = false; private boolean myIndexIdentifierOfType = false;
private IndexEnabledEnum myIndexMissingFieldsEnabled = IndexEnabledEnum.DISABLED; private IndexEnabledEnum myIndexMissingFieldsEnabled = IndexEnabledEnum.DISABLED;
/**
* @since 6.8.0
* Prevents any non IN-MEMORY Search params from being created by users.
*/
private boolean myAllowOnlyInMemorySubscriptions = false;
/** /**
* Since 6.4.0 * Since 6.4.0
*/ */
private boolean myQualifySubscriptionMatchingChannelName = true; private boolean myQualifySubscriptionMatchingChannelName = true;
/**
* If set to true, the server will prevent the creation of Subscriptions which cannot be evaluated IN-MEMORY. This can improve
* overall server performance.
*
* @since 6.8.0
*/
public void setOnlyAllowInMemorySubscriptions(boolean theAllowOnlyInMemorySearchParams) {
myAllowOnlyInMemorySubscriptions = theAllowOnlyInMemorySearchParams;
}
/**
* If set to true, the server will prevent the creation of Subscriptions which cannot be evaluated IN-MEMORY. This can improve
* overall server performance.
*
* @since 6.8.0
* @return Returns the value of {@link #setOnlyAllowInMemorySubscriptions(boolean)}
*/
public boolean isOnlyAllowInMemorySubscriptions() {
return myAllowOnlyInMemorySubscriptions;
}
/** /**
* Constructor * Constructor
*/ */

View File

@ -151,6 +151,9 @@ public class SubscriptionValidatingInterceptor {
try { try {
SubscriptionMatchingStrategy strategy = mySubscriptionStrategyEvaluator.determineStrategy(subscription); SubscriptionMatchingStrategy strategy = mySubscriptionStrategyEvaluator.determineStrategy(subscription);
if (!(SubscriptionMatchingStrategy.IN_MEMORY == strategy) && myStorageSettings.isOnlyAllowInMemorySubscriptions()) {
throw new InvalidRequestException(Msg.code(2367)+ "This server is configured to only allow in-memory subscriptions. This subscription's criteria cannot be evaluated in-memory.");
}
mySubscriptionCanonicalizer.setMatchingStrategyTag(theSubscription, strategy); mySubscriptionCanonicalizer.setMatchingStrategyTag(theSubscription, strategy);
} catch (InvalidRequestException | DataFormatException e) { } catch (InvalidRequestException | DataFormatException e) {
throw new UnprocessableEntityException(Msg.code(9) + "Invalid subscription criteria submitted: " + subscription.getCriteriaString() + " " + e.getMessage()); throw new UnprocessableEntityException(Msg.code(9) + "Invalid subscription criteria submitted: " + subscription.getCriteriaString() + " " + e.getMessage());

View File

@ -63,6 +63,7 @@ import static ca.uhn.fhir.util.HapiExtensions.EX_SEND_DELETE_MESSAGES;
import static org.awaitility.Awaitility.await; import static org.awaitility.Awaitility.await;
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.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.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals;
@ -123,6 +124,8 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
myInterceptorRegistry.registerInterceptor(ourSubscriptionDebugLogInterceptor); myInterceptorRegistry.registerInterceptor(ourSubscriptionDebugLogInterceptor);
ourLog.info("After re-registering interceptors"); ourLog.info("After re-registering interceptors");
DaoTestUtils.logAllInterceptors(myInterceptorRegistry); DaoTestUtils.logAllInterceptors(myInterceptorRegistry);
myStorageSettings.setOnlyAllowInMemorySubscriptions(new JpaStorageSettings().isOnlyAllowInMemorySubscriptions());
} }
@BeforeEach @BeforeEach
@ -212,6 +215,19 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
assertEquals(HapiExtensions.EXT_SUBSCRIPTION_MATCHING_STRATEGY, tag.get(0).getSystem()); assertEquals(HapiExtensions.EXT_SUBSCRIPTION_MATCHING_STRATEGY, tag.get(0).getSystem());
assertEquals(SubscriptionMatchingStrategy.IN_MEMORY.toString(), tag.get(0).getCode()); assertEquals(SubscriptionMatchingStrategy.IN_MEMORY.toString(), tag.get(0).getCode());
} }
@Test
public void testForcedInMemoryPreventsDatabaseSubscriptions() throws InterruptedException {
myStorageSettings.setOnlyAllowInMemorySubscriptions(true);
String databaseCriteria = "Observation?code=17861-6&context.type=IHD";
try {
createSubscription(databaseCriteria, null, ourNotificationListenerServer);
} catch (UnprocessableEntityException e) {
assertThat(e.getMessage(), is(containsString("HAPI-2367: This server is configured to only allow in-memory subscriptions.")));
}
myStorageSettings.setOnlyAllowInMemorySubscriptions(false);
}
@ParameterizedTest @ParameterizedTest
@ValueSource(strings = {"[*]", "[Observation]", "Observation?"}) @ValueSource(strings = {"[*]", "[Observation]", "Observation?"})
public void RestHookSubscriptionWithPayloadSendsDeleteRequest(String theCriteria) throws Exception { public void RestHookSubscriptionWithPayloadSendsDeleteRequest(String theCriteria) throws Exception {