Skip to content
Merged
6 changes: 3 additions & 3 deletions docs/groovy/conceptual/execution-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ executionContext = ExecutionContext.newBuilder()
.newQueryScope()
.setOperationInitializer(OperationInitializer.NON_PARALLELIZABLE)
.setUpdateGraph(PeriodicUpdateGraph.newBuilder("MyCustomGraph").build())
.setQueryCompiler(QueryCompilerImpl.create(Files.createTempDirectory("qc_").toFile(), ClassLoader.getSystemClassLoader()))
.setQueryCompiler(QueryCompilerImpl.create())
.build()
```

Expand All @@ -248,7 +248,7 @@ This approach allows you to specify:
- **Query scope**: A new, empty query scope via `newQueryScope`.
- **Operation initializer**: Parallelization behavior of operations.
- **Update graph**: A custom update graph (e.g., `PeriodicUpdateGraph` or `EventDrivenUpdateGraph`).
- **Query compiler**: A compiler instance with a specified working directory and class loader.
- **Query compiler**: A compiler instance with an optional directory to load classes from and classloader.

For use cases requiring event-driven updates instead of periodic updates, you can substitute an `EventDrivenUpdateGraph`:

Expand All @@ -262,7 +262,7 @@ executionContext = ExecutionContext.newBuilder()
.newQueryScope()
.setOperationInitializer(OperationInitializer.NON_PARALLELIZABLE)
.setUpdateGraph(eventDrivenGraph)
.setQueryCompiler(QueryCompilerImpl.create(Files.createTempDirectory("qc_").toFile(), ClassLoader.getSystemClassLoader()))
.setQueryCompiler(QueryCompilerImpl.create())
.build()
```

Expand Down
16 changes: 3 additions & 13 deletions docs/python/conceptual/execution-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,7 @@ execution_context = (
.newQueryScope()
.setOperationInitializer(OperationInitializer.NON_PARALLELIZABLE)
.setUpdateGraph(PeriodicUpdateGraph.newBuilder("MyCustomGraph").build())
.setQueryCompiler(
QueryCompilerImpl.create(
jpy.get_type("java.io.File")(temp_dir),
jpy.get_type("java.lang.ClassLoader").getSystemClassLoader(),
)
)
.setQueryCompiler(QueryCompilerImpl.create())
.build()
)
```
Expand All @@ -279,7 +274,7 @@ This approach allows you to specify:
- **Query scope**: A new, empty query scope via `newQueryScope`.
- **Operation initializer**: Parallelization behavior of operations.
- **Update graph**: A custom update graph (e.g., `PeriodicUpdateGraph` or `EventDrivenUpdateGraph`).
- **Query compiler**: A compiler instance with a specified working directory and class loader.
- **Query compiler**: A custom query compiler, which can be created with an optional class directory, plus optional classloader

For use cases requiring event-driven updates instead of periodic updates, you can substitute an `EventDrivenUpdateGraph`:

Expand All @@ -306,12 +301,7 @@ execution_context = (
.newQueryScope()
.setOperationInitializer(OperationInitializer.NON_PARALLELIZABLE)
.setUpdateGraph(event_driven_graph)
.setQueryCompiler(
QueryCompilerImpl.create(
jpy.get_type("java.io.File")(temp_dir),
jpy.get_type("java.lang.ClassLoader").getSystemClassLoader(),
)
)
.setQueryCompiler(QueryCompilerImpl.create())
.build()
)
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@

import java.util.concurrent.ExecutionException;

/**
* Java compiler api, specifically geared towards query language expressions. Implementations should be constructed with
* a path on disk to existing bytecode to use in addition to {@code java.class.path}. Likewise, callers must ensure that
* the context classloader already contains those input classes - the new class will be loaded in a child classloader to
* ensure that the class can be GCd when neither it nor the compiler instance are reachable.
* <p>
* Requests for compilation will never depend on other classes compiled by this or any other QueryCompiler, and are
* expected to be unique based on the provided class name. This enables the implementation to cache classes and only
* compile and load a class once per name.
*/
public interface QueryCompiler {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.IOException;
import java.lang.reflect.Method;
import java.time.Instant;
import java.time.LocalDateTime;
Expand Down Expand Up @@ -60,18 +58,14 @@ private static String generateClassBody(final String className) {
@Rule
public final EngineCleanup framework = new EngineCleanup();

@Rule
public TemporaryFolder folder = new TemporaryFolder();

private SafeCloseable executionContextClosable;

@Before
public void setUp() throws IOException {
public void setUp() {
executionContextClosable = ExecutionContext.newBuilder()
.captureQueryLibrary()
.captureQueryScope()
.setQueryCompiler(QueryCompilerImpl.create(
folder.newFolder(), TestQueryCompiler.class.getClassLoader()))
.setQueryCompiler(QueryCompilerImpl.create())
.build()
.open();
}
Expand Down Expand Up @@ -375,12 +369,15 @@ public void testBadCompile() {
CompletionStageFuture.make(),
};

final QueryCompilerImpl badCompiler = QueryCompilerImpl.createForUnitTests(List.of("InvalidClassArgument"));
final QueryCompilerImpl badCompiler = QueryCompilerImpl.create();
badCompiler.setClassNamesForAnnotationProcessing(List.of("InvalidClassArgument"));

UncheckedDeephavenException e = org.junit.Assert.assertThrows(UncheckedDeephavenException.class,
() -> badCompiler.compile(requests, resolvers));
org.junit.Assert.assertEquals("Error Invoking Compiler, no source present in diagnostic:\n" +
"Class names, 'InvalidClassArgument', are only accepted if annotation processing is explicitly requested",
e.getMessage());

}

@Test
Expand Down
Loading
Loading