Skip to content

Live-verify server/managed backend adapters; fix 8 bugs - #14

Merged
thorwhalen merged 1 commit into
masterfrom
verify-server-backend-adapters
May 22, 2026
Merged

Live-verify server/managed backend adapters; fix 8 bugs#14
thorwhalen merged 1 commit into
masterfrom
verify-server-backend-adapters

Conversation

@thorwhalen

Copy link
Copy Markdown
Member

Closes #13. Refs #11.

Live verification of the 9 backend adapters that #11 shipped
correct-by-construction but never ran against a real engine. Verified the 7
reachable without a cloud account; pinecone and turbopuffer remain
deferred (need accounts).

Result: all 344 contract tests pass across 13 backends. 8 real bugs found.

Bugs fixed

Backend Bug
sqlite_vec vec0 tables reject INSERT OR REPLACE → delete+insert; KNN through a JOIN drops the required k constraint → subquery form; over-broad except OperationalError swallowed query errors → explicit _tables_exist; NULL distance for a zero-norm vector crashed scoring
milvus tempfile.mkstemp creates a file, but milvus-lite ≥3.0 wants a directory path → FileExistsError
pgvector vector(N) type modifier can't be a bound parameter; executemany is a cursor method in psycopg 3, not a connection method; query vector needs an explicit ::vector cast
elasticsearch lazily-created collections were invisible to list/in/get → index created eagerly, dense_vector field added on first write; _keys sorted on the disallowed _id field → helpers.scan
weaviate collections.get() never raises in v4, so _class_exists always returned True → create/get/delete broken → collections.exists()
mongodb _raw_to_document was undefined (NameError in _read); the Atlas vector search index is now auto-created + awaited on first search; metadata filtering moved client-side (Atlas can only pre-filter on index-declared fields)

Test harness (reusable)

  • tests/docker-compose.yml — one container per server backend.
  • tests/conftest.py — the client fixture now sweeps embedded and server
    backends; server backends are TCP-probed and skipped when unreachable, so
    CI stays green without containers.
  • tests/README.md — how to run it.

Notable design decision

The mongodb adapter previously required the Atlas vector search index to be
created out-of-band. It now creates and awaits the index automatically on the
first search — making mongodb consistent with every other adapter (all
auto-create their index) and honoring the facade's "simple things simple"
principle. Needs an Atlas-capable deployment (Atlas / mongodb-atlas-local).

Test-input change

Three contract tests used all-zero vectors as "valid" inputs. A zero-magnitude
vector has undefined cosine similarity and Elasticsearch rejects it outright;
the inputs are now non-zero (assertions are filter/dimension-driven, so intent
is preserved). This makes the cross-backend contract honest — vd does not
promise zero-vector portability.

Verification environment

Run in an isolated venv (Python 3.11, all backend client libs) to keep the
heavyweight DB clients out of the main environment. milvus is verified against
the embedded Milvus Lite engine — same adapter code path as a server, only the
client constructor differs.

Exercised the 9 previously-unverified backend adapters (issue #11) against
real engines: Docker containers for pgvector / redis / elasticsearch /
weaviate / mongodb, the embedded Milvus Lite engine for milvus, and a
loadable-extension Python for sqlite_vec. All 344 contract tests now pass
across 13 backends.

Adapter bugs fixed:
- sqlite_vec: vec0 tables reject INSERT OR REPLACE (delete+insert instead);
  a KNN query through a JOIN drops the required `k` constraint (subquery
  form); an over-broad `except OperationalError` silently swallowed query
  errors; a NULL distance for a zero-norm vector crashed scoring.
- milvus: used tempfile.mkstemp (creates a file) but milvus-lite >=3.0
  treats the path as a directory -> FileExistsError.
- pgvector: the vector(N) type modifier cannot be a bound parameter;
  executemany is a cursor (not connection) method in psycopg 3; the query
  vector needs an explicit ::vector cast.
- elasticsearch: lazily-created collections were invisible to list /
  contains / get (the index is now created eagerly, the dense_vector field
  added on first write); _keys sorted on the disallowed _id field (now uses
  helpers.scan).
- weaviate: collections.get() never raises in v4, so _class_exists always
  reported True -> create / get / delete were broken (now collections.exists()).
- mongodb: _raw_to_document was undefined (NameError in _read); the Atlas
  vector search index is now created and awaited automatically on the first
  search, and metadata filtering moved client-side (Atlas can only pre-filter
  on index-declared fields).

Test harness:
- tests/docker-compose.yml: one container per server backend.
- tests/conftest.py: sweeps embedded + server backends; server backends are
  TCP-probed and skipped when unreachable, so CI stays green without them.
- tests/README.md: how to run the server-backend suite.

Also: de-degenerate three test inputs that used all-zero vectors (undefined
cosine similarity, which Elasticsearch rejects); add milvus-lite to the
milvus extra so the embedded engine works out of the box.

Refs #11
@thorwhalen
thorwhalen merged commit ba175d5 into master May 22, 2026
12 checks passed
@thorwhalen
thorwhalen deleted the verify-server-backend-adapters branch May 22, 2026 07:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Live-verify the 9 server/managed backend adapters (deferred from #11)

1 participant