Skip to content

Commit

Permalink
fix(ecl): report HTTP 400 on Too Costly ECL expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
cmark committed Mar 29, 2023
1 parent 2024ed4 commit 77e20f0
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2023 B2i Healthcare Pte Ltd, http://b2i.sg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.b2international.commons.exceptions;

/**
* @since 8.10
*/
public final class TooCostlyException extends BadRequestException {

private static final long serialVersionUID = 1L;

public TooCostlyException(String developerMessage, Object...args) {
super("Request is too costly to execute. Alter your input parameters so that the system is able to process your request.");
withDeveloperMessage(developerMessage, args);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 B2i Healthcare Pte Ltd, http://b2i.sg
* Copyright 2022-2023 B2i Healthcare Pte Ltd, http://b2i.sg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -35,6 +35,7 @@

import com.b2international.commons.CompareUtils;
import com.b2international.commons.exceptions.BadRequestException;
import com.b2international.commons.exceptions.TooCostlyException;
import com.b2international.index.query.*;
import com.b2international.index.revision.RevisionSearcher;
import com.b2international.snomed.ecl.Ecl;
Expand Down Expand Up @@ -100,7 +101,11 @@ public void setIgnoredSyntaxErrorCodes(Set<String> ignoredSyntaxErrorCodes) {
}

protected final Promise<Expression> evaluate(C context, EObject expression) {
return dispatcher.invoke(context, expression);
try {
return dispatcher.invoke(context, expression);
} catch (StackOverflowError e) {
throw new TooCostlyException("ECL expression contains too many clauses and the server is unable to process it.");
}
}

protected Promise<Expression> eval(C context, EObject eObject) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.junit.runners.Parameterized.Parameters;

import com.b2international.commons.exceptions.BadRequestException;
import com.b2international.commons.exceptions.TooCostlyException;
import com.b2international.index.query.Expression;
import com.b2international.index.query.Expressions;
import com.b2international.index.query.MatchNone;
Expand Down Expand Up @@ -452,6 +453,19 @@ public void largeIdSetWithOrOperators() throws Exception {
.collect(Collectors.joining(" OR ")));
}

// XXX until we figure out how to process these effectively
@Test(expected = TooCostlyException.class)
public void largeEclOrOperatorOnly() throws Exception {
eval(IntStream.range(0, 10_000)
.mapToObj(i -> {
if (i % 10 == 0) {
return "<" + RandomSnomedIdentiferGenerator.generateConceptId();
} else {
return RandomSnomedIdentiferGenerator.generateConceptId();
}
})
.collect(Collectors.joining(" OR ")));
}

@Test(expected = BadRequestException.class)
public void binaryOperatorAmbiguityOrAnd() throws Exception {
Expand Down

0 comments on commit 77e20f0

Please sign in to comment.