From 40019912d39d483e0c72060b91c573e05184caed Mon Sep 17 00:00:00 2001 From: Jonathan Shook Date: Wed, 27 Sep 2023 23:57:20 -0500 Subject: [PATCH] lay foundation for component hierarchy --- .../java/io/nosqlbench/engine/cli/NBCLI.java | 16 ++-- .../core/lifecycle/scenario/Scenario.java | 7 +- .../lifecycle/session/ResultCollector.java | 45 +++++++++++ .../core/lifecycle/session/ResultContext.java | 81 +++++++++++++++++++ .../core/script/ScenariosExecutorTest.java | 6 +- .../io/nosqlbench/api/config/NBComponent.java | 6 +- .../api/config/standard/NBBaseComponent.java | 39 +++++++++ .../api/config/standard/TestComponent.java | 38 +++++++++ .../api/labels/NBLabeledElement.java | 4 +- 9 files changed, 229 insertions(+), 13 deletions(-) create mode 100644 engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/session/ResultCollector.java create mode 100644 engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/session/ResultContext.java create mode 100644 nb-api/src/main/java/io/nosqlbench/api/config/standard/NBBaseComponent.java create mode 100644 nb-api/src/main/java/io/nosqlbench/api/config/standard/TestComponent.java diff --git a/engine-cli/src/main/java/io/nosqlbench/engine/cli/NBCLI.java b/engine-cli/src/main/java/io/nosqlbench/engine/cli/NBCLI.java index d53289412..42e2ac2cd 100644 --- a/engine-cli/src/main/java/io/nosqlbench/engine/cli/NBCLI.java +++ b/engine-cli/src/main/java/io/nosqlbench/engine/cli/NBCLI.java @@ -72,7 +72,7 @@ import java.util.ServiceLoader.Provider; import java.util.function.Function; import java.util.stream.Collectors; -public class NBCLI implements Function, NBLabeledElement { +public class NBCLI implements Function, NBComponent { private static Logger logger; private static final LoggerConfig loggerConfig; @@ -164,10 +164,11 @@ public class NBCLI implements Function, NBLabeledElement { final NBCLIOptions globalOptions = new NBCLIOptions(args, Mode.ParseGlobalsOnly); this.sessionCode = SystemId.genSessionCode(sessionTime); - this.sessionName = SessionNamer.format(globalOptions.getSessionName(),sessionTime).replaceAll("SESSIONCODE",sessionCode); - this.labels = NBLabels.forKV("appname", "nosqlbench") - .and("node",SystemId.getNodeId()) - .and(globalOptions.getLabelMap()); + this.sessionName = SessionNamer.format(globalOptions.getSessionName(), sessionTime).replaceAll("SESSIONCODE", sessionCode); + this.labels = NBLabels.forKV() + .and("appname", "nosqlbench") + .and("node", SystemId.getNodeId()) + .and(globalOptions.getLabelMap()); NBCLI.loggerConfig .setSessionName(sessionName) @@ -599,4 +600,9 @@ public class NBCLI implements Function, NBLabeledElement { public NBLabels getLabels() { return labels; } + + @Override + public NBComponent getParent() { + return this; + } } diff --git a/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/scenario/Scenario.java b/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/scenario/Scenario.java index 80de69204..ff28ddec7 100644 --- a/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/scenario/Scenario.java +++ b/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/scenario/Scenario.java @@ -19,6 +19,11 @@ import com.codahale.metrics.MetricRegistry; import com.oracle.truffle.js.scriptengine.GraalJSScriptEngine; import io.nosqlbench.api.annotations.Annotation; import io.nosqlbench.api.annotations.Layer; +import io.nosqlbench.api.config.NBComponent; +import io.nosqlbench.api.config.standard.NBBaseComponent; +import io.nosqlbench.api.engine.metrics.ActivityMetrics; +import io.nosqlbench.api.extensions.SandboxExtensionFinder; +import io.nosqlbench.api.extensions.ScriptingExtensionPluginInfo; import io.nosqlbench.api.labels.NBLabeledElement; import io.nosqlbench.api.labels.NBLabels; import io.nosqlbench.api.metadata.ScenarioMetadata; @@ -55,7 +60,7 @@ import java.nio.file.StandardOpenOption; import java.util.*; import java.util.concurrent.Callable; -public class Scenario implements Callable, NBLabeledElement { +public class Scenario extends NBBaseComponent implements Callable { private final String reportSummaryTo; private final Path logsPath; diff --git a/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/session/ResultCollector.java b/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/session/ResultCollector.java new file mode 100644 index 000000000..aa3476ce4 --- /dev/null +++ b/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/session/ResultCollector.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * 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 io.nosqlbench.engine.core.lifecycle.session; + +import io.nosqlbench.engine.core.lifecycle.ExecutionResult; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class ResultCollector implements Consumer { + private final List results = new ArrayList<>(); + + @Override + public void accept(ResultContext resultContext) { + this.results.add(resultContext); + } + + public ExecutionResult toExecutionResult() { + if (results.size()==1) { + return results.get(0).toExecutionResult(); + } else { + long min = results.stream().mapToLong(ResultContext::startMillis).min().orElseThrow(); + long max = results.stream().mapToLong(ResultContext::stopMillis).max().orElseThrow(); + String buf = results.stream().map(ResultContext::output).collect(Collectors.joining("\n\n", "---", "--")); + return new ExecutionResult(min,max,buf,results.get(0).getException()); + } + + } +} diff --git a/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/session/ResultContext.java b/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/session/ResultContext.java new file mode 100644 index 000000000..4960b41e5 --- /dev/null +++ b/engine-core/src/main/java/io/nosqlbench/engine/core/lifecycle/session/ResultContext.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * 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 io.nosqlbench.engine.core.lifecycle.session; + +import io.nosqlbench.engine.core.lifecycle.ExecutionResult; + +import java.util.function.Consumer; + +public class ResultContext implements AutoCloseable { + private final Consumer receiver; + private ExecutionResult.Status status; + + ResultContext(Consumer receiver) { + this.receiver = receiver; + } + + private final long startMillis = System.currentTimeMillis(); + private Exception error; + public final StringBuilder buf = new StringBuilder(); + private long stopMillis; + + public void error(Exception error) { + this.error = error; + } + + public void output(CharSequence cs) { + buf.append(cs); + } + public String output() { + return buf.toString(); + } + + @Override + public void close() throws RuntimeException { + this.stopMillis = System.currentTimeMillis(); + if (this.status==null) { + this.status= ExecutionResult.Status.ERROR; + if (this.error!=null) { + this.error=new RuntimeException("early execution result with no asserted status. Call setStatus on your result context or end with `return ctx.ok() or ctx.error(...)`"); + } + } + receiver.accept(this); + } + + public ExecutionResult toExecutionResult() { + return new ExecutionResult(this.startMillis,this.stopMillis,buf.toString(), error); + } + + public void ok() { + this.status= ExecutionResult.Status.OK; + } + public void error() { + this.status= ExecutionResult.Status.ERROR; + } + + public long startMillis() { + return this.startMillis; + } + + public long stopMillis() { + return this.stopMillis; + } + + public Exception getException() { + return error; + } +} diff --git a/engine-core/src/test/java/io/nosqlbench/engine/core/script/ScenariosExecutorTest.java b/engine-core/src/test/java/io/nosqlbench/engine/core/script/ScenariosExecutorTest.java index e1e7b614a..cda8d29c7 100644 --- a/engine-core/src/test/java/io/nosqlbench/engine/core/script/ScenariosExecutorTest.java +++ b/engine-core/src/test/java/io/nosqlbench/engine/core/script/ScenariosExecutorTest.java @@ -16,10 +16,10 @@ package io.nosqlbench.engine.core.script; -import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosResults; +import io.nosqlbench.api.config.standard.TestComponent; import io.nosqlbench.engine.core.lifecycle.scenario.Scenario; import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosExecutor; -import io.nosqlbench.nb.annotations.Maturity; +import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosResults; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -29,7 +29,7 @@ public class ScenariosExecutorTest { @Disabled public void testAwaitOnTime() { ScenariosExecutor e = new ScenariosExecutor(ScenariosExecutorTest.class.getSimpleName(), 1); - Scenario s = Scenario.forTesting("testing", Scenario.Engine.Graalvm,"stdout:3000", Maturity.Any); + Scenario s = Scenario.forTesting("testing", "stdout:3000", new TestComponent()); s.addScriptText("load('classpath:scripts/asyncs.js');\nsetTimeout(\"print('waited')\",5000);\n"); e.execute(s); ScenariosResults scenariosResults = e.awaitAllResults(); diff --git a/nb-api/src/main/java/io/nosqlbench/api/config/NBComponent.java b/nb-api/src/main/java/io/nosqlbench/api/config/NBComponent.java index 0ea20d4c7..3c1cdbf6e 100644 --- a/nb-api/src/main/java/io/nosqlbench/api/config/NBComponent.java +++ b/nb-api/src/main/java/io/nosqlbench/api/config/NBComponent.java @@ -16,6 +16,8 @@ package io.nosqlbench.api.config; +import io.nosqlbench.api.labels.NBLabeledElement; + /** * A Component is a functional element of the NoSQLBench runtime which is: *
    @@ -29,5 +31,7 @@ package io.nosqlbench.api.config; * * This interface will start as a tagging interface, but will eventually include aspects of above by extension. */ -public interface NBComponent { +public interface NBComponent extends NBLabeledElement { + + NBComponent getParent(); } diff --git a/nb-api/src/main/java/io/nosqlbench/api/config/standard/NBBaseComponent.java b/nb-api/src/main/java/io/nosqlbench/api/config/standard/NBBaseComponent.java new file mode 100644 index 000000000..7c4c8e6a5 --- /dev/null +++ b/nb-api/src/main/java/io/nosqlbench/api/config/standard/NBBaseComponent.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * 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 io.nosqlbench.api.config.standard; + +import io.nosqlbench.api.config.NBComponent; +import io.nosqlbench.api.labels.NBLabels; + +public class NBBaseComponent implements NBComponent { + private final NBComponent parent; + private final NBLabels labels; + + public NBBaseComponent(NBComponent parentComponent, NBLabels compomentSpecificLabelsOnly) { + this.parent = parentComponent; + this.labels = compomentSpecificLabelsOnly; + } + @Override + public NBComponent getParent() { + return parent; + } + + @Override + public NBLabels getLabels() { + return this.parent.getLabels().and(labels); + } +} diff --git a/nb-api/src/main/java/io/nosqlbench/api/config/standard/TestComponent.java b/nb-api/src/main/java/io/nosqlbench/api/config/standard/TestComponent.java new file mode 100644 index 000000000..7d8076052 --- /dev/null +++ b/nb-api/src/main/java/io/nosqlbench/api/config/standard/TestComponent.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * 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 io.nosqlbench.api.config.standard; + +import io.nosqlbench.api.config.NBComponent; +import io.nosqlbench.api.labels.NBLabels; + +public class TestComponent implements NBComponent { + + private final NBLabels labels; + + public TestComponent(String... labels) { + this.labels = NBLabels.forKV((Object[]) labels); + } + @Override + public NBComponent getParent() { + return this; + } + + @Override + public NBLabels getLabels() { + return labels; + } +} diff --git a/nb-api/src/main/java/io/nosqlbench/api/labels/NBLabeledElement.java b/nb-api/src/main/java/io/nosqlbench/api/labels/NBLabeledElement.java index a471baa18..ed4b702ef 100644 --- a/nb-api/src/main/java/io/nosqlbench/api/labels/NBLabeledElement.java +++ b/nb-api/src/main/java/io/nosqlbench/api/labels/NBLabeledElement.java @@ -16,11 +16,9 @@ package io.nosqlbench.api.labels; -import io.nosqlbench.api.config.NBComponent; - import java.util.Map; -public interface NBLabeledElement extends NBComponent { +public interface NBLabeledElement { NBLabeledElement EMPTY = forKV();