Skip to content

Production Readiness

Matthew Barker edited this page Jul 31, 2026 · 5 revisions

Production Readiness

Status of A3SQL for live use by units, multiplayer servers, and large mods, and the concrete gaps to close before you rely on it in production.

Verified working (as of v0.2.0)

Everything below is exercised by the CI smoke test, which loads the real release extension binary and runs the mod's own production SQL through the exact C ABI Arma uses ("a3sql" callExtension stmt):

python3 tools/sql_smoke_test.py --bin a3sql_x64.so tools/smoke_test.sql
Area Status
All 4 extension binaries (x64/i686 × Linux/Windows) Verified loading + executing via ctypes/C harnesses, incl. under wine for the DLLs
STRING + ARRAY callExtension forms Both work; every SQF call site routes correctly
The mod's own schema (patch_rules, patch_presets, server_commands) Create/CRUD/cursor/prepare/save/load round-trip green
SQL injection surface $1 param substitution + escaping; call compile removed (RCE-class)
TCP listener Loopback-only, optional LOGIN auth, per-statement panic barrier
Every SQL-Dialect.md documented feature 94/94 pass against the real binary (dialect sweep)
527 Rust tests + miri + clippy -D warnings + hemtt check All green in CI

Gap history — all closed in v0.2.0

These were real, confirmed limitations. Each is now fixed; the list is kept for the record and for anyone upgrading from an older build.

1. Custom SQL engine ≠ SQLite (mitigated)

The parser is sqlparser (mature), but execution is hand-rolled. Real bugs were found and fixed in v0.2.0: UNIQUE treated as PK, datetime('now') in VALUES rejected, no numeric→TEXT affinity, SELECT on empty views failing, STRINGS[]/FLOATS[] columns downgraded to scalars, plus the FFI layer (STRING form empty, ARRAY form routing dead).

Mitigation (not a rewrite): every mod must run its own SQL through the smoke test before shipping — python3 tools/sql_smoke_test.py <mod.sql>. A 94-case dialect sweep now gates every documented feature against the real binary in CI.

2. Response buffer cap raised to 30 KB (DONE)

OUTPUT_BUF_SIZE = 30720 — matches Arma 3 v2.20's callExtension ceiling. SELECTs exceeding ~30 KB still fail with ERR_INTERNAL and need LIMIT/OFFSET pagination, but the headroom is now the full platform cap.

3. Crash-safe persistence (DONE)

SAVE writes to a temp file then renames (atomic on POSIX/NTFS); a crash mid-write leaves the last good save untouched. The previous good save is kept as *.bak; LOAD falls back to it automatically if the main save is corrupt, with a clear message. Binary format carries an FNV-1a checksum trailer verified on LOAD.

4. Single global DB mutex (accepted)

All queries serialize on one Mutex<Database>. Fine for Arma's single-threaded server and unit-scale data (thousands of rows). If a mod hammers the TCP listener from many clients concurrently, expect contention — the RwLock read/write split is the upgrade if profiling ever shows it matters. Not worth the complexity at current scale.

5. Listener auth hardening (DONE)

listener_require_auth = true in a3sql.toml forces LOGIN on every TCP connection even with no CBA credentials set — for shared hosts where any local process could otherwise connect. The empty-credentials LOGIN bypass (LOGIN with blank tokens) is closed, and the error message tells the operator exactly what to configure. CBA credentials still work as before.

6. Save format version pinning (DONE)

Older save formats are rejected with an actionable message: "Save file uses format v1, this build uses v2 — migrate via export_sql and re-import." Saves remain NOT forward/backward compatible across versions (pre-1.0, by design).

What "production ready" means for each consumer

Consumer Can ship today? Notes
Small unit (single server, <10k rows) Yes No blockers
Multiplayer server (public, dedicated host) Yes Set listener credentials; back up a3sql_data/
Big mod (heavy SQL, big datasets) Yes with SQL pass Run own SQL through the smoke test; paginate >30 KB results

The 30-minute production checklist

  1. python3 tools/sql_smoke_test.py tools/smoke_test.sql → all PASS
  2. Run your mod's own SQL through the smoke test → all PASS
  3. Set listener credentials via CBA settings (or listener_require_auth = true in a3sql.toml)
  4. Point a3sql_database_auto_save_path somewhere backed up; test a restore (corrupt the save, confirm the .bak fallback)
  5. Verify a >30 KB SELECT errors cleanly, then paginate or use cursors

Clone this wiki locally