Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime fields: rework script service injection #59659

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,60 +6,26 @@

package org.elasticsearch.xpack.runtimefields;

import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.plugins.MapperPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.ScriptPlugin;
import org.elasticsearch.repositories.RepositoriesService;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.runtimefields.mapper.ScriptFieldMapper;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

public final class RuntimeFields extends Plugin implements MapperPlugin, ScriptPlugin {

private final ScriptFieldMapper.TypeParser typeParser = new ScriptFieldMapper.TypeParser();

@Override
public Map<String, Mapper.TypeParser> getMappers() {
return Collections.singletonMap(ScriptFieldMapper.CONTENT_TYPE, typeParser);
return Collections.singletonMap(ScriptFieldMapper.CONTENT_TYPE, new ScriptFieldMapper.TypeParser());
}

@Override
public List<ScriptContext<?>> getContexts() {
return List.of(DoubleScriptFieldScript.CONTEXT, LongScriptFieldScript.CONTEXT, StringScriptFieldScript.CONTEXT);
}

@Override
public Collection<Object> createComponents(
Client client,
ClusterService clusterService,
ThreadPool threadPool,
ResourceWatcherService resourceWatcherService,
ScriptService scriptService,
NamedXContentRegistry xContentRegistry,
Environment environment,
NodeEnvironment nodeEnvironment,
NamedWriteableRegistry namedWriteableRegistry,
IndexNameExpressionResolver indexNameExpressionResolver,
Supplier<RepositoriesService> repositoriesServiceSupplier
) {
// TODO getMappers gets called before createComponents. We should wire the script service differently
typeParser.setScriptService(scriptService);
return Collections.emptyList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

package org.elasticsearch.xpack.runtimefields.mapper;

import org.apache.lucene.util.SetOnce;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
Expand All @@ -15,7 +14,7 @@
import org.elasticsearch.index.mapper.ParametrizedFieldMapper;
import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.xpack.runtimefields.StringScriptFieldScript;

Expand All @@ -29,7 +28,7 @@ public final class ScriptFieldMapper extends ParametrizedFieldMapper {

private final String runtimeType;
private final Script script;
private final ScriptService scriptService;
private final ScriptCompiler scriptCompiler;

protected ScriptFieldMapper(
String simpleName,
Expand All @@ -38,17 +37,17 @@ protected ScriptFieldMapper(
CopyTo copyTo,
String runtimeType,
Script script,
ScriptService scriptService
ScriptCompiler scriptCompiler
) {
super(simpleName, mappedFieldType, multiFields, copyTo);
this.runtimeType = runtimeType;
this.script = script;
this.scriptService = scriptService;
this.scriptCompiler = scriptCompiler;
}

@Override
public ParametrizedFieldMapper.Builder getMergeBuilder() {
return new ScriptFieldMapper.Builder(simpleName(), scriptService).init(this);
return new ScriptFieldMapper.Builder(simpleName(), scriptCompiler).init(this);
}

@Override
Expand Down Expand Up @@ -99,11 +98,11 @@ private static ScriptFieldMapper toType(FieldMapper in) {
}
});

private final ScriptService scriptService;
private final ScriptCompiler scriptCompiler;

protected Builder(String name, ScriptService scriptService) {
protected Builder(String name, ScriptCompiler scriptCompiler) {
super(name);
this.scriptService = scriptService;
this.scriptCompiler = scriptCompiler;
}

@Override
Expand All @@ -115,7 +114,7 @@ protected List<Parameter<?>> getParameters() {
public ScriptFieldMapper build(BuilderContext context) {
MappedFieldType mappedFieldType;
if (runtimeType.getValue().equals("keyword")) {
StringScriptFieldScript.Factory factory = scriptService.compile(script.getValue(), StringScriptFieldScript.CONTEXT);
StringScriptFieldScript.Factory factory = scriptCompiler.compile(script.getValue(), StringScriptFieldScript.CONTEXT);
mappedFieldType = new RuntimeKeywordMappedFieldType(buildFullName(context), script.getValue(), factory, meta.getValue());
} else {
throw new IllegalArgumentException("runtime_type [" + runtimeType + "] not supported");
Expand All @@ -128,7 +127,7 @@ public ScriptFieldMapper build(BuilderContext context) {
copyTo.build(),
runtimeType.getValue(),
script.getValue(),
scriptService
scriptCompiler
);
}

Expand All @@ -143,19 +142,23 @@ static Script parseScript(String name, Mapper.TypeParser.ParserContext parserCon

public static class TypeParser implements Mapper.TypeParser {

private final SetOnce<ScriptService> scriptService = new SetOnce<>();

public void setScriptService(ScriptService scriptService) {
this.scriptService.set(scriptService);
}

@Override
public ScriptFieldMapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext)
throws MapperParsingException {

ScriptFieldMapper.Builder builder = new ScriptFieldMapper.Builder(name, scriptService.get());
ScriptFieldMapper.Builder builder = new ScriptFieldMapper.Builder(name, new ScriptCompiler() {
@Override
public <FactoryType> FactoryType compile(Script script, ScriptContext<FactoryType> context) {
return parserContext.queryShardContextSupplier().get().compile(script, context);
}
});
builder.parse(name, parserContext, node);
return builder;
}
}

@FunctionalInterface
private interface ScriptCompiler {
<FactoryType> FactoryType compile(Script script, ScriptContext<FactoryType> context);
}
}