java.lang.Object
com.darkcollective.relix.embed.Sandbox

public final class Sandbox extends Object
What a session lets its users reach, and how much work one query may do.

A session is open by default: every declaration the language has is accepted, and nothing is limited beyond what the Relix.Builder sets. A closed sandbox is for a session whose text comes from someone the host does not fully trust, such as a learner or a language model. In a closed sandbox:

  • internal declarations are always accepted: inline tables, views, functions, relate, and generator sources, none of which reads anything outside the session;
  • an external declaration is accepted only if the sandbox's own declarations contain the same one. External means a source that reads a file, a database or an HTTP endpoint, a connection, an import and an env statement. The comparison is on the declaration as printed, so layout and comments do not matter but every value does;
  • the limits below apply to every query.

The sandbox's declarations are installed when the session is built, so the sources and connections they name are ready to query. They may use ${NAME} placeholders, resolved through Relix.Builder.placeholders like any other declaration, which keeps credentials out of the configuration file.

The rules govern text and statements a session is given through Relix.define(String), Relix.define(com.darkcollective.relix.lang.ast.Statement...), Relix.script(String), Relix.relation(String) and Relix.validate(String). The Java registration methods (Relix.table(java.lang.String, java.util.List<java.lang.String>, java.util.List<? extends java.util.Map<java.lang.String, ?>>), Relix.source(java.lang.String, com.darkcollective.relix.symbol.Schema, java.util.function.Supplier<java.util.stream.Stream<com.darkcollective.relix.processor.Row>>), Relix.connector(com.darkcollective.relix.processor.connector.RelixConnector) and the builder's bindings) are the host's own and are not restricted.

The configuration file

load(Path) reads a JSON document. Every key is optional; an unknown key is refused, so a misspelt limit fails rather than silently not applying.
{
  "declarations": "sandbox.relix",
  "limits": {
    "maxInputChars": 20000,
    "maxOutputRows": 1000,
    "maxMaterializedRows": 100000,
    "maxFixpointRounds": 1000,
    "maxProcessedRows": 10000000,
    "timeoutMillis": 30000
  }
}

declarations names a .relix file, relative to the configuration file, holding the external declarations users may reach. It may also hold internal ones, such as a fixed inline table. Relative paths inside it resolve against the configuration file's directory, unless the builder names another base directory.

The limits

Since:
1.0
  • Method Details

    • open

      public static Sandbox open()
      The open sandbox: no rules and no limits. A session built without a sandbox has this one.
      Returns:
      the open sandbox
      Since:
      1.0
    • builder

      public static Sandbox.Builder builder()
      Starts building a closed sandbox. With nothing added, it permits no external declaration at all and sets no limit.
      Returns:
      a new builder
      Since:
      1.0
    • load

      public static Sandbox load(Path configFile)
      Reads a closed sandbox from a configuration file. See the class description for the format.
      Parameters:
      configFile - the JSON configuration file; must not be null
      Returns:
      the sandbox it describes
      Throws:
      RelixException - if the file cannot be read, is not a JSON object, names a key this format does not have, gives a limit that is not a positive integer, or names a declarations file that cannot be read
      Since:
      1.0
    • isOpen

      public boolean isOpen()
      Returns whether this is the open sandbox, which enforces nothing.
      Returns:
      whether this is the open sandbox, which enforces nothing
      Since:
      1.0
    • declarations

      public String declarations()
      Returns the .relix text installed when a session is built: the external declarations users may reach, and any fixed data; empty for none.
      Returns:
      the .relix text installed when a session is built: the external declarations users may reach, and any fixed data; empty for none
      Since:
      1.0
    • baseDirectory

      public Optional<Path> baseDirectory()
      Returns the directory relative paths in the declarations resolve against, when the sandbox names one.
      Returns:
      the directory relative paths in the declarations resolve against, when the sandbox names one
      Since:
      1.0
    • maxInputChars

      public OptionalInt maxInputChars()
      Returns the longest text one call may pass, when limited.
      Returns:
      the longest text one call may pass, when limited
      Since:
      1.0
    • maxOutputRows

      public OptionalInt maxOutputRows()
      Returns the most rows one query returns, when limited.
      Returns:
      the most rows one query returns, when limited
      Since:
      1.0
    • maxMaterializedRows

      public OptionalInt maxMaterializedRows()
      Returns the most rows one blocking operator may buffer, when limited.
      Returns:
      the most rows one blocking operator may buffer, when limited
      Since:
      1.0
    • maxFixpointRounds

      public OptionalInt maxFixpointRounds()
      Returns the most rounds one recursion may run, when limited.
      Returns:
      the most rounds one recursion may run, when limited
      Since:
      1.0
    • maxProcessedRows

      public OptionalLong maxProcessedRows()
      Returns the most rows one execution's operators may pass to one another, when limited.
      Returns:
      the most rows one execution's operators may pass to one another, when limited
      Since:
      1.0
    • timeout

      public Optional<Duration> timeout()
      Returns how long one execution may run, when limited.
      Returns:
      how long one execution may run, when limited
      Since:
      1.0
    • toString

      public String toString()
      Overrides:
      toString in class Object