Denox.Pool (denox v0.7.0)

Copy Markdown View Source

GenServer-based pool of JavaScript runtimes for concurrent workloads.

V8 isolates are single-threaded, so the pool round-robins requests across N runtimes to achieve parallelism.

Usage

# In your supervision tree
children = [
  {Denox.Pool, name: :js_pool, size: 4, permissions: :all}
]

# Then use the pool
{:ok, result} = Denox.Pool.eval(:js_pool, "1 + 2")
{:ok, result} = Denox.Pool.eval_ts(:js_pool, "const x: number = 42; x")

Pre-loading shared code

Use load_npm/2 to load a bundled JS file into all pool runtimes at once. This is the recommended way to share npm packages across a pool:

Denox.Npm.bundle!("npm:zod@3.22", "priv/bundles/zod.js")
:ok = Denox.Pool.load_npm(:js_pool, "priv/bundles/zod.js")

Or use exec/2 to initialise shared globals:

:ok = Denox.Pool.exec(:js_pool, "globalThis.helper = (x) => x * 2")

Note that each runtime in the pool has independent state, so mutations made via exec/2 are distributed round-robin and may not reach all runtimes. Use load_npm/2 (which broadcasts to all runtimes) for shared initialisation.

Summary

Functions

Call a named JavaScript function with arguments.

Call a named async JavaScript function with arguments, returning a Task.

Call a named async JavaScript function and decode the JSON result, returning a Task.

Call a named JavaScript function and decode the JSON result.

Returns a child specification for the pool, using the :name option as the child id.

Evaluate JavaScript code using the next runtime in the pool.

Evaluate JavaScript code asynchronously, returning a Task.

Evaluate JavaScript asynchronously and decode JSON result, returning a Task.

Evaluate and decode JSON result.

Read and evaluate a JavaScript or TypeScript file.

Read and evaluate a JavaScript or TypeScript file asynchronously, returning a Task.

Read and evaluate a JavaScript or TypeScript file asynchronously and decode the JSON result, returning a Task.

Read and evaluate a JavaScript or TypeScript file and decode the JSON result.

Load and evaluate an ES module file. Supports .ts/.js with import/export.

Evaluate TypeScript code using the next runtime in the pool.

Evaluate TypeScript code asynchronously, returning a Task.

Evaluate TypeScript asynchronously and decode JSON result, returning a Task.

Evaluate TypeScript and decode JSON result.

Execute JavaScript code, ignoring the return value.

Execute TypeScript code, ignoring the return value.

Load a bundled JS file into all runtimes in the pool.

Return the pool size.

Start a pool of runtimes.

Types

pool()

@type pool() :: GenServer.server()

Functions

call(pool, func_name, args \\ [])

@spec call(pool(), String.t(), list()) :: {:ok, String.t()} | {:error, String.t()}

Call a named JavaScript function with arguments.

call_async(pool, func_name, args \\ [])

@spec call_async(pool(), String.t(), list()) :: Task.t()

Call a named async JavaScript function with arguments, returning a Task.

call_async_decode(pool, func_name, args \\ [])

@spec call_async_decode(pool(), String.t(), list()) :: Task.t()

Call a named async JavaScript function and decode the JSON result, returning a Task.

call_decode(pool, func_name, args \\ [])

@spec call_decode(pool(), String.t(), list()) :: {:ok, term()} | {:error, term()}

Call a named JavaScript function and decode the JSON result.

child_spec(init_arg)

@spec child_spec(keyword()) :: Supervisor.child_spec()

Returns a child specification for the pool, using the :name option as the child id.

This allows multiple pools to coexist in the same supervisor without id conflicts.

eval(pool, code)

@spec eval(pool(), String.t()) :: {:ok, String.t()} | {:error, String.t()}

Evaluate JavaScript code using the next runtime in the pool.

eval_async(pool, code)

@spec eval_async(pool(), String.t()) :: Task.t()

Evaluate JavaScript code asynchronously, returning a Task.

eval_async_decode(pool, code)

@spec eval_async_decode(pool(), String.t()) :: Task.t()

Evaluate JavaScript asynchronously and decode JSON result, returning a Task.

eval_decode(pool, code)

@spec eval_decode(pool(), String.t()) :: {:ok, term()} | {:error, term()}

Evaluate and decode JSON result.

eval_file(pool, path, opts \\ [])

@spec eval_file(pool(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, String.t()}

Read and evaluate a JavaScript or TypeScript file.

eval_file_async(pool, path, opts \\ [])

@spec eval_file_async(pool(), String.t(), keyword()) :: Task.t()

Read and evaluate a JavaScript or TypeScript file asynchronously, returning a Task.

eval_file_async_decode(pool, path, opts \\ [])

@spec eval_file_async_decode(pool(), String.t(), keyword()) :: Task.t()

Read and evaluate a JavaScript or TypeScript file asynchronously and decode the JSON result, returning a Task.

eval_file_decode(pool, path, opts \\ [])

@spec eval_file_decode(pool(), String.t(), keyword()) ::
  {:ok, term()} | {:error, term()}

Read and evaluate a JavaScript or TypeScript file and decode the JSON result.

eval_module(pool, path)

@spec eval_module(pool(), String.t()) :: {:ok, String.t()} | {:error, String.t()}

Load and evaluate an ES module file. Supports .ts/.js with import/export.

eval_ts(pool, code)

@spec eval_ts(pool(), String.t()) :: {:ok, String.t()} | {:error, String.t()}

Evaluate TypeScript code using the next runtime in the pool.

eval_ts_async(pool, code)

@spec eval_ts_async(pool(), String.t()) :: Task.t()

Evaluate TypeScript code asynchronously, returning a Task.

eval_ts_async_decode(pool, code)

@spec eval_ts_async_decode(pool(), String.t()) :: Task.t()

Evaluate TypeScript asynchronously and decode JSON result, returning a Task.

eval_ts_decode(pool, code)

@spec eval_ts_decode(pool(), String.t()) :: {:ok, term()} | {:error, term()}

Evaluate TypeScript and decode JSON result.

exec(pool, code)

@spec exec(pool(), String.t()) :: :ok | {:error, String.t()}

Execute JavaScript code, ignoring the return value.

Returns :ok on success. Returns {:error, message} if the JavaScript throws or if evaluation fails — callers must still handle the error.

exec_ts(pool, code)

@spec exec_ts(pool(), String.t()) :: :ok | {:error, String.t()}

Execute TypeScript code, ignoring the return value.

Returns :ok on success. Returns {:error, message} if the code throws or if evaluation fails — callers must still handle the error.

load_npm(pool, bundle_path)

@spec load_npm(pool(), String.t()) :: :ok | {:error, String.t()}

Load a bundled JS file into all runtimes in the pool.

size(pool)

@spec size(pool()) :: non_neg_integer()

Return the pool size.

start_link(opts)

@spec start_link(keyword()) :: GenServer.on_start()

Start a pool of runtimes.

Options:

  • :name - registered name for the pool (required)
  • :size - number of runtimes (default: System.schedulers_online())
  • :permissions - permission mode for all runtimes (:all, :none, or keyword list)
  • :sandbox - (deprecated) use permissions: :none instead
  • :base_dir - base directory for module resolution
  • :cache_dir - cache directory for remote modules
  • :import_map - map of bare specifiers to resolved URLs/paths
  • :callback_pid - PID that handles JS→Elixir callbacks
  • :snapshot - V8 snapshot binary for faster cold start (applied to all runtimes)