Files
OmniRoute/docs/ops/SQLITE_RUNTIME.md
Praveen K Palaniswamy 65e81158ab fix(ollama): route models by advertised capability (#11088)
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host.

Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean.

Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
2026-08-23 11:45:01 -03:00

3.9 KiB

title
title
SQLite Runtime Resolution

SQLite Runtime Resolution

OmniRoute resolves its SQLite driver at startup through a 5-step fallback chain:

  1. Bundled better-sqlite3 (via dependencies in package.json) — fastest, native binary, installed by npm install when build tools are present.

  2. Runtime-installed better-sqlite3 (in ~/.omniroute/runtime/) — installed lazily on first run OR by scripts/build/postinstall.mjs → scripts/postinstall.mjs. Validates native .node magic bytes (ELF / Mach-O / PE) before loading to guard against corrupt or wrong-platform binaries.

  3. node:sqlite (Node ≥22.5 stdlib) — no native build needed; used when both better-sqlite3 paths fail. Limited feature set.

  4. sql.js (WASM) — final fallback. Works everywhere but is slower and writes data on an interval rather than synchronously.

Why this complexity?

  • Windows EBUSY: npm install -g omniroute@latest can fail if the previous version's better_sqlite3.node is locked by a running process. The runtime install in ~/.omniroute/runtime/ sidesteps the global npm cache.
  • No build tools: Some environments (corporate Windows without VS Build Tools, minimal Docker images) cannot compile better-sqlite3. The runtime installer resolves a pre-built binary from the npm registry; the fallback drivers ensure OmniRoute still boots even if that fails.
  • Air-gapped systems: If the npm registry is unreachable, node:sqlite or sql.js guarantee baseline functionality.

Magic-byte validation

Before loading a runtime-installed .node file, OmniRoute reads the first 8 bytes and matches against known platform magics:

Platform Bytes (hex) Label
Linux 7F 45 4C 46 elf
macOS 64-bit BE FE ED FA CF macho
macOS 64-bit LE CF FA ED FE macho-le
macOS fat (universal) CA FE BA BE macho-fat
Windows 4D 5A (MZ) pe

A mismatched magic → file is ignored, fallback continues to the next step.

Checking the active driver

import { getDriverInfo } from "@/lib/db/core";

const info = getDriverInfo();
// { source: "bundled" | "runtime" | "runtime-installed-now" | "node-sqlite" | "sql-js",
//   kind: "better-sqlite3" | "node-sqlite" | "sql-js" }

Manual control

# Skip postinstall warm-up (for fast CI installs)
OMNIROUTE_SKIP_POSTINSTALL=1 npm install -g omniroute

# Force-reinstall runtime better-sqlite3
rm -rf ~/.omniroute/runtime
omniroute  # will reinstall on next start

# Check what driver is active
omniroute config db-info  # (if CLI command exists)

Reference

Implementation:

  • bin/cli/runtime/magicBytes.mjs — binary magic-byte validation helpers
  • bin/cli/runtime/sqliteRuntime.mjs — 5-step runtime resolver + lazy installer
  • bin/cli/runtime/index.mjs — startup orchestrator (warmUpRuntimes())
  • scripts/postinstall.mjs — npm post-install hook (non-fatal warm-up)
  • src/lib/db/core.tsensureDbInitialized() / getDriverInfo() exports

Single-writer topology (HA unsupported)

The driver fallback chain above still runs in one process. Default SQLite OmniRoute is a single writer:

  • Do not attach two OmniRoute replicas to the same storage.sqlite file.
  • A container restart, Recreate deploy, OOM kill, or HEALTHCHECK restart drops every in-flight SSE session. There is no session drain on the stock path.
  • Orchestrator liveness that treats a slow /healthz as dead will kill the only replica. Prefer TCP liveness + HTTP /healthz readiness. See Docker Guide — availability and Kubernetes probe recommendations.