Concurrent Batch (Headless)

Concurrent Batch (Headless)

Headless (no GUI) example demonstrating parallel batch execution with core.EvalBatch. Uses only the core package — no Fyne/GUI dependencies.

Features

  • Compile once, run many - A single script is compiled to bytecode once, then run over many inputs concurrently
  • Isolated VMs - Each input runs on its own Context+VM with no shared mutable state
  • Bounded concurrency - BatchConfig{Concurrency: 4} caps how many inputs run at once
  • Index-aligned results - Output order matches input order; per-input errors are reported individually
  • Per-input globals - Each input map is exposed to the script as global variables

Worker Script

worker.risor is the unit of work — it reads the CSV file named by the per-input global file, sums the amount column, and returns a summary map:

require(["v0.8", "@csv"])

// `file` is supplied per-input by core.EvalBatch — one run per CSV file,
// each on its own isolated VM.
let rows = csv.read(file)

let total = 0
rows.each(row => { total = total + int(row["amount"]) })

// The final expression is this run's result (returned to Go as map[string]any).
{
    "rows": len(rows),
    "total": total,
}

Go Host

// One input per file; each becomes the global `file` for that run.
inputs := make([]map[string]any, len(files))
for i, f := range files {
    inputs[i] = map[string]any{"file": f}
}

results, err := core.EvalBatch(
    context.Background(),
    string(script),
    inputs,
    core.BatchConfig{Concurrency: 4},
    core.WithCSV(),
)

// Results are index-aligned with inputs. Per-input failures appear in r.Err;
// the returned error is only for setup/compile failures.
for i, r := range results {
    if r.Err != nil {
        fmt.Printf("%-16s ERROR: %v\n", files[i], r.Err)
        continue
    }
    fmt.Printf("%-16s %v\n", files[i], r.Value)
}
ℹ️
EvalBatch is headless only — do not use it to drive Fyne widgets. Stateless modules like csv/json/strings are safe across workers; values shared via WithGlobal must be made concurrency-safe by the caller.

Running

cd examples/40-concurrent-batch
go run main.go

Expected output (order-stable, one line per file):

data/east.csv    map[rows:4 total:400]
data/north.csv   map[rows:3 total:425]
data/south.csv   map[rows:2 total:625]
data/west.csv    map[rows:2 total:355]

Full Source

View full example on GitHub ↗