Skip to content

Commit 356d1a2

Browse files
authored
Scripting: Groundwork for caching script results (#49895)
In order to cache script results in the query shard cache, we need to check if scripts are deterministic. This change adds a default method to the script factories, `isResultDeterministic() -> false` which is used by the `QueryShardContext`. Script results were never cached and that does not change here. Future changes will implement this method based on whether the results of the scripts are deterministic or not and therefore cacheable. Refs: #49466
1 parent 2e84e83 commit 356d1a2

File tree

59 files changed

+236
-114
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+236
-114
lines changed

modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/AnalysisPredicateScript.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
2828
import org.apache.lucene.util.AttributeSource;
2929
import org.elasticsearch.script.ScriptContext;
30+
import org.elasticsearch.script.ScriptFactory;
3031

3132
/**
3233
* A predicate based on the current token in a TokenStream
@@ -107,7 +108,7 @@ public boolean isKeyword() {
107108
*/
108109
public abstract boolean execute(Token token);
109110

110-
public interface Factory {
111+
public interface Factory extends ScriptFactory {
111112
AnalysisPredicateScript newInstance();
112113
}
113114

modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/PredicateTokenScriptFilterTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.elasticsearch.indices.analysis.AnalysisModule;
3131
import org.elasticsearch.script.Script;
3232
import org.elasticsearch.script.ScriptContext;
33+
import org.elasticsearch.script.ScriptFactory;
3334
import org.elasticsearch.script.ScriptService;
3435
import org.elasticsearch.test.ESTokenStreamTestCase;
3536
import org.elasticsearch.test.IndexSettingsModule;
@@ -63,7 +64,7 @@ public boolean execute(Token token) {
6364
@SuppressWarnings("unchecked")
6465
ScriptService scriptService = new ScriptService(indexSettings, Collections.emptyMap(), Collections.emptyMap()){
6566
@Override
66-
public <FactoryType> FactoryType compile(Script script, ScriptContext<FactoryType> context) {
67+
public <FactoryType extends ScriptFactory> FactoryType compile(Script script, ScriptContext<FactoryType> context) {
6768
assertEquals(context, AnalysisPredicateScript.CONTEXT);
6869
assertEquals(new Script("my_script"), script);
6970
return (FactoryType) factory;

modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/ScriptedConditionTokenFilterTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.elasticsearch.indices.analysis.AnalysisModule;
3131
import org.elasticsearch.script.Script;
3232
import org.elasticsearch.script.ScriptContext;
33+
import org.elasticsearch.script.ScriptFactory;
3334
import org.elasticsearch.script.ScriptService;
3435
import org.elasticsearch.test.ESTokenStreamTestCase;
3536
import org.elasticsearch.test.IndexSettingsModule;
@@ -63,7 +64,7 @@ public boolean execute(Token token) {
6364
@SuppressWarnings("unchecked")
6465
ScriptService scriptService = new ScriptService(indexSettings, Collections.emptyMap(), Collections.emptyMap()){
6566
@Override
66-
public <FactoryType> FactoryType compile(Script script, ScriptContext<FactoryType> context) {
67+
public <FactoryType extends ScriptFactory> FactoryType compile(Script script, ScriptContext<FactoryType> context) {
6768
assertEquals(context, AnalysisPredicateScript.CONTEXT);
6869
assertEquals(new Script("token.getPosition() > 1"), script);
6970
return (FactoryType) factory;

modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.elasticsearch.script.ScriptContext;
4545
import org.elasticsearch.script.ScriptEngine;
4646
import org.elasticsearch.script.ScriptException;
47+
import org.elasticsearch.script.ScriptFactory;
4748
import org.elasticsearch.script.TermsSetQueryScript;
4849
import org.elasticsearch.search.lookup.SearchLookup;
4950

@@ -108,7 +109,12 @@ public String getType() {
108109
}
109110

110111
@Override
111-
public <T> T compile(String scriptName, String scriptSource, ScriptContext<T> context, Map<String, String> params) {
112+
public <T extends ScriptFactory> T compile(
113+
String scriptName,
114+
String scriptSource,
115+
ScriptContext<T> context,
116+
Map<String, String> params
117+
) {
112118
// classloader created here
113119
final SecurityManager sm = System.getSecurityManager();
114120
SpecialPermission.check();

modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngine.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.elasticsearch.script.ScriptContext;
3333
import org.elasticsearch.script.ScriptEngine;
3434
import org.elasticsearch.script.ScriptException;
35+
import org.elasticsearch.script.ScriptFactory;
3536
import org.elasticsearch.script.TemplateScript;
3637

3738
import java.io.Reader;
@@ -64,7 +65,12 @@ public final class MustacheScriptEngine implements ScriptEngine {
6465
* @return a compiled template object for later execution.
6566
* */
6667
@Override
67-
public <T> T compile(String templateName, String templateSource, ScriptContext<T> context, Map<String, String> options) {
68+
public <T extends ScriptFactory> T compile(
69+
String templateName,
70+
String templateSource,
71+
ScriptContext<T> context,
72+
Map<String, String> options
73+
) {
6874
if (context.instanceClazz.equals(TemplateScript.class) == false) {
6975
throw new IllegalArgumentException("mustache engine does not know how to handle context [" + context.name + "]");
7076
}

modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java

+21-6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.elasticsearch.script.ScriptContext;
2929
import org.elasticsearch.script.ScriptEngine;
3030
import org.elasticsearch.script.ScriptException;
31+
import org.elasticsearch.script.ScriptFactory;
3132
import org.objectweb.asm.ClassWriter;
3233
import org.objectweb.asm.Opcodes;
3334
import org.objectweb.asm.Type;
@@ -66,7 +67,7 @@ public final class PainlessScriptEngine implements ScriptEngine {
6667
*/
6768
private static final AccessControlContext COMPILATION_CONTEXT;
6869

69-
/**
70+
/*
7071
* Setup the allowed permissions.
7172
*/
7273
static {
@@ -122,7 +123,12 @@ public String getType() {
122123
}
123124

124125
@Override
125-
public <T> T compile(String scriptName, String scriptSource, ScriptContext<T> context, Map<String, String> params) {
126+
public <T extends ScriptFactory> T compile(
127+
String scriptName,
128+
String scriptSource,
129+
ScriptContext<T> context,
130+
Map<String, String> params
131+
) {
126132
Compiler compiler = contextsToCompilers.get(context);
127133

128134
// Check we ourselves are not being called by unprivileged code.
@@ -162,12 +168,16 @@ public Set<ScriptContext<?>> getSupportedContexts() {
162168
* @param <T> The factory class.
163169
* @return A factory class that will return script instances.
164170
*/
165-
private <T> Type generateStatefulFactory(Loader loader, ScriptContext<T> context, Set<String> extractedVariables) {
171+
private <T extends ScriptFactory> Type generateStatefulFactory(
172+
Loader loader,
173+
ScriptContext<T> context,
174+
Set<String> extractedVariables
175+
) {
166176
int classFrames = ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS;
167177
int classAccess = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL;
168178
String interfaceBase = Type.getType(context.statefulFactoryClazz).getInternalName();
169179
String className = interfaceBase + "$StatefulFactory";
170-
String classInterfaces[] = new String[] { interfaceBase };
180+
String[] classInterfaces = new String[] { interfaceBase };
171181

172182
ClassWriter writer = new ClassWriter(classFrames);
173183
writer.visit(WriterConstants.CLASS_VERSION, classAccess, className, null, OBJECT_TYPE.getInternalName(), classInterfaces);
@@ -263,12 +273,17 @@ private <T> Type generateStatefulFactory(Loader loader, ScriptContext<T> context
263273
* @param <T> The factory class.
264274
* @return A factory class that will return script instances.
265275
*/
266-
private <T> T generateFactory(Loader loader, ScriptContext<T> context, Set<String> extractedVariables, Type classType) {
276+
private <T extends ScriptFactory> T generateFactory(
277+
Loader loader,
278+
ScriptContext<T> context,
279+
Set<String> extractedVariables,
280+
Type classType
281+
) {
267282
int classFrames = ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS;
268283
int classAccess = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER| Opcodes.ACC_FINAL;
269284
String interfaceBase = Type.getType(context.factoryClazz).getInternalName();
270285
String className = interfaceBase + "$Factory";
271-
String classInterfaces[] = new String[] { interfaceBase };
286+
String[] classInterfaces = new String[] { interfaceBase };
272287

273288
ClassWriter writer = new ClassWriter(classFrames);
274289
writer.visit(WriterConstants.CLASS_VERSION, classAccess, className, null, OBJECT_TYPE.getInternalName(), classInterfaces);

modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import org.elasticsearch.script.ScoreScript;
7676
import org.elasticsearch.script.Script;
7777
import org.elasticsearch.script.ScriptContext;
78+
import org.elasticsearch.script.ScriptFactory;
7879
import org.elasticsearch.script.ScriptService;
7980
import org.elasticsearch.script.ScriptType;
8081
import org.elasticsearch.threadpool.ThreadPool;
@@ -415,7 +416,7 @@ public Map<String, Object> getParams() {
415416

416417
public abstract Object execute();
417418

418-
public interface Factory {
419+
public interface Factory extends ScriptFactory {
419420

420421
PainlessTestScript newInstance(Map<String, Object> params);
421422

0 commit comments

Comments
 (0)