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
524 Rust tests + miri + clippy -D warnings + hemtt check All green in CI

Gaps to close for production

Ranked by risk. Each is a real, confirmed limitation — not theoretical.

1. Custom SQL engine ≠ SQLite (HIGH)

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). More incompatibilities will surface with real-world SQL.

Close it: every mod must run its own SQL through the smoke test before shipping. The tool exists for exactly this. Engine-side: build a SQLite compatibility corpus (run a known SQL suite against both engines, diff behaviour) and fix the top divergences.

2. 20 KB response buffer cap (MEDIUM)

OUTPUT_BUF_SIZE = 20480. SELECTs returning more than that fail with ERR_INTERNAL — mods must paginate with LIMIT/OFFSET. Arma 3's own callExtension ceiling is ~30 KB (v2.20), so there is headroom to raise the cap, but not to unbounded.

Close it: raise to 30 KB; document the cap + pagination pattern in Module-Guide.md. Consider an explicit fetch_rows/cursor mode for big dumps (partial: cursor create/fetch/drop already exists).

3. No write-ahead journal / crash durability (MEDIUM)

SAVE is a synchronous full-file write. A crash mid-write (server kill, power loss) can corrupt the save file. No WAL, no checksum, no atomic rename.

Close it: write to *.tmp then rename (atomic on POSIX/NTFS); append a checksum trailer and verify on LOAD; keep the last-good backup (*.bak) on load failure. This is ~30 lines in dispatch/commands/io.rs.

4. Single global DB mutex (LOW for current scale)

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.

Close it: only if profiling shows it. RwLock split (reads vs writes) is the cheap upgrade; per-connection batching is the expensive one.

5. Listener auth is optional (MEDIUM if shared host)

No credentials set (set_credentials never called) → any local process can run SQL over the loopback listener. Acceptable on a dedicated box.

Close it: require credentials by default (config flag listener_require_auth = true); document in TCP-Connector.md.

6. Save format version pinning (LOW)

Binary save format has magic + version byte; older saves are rejected on mismatch. Fine pre-1.0, but document that saves are NOT forward/backward compatible across versions, and make the failure message actionable ("save from v0.1.2 — migrate via export_sql").

What "production ready" means for each consumer

Consumer Blocking gaps Can ship today?
Small unit (single server, <10k rows) none Yes
Multiplayer server (public, dedicated host) #5 (set credentials), #3 (back up a3sql_data) Yes with hygiene
Big mod (heavy SQL, big datasets) #1 (smoke-test own SQL), #2 (pagination) After SQL pass

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
  4. Point a3sql_database_auto_save_path somewhere backed up; test a restore
  5. Verify a >20 KB SELECT errors cleanly, then paginate or use cursors

Clone this wiki locally