Skip to content

Backend clients in CI; account-free live tests for Pinecone, MongoDB Atlas and Qdrant server; 3 adapter fixes - #30

Merged
thorwhalen merged 7 commits into
masterfrom
cloud-sweep-2026-09-26
Sep 30, 2026
Merged

thorwhalen merged 7 commits into
masterfrom
cloud-sweep-2026-09-26

Conversation

@thorwhalen

@thorwhalen thorwhalen commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Follow-up to #25, answering two requests: run the qdrant and LanceDB tests in CI, and find a way to test the "account-only" backends without accounts.

Tests

Where Before (master) After
GitHub CI, Python 3.10 (test,ci-backends) 210 passed 286 passed, 338 skipped
This VM, every server backend up (dev env, pinecone 9.1) server backends mostly skipped 631 passed, 13 skipped

The 13 skips are by design: fallback-only tests skip on native-hybrid backends. Dependents are unchanged: ef 111 passed, ir 583 passed, newsmood 192 passed with the same 6 pre-existing config2py failures.

Account-free testing

Backend How it's tested now
pinecone Pinecone Local, the official in-memory emulator (ghcr.io/pinecone-io/pinecone-local). It speaks the pre-2026-07 API, so it needs the pinecone SDK < 10; the tests skip with that reason on SDK 10.
mongodb MongoDB Atlas Local (mongodb/mongodb-atlas-local), with real $vectorSearch.
qdrant (server) A qdrant/qdrant container, as the new qdrant_server entry next to embedded qdrant.
weaviate, pgvector, redis, elasticsearch Containers, as before. They are now reachable from the cloud VM too.
turbopuffer Not possible: no emulator exists, and turbopuffer's docs say to test against production with a throwaway namespace.

tests/docker-compose.yml brings all seven up. DOCKERHUB_MIRROR=mirror.gcr.io pulls Docker Hub images through Google's mirror, avoiding the anonymous rate limit that blocked the previous sweep.

Changes

  • ci: new ci-backends extra (qdrant-client, lancedb, pgvector, psycopg[binary]), installed via [tool.wads.ci.install] extras = "test,ci-backends". The Windows job installs these extras as well; it is non-blocking.
  • fix(mongodb): recreating a collection under a dropped name hung for 120 s. Atlas briefly lists the old index as DOES_NOT_EXIST.
  • fix(pinecone): the adapter failed 19 of 32 contract tests on Pinecone Local; all now pass.
    • A new host= option reaches the emulator, and indexes are opened over plain HTTP for an http:// host.
    • A reversible _→-- name mapping, because Pinecone allows only [a-z0-9-] while Milvus rejects hyphens.
    • Collections created without a dimension are tracked until their first write.
    • IDs are parsed from every Index.list() page shape.
  • fix(qdrant): get_collection reads the metric and dimension from the server. A second client used to score l2 collections as cosine, returning raw distances.
  • test: new server entries (pinecone, qdrant_server), live regression tests, and a native-async qdrant test against the server.
    • Server probes follow the VD_* overrides.
    • Non-local or unparseable targets are skipped unless VD_ALLOW_REMOTE_TESTS=1, because the fixture deletes every collection it sees.
  • docs: tests/README.md, CLAUDE.md, the README contributor section and the vd-setup-backend skill, which now has an account-free Pinecone and Atlas section; its snippets were run.

Issues

Adversarial review (Opus subagent)

Two rounds by a separate Opus subagent, briefed to refute the change. It ran everything it suspected, including CI's configuration with the network cut off: 286 passed, 0 failed. Verdict: APPROVE in both rounds, with no blocking findings.

Round 1 (9 non-blocking):

  • Fixed:
    • Unreachable Pinecone names like a-_b: names that don't round-trip are now rejected, with unit tests.
    • The test guard could wipe a real account through a VD_* override.
    • Pinecone tests now skip on SDK 10 instead of failing.
    • The milvus wording in CLAUDE.md.
  • Accepted:
    • Existing -- index names now list as _; the not-found message explains the mapping.
    • ci-backends is a public extra.
    • A mongodb race path relies on the error text containing "already exists".
    • Named or sparse qdrant collections fall back to cosine, and get_collection makes one extra round trip.
  • Corrected in this description: the Windows job also installs the CI extras.

Round 2 (4 non-blocking), all fixed in the last commit:

  • Keyword-style Postgres DSNs slipped past the guard.
  • Multi-host MongoDB URIs errored instead of skipping.
  • The Pinecone version check failed with the legacy package.
  • The error wording overstated the name rule.

That last commit touches only test infrastructure and one error string, so it was not re-reviewed. The suites were rerun after it.

For whoever lands it

  • Merging publishes a release.
  • Pinecone users see collection names mapped (my_docs ↔ index my--docs). Pre-existing hyphenated indexes like my-index are unaffected.
  • The pinecone adapter is verified on SDK 9.1 against Pinecone Local. On SDK 10 it imports and its calls exist, but it can't be exercised without a real account.

Fixes #29

🤖 Generated with Claude Code

New ci-backends extra (qdrant-client, lancedb, pgvector + psycopg[binary])
installed alongside test via [tool.wads.ci.install]. Before this, every
qdrant, LanceDB and pgvector test skipped in CI.
…llection

Right after a drop, Atlas still lists the old collection's search index
with status DOES_NOT_EXIST. The adapter took that as "exists", skipped
create_search_index, then waited 120 s on an index that never came.
Ignore DOES_NOT_EXIST / DELETING entries, and (re)create the index if it
vanishes while waiting. Verified against MongoDB Atlas Local: the live
mongodb suite now passes (28 tests, 15 s; it had 2 timeouts).

Fixes #29
…ocal

Running the shared suite against Pinecone Local (the official in-memory
emulator, no account) failed 19 of 32 tests. Fixes:

- host= on the client reaches Pinecone Local (api_key="pclocal"); with an
  http:// host, index handles are opened over plain HTTP, since the
  emulator reports https:// index hosts but serves HTTP.
- Collection names: Pinecone allows only [a-z0-9-] while Milvus and SQL
  backends reject hyphens. '_' in a vd name is stored as '--' in the index
  name and mapped back on listing; ambiguous or invalid names raise a
  clear ValueError before any API call.
- Collections created without a dimension are tracked until their first
  write, so list/get/delete/duplicate checks see them (as qdrant does).
- Document ids are read from every Index.list() page shape (v9 yields
  ListResponse pages of ListItem objects; iterating them crashed).

tests/conftest.py gains a pinecone server entry (probe :5080). Pinecone
Local speaks the pre-2026-07 API, so it needs the pinecone SDK < 10.
A client that did not create a collection assumed cosine, so an l2
collection opened from a second client (or process) returned raw
Euclidean distances as scores. get_collection now reads the distance and
size from Qdrant's collection config, in the sync and native async
clients alike.

Found by running the suite against a real Qdrant server: tests/conftest.py
gains a qdrant_server entry (the qdrant adapter with url=, probe :6333)
alongside embedded qdrant, plus live tests for this regression and for
native async against the server (parity with sync).
tests/docker-compose.yml adds a Qdrant server and Pinecone Local (the
official in-memory emulator) next to pgvector, Redis, Elasticsearch,
Weaviate and MongoDB Atlas Local, and takes an optional DOCKERHUB_MIRROR
(e.g. mirror.gcr.io) to avoid Docker Hub's anonymous pull limit. With
all seven up, the full suite is 620 passed, 13 skipped (by-design
fallback-only tests); turbopuffer has no emulator.

tests/README.md, the conftest docstring, CLAUDE.md, the README and the
vd-setup-backend skill describe the account-free setup, including
Pinecone Local's need for the pinecone SDK < 10.
…K 10 skip)

- pinecone: names whose '_' sits next to '-' (e.g. "a-_b") could be
  created but never reached again; reject any name that doesn't
  round-trip, and explain the '--' mapping in the not-found error.
  Server-free unit tests cover the mapping.
- tests: server probes now follow the VD_* connection overrides, and a
  non-local target is skipped unless VD_ALLOW_REMOTE_TESTS=1, since the
  client fixture deletes every collection it sees (a real Pinecone key or
  Qdrant Cloud URL would have been wiped).
- tests: the Pinecone Local entry skips with a clear reason on pinecone
  SDK >= 10 instead of failing.
- docs: milvus wording in CLAUDE.md; remote-test guard in tests/README.
Keyword-style or query-string pgvector DSNs, multi-host MongoDB URIs and
anything else without a parseable host now count as remote (skipped
unless VD_ALLOW_REMOTE_TESTS=1) instead of falling back to localhost.
The Pinecone SDK check reads pinecone.__version__ (works with the legacy
distribution too). Clearer ambiguous-name error in the pinecone adapter.
@thorwhalen thorwhalen changed the title WIP: backend clients in CI; account-free live tests for Pinecone, MongoDB Atlas, Qdrant server Backend clients in CI; account-free live tests for Pinecone, MongoDB Atlas and Qdrant server; 3 adapter fixes Sep 30, 2026
@thorwhalen
thorwhalen merged commit 986a59d into master Sep 30, 2026
12 checks passed
@thorwhalen
thorwhalen deleted the cloud-sweep-2026-09-26 branch September 30, 2026 06:42
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.

mongodb: searching a collection recreated under a dropped name hangs 120 s and fails

1 participant