Fix O(collection) client-side scans and missing payload indexes on the qdrant network backend - #2043
Conversation
|
For reviewers — where this fits with the existing server-side aggregation work:
All new fast paths are gated on |
b392205 to
e6b1b0a
Compare
|
Rebased onto current Could a maintainer approve the workflow run? No checks have ever reported on this branch — as a fork PR the Actions run needs approval, so |
e6b1b0a to
0a6bdad
Compare
|
Rebased onto current Conflict resolution (one hunk,
Net effect on ChromaDB is still nil: the preflight runs first exactly as on Also addressed the helper duplication I flagged in the description. Also fixed a missing blank line in Verification — I got a clean dev environment this time, so the suite I couldn't run before now has results:
Diff is now 189+/25− across 7 files (was 184+/18− across 4), in two commits.
|
…rant
Setting up a shared palace across machines on the qdrant network backend
surfaces several operations that assume cheap local ChromaDB reads and
instead scan the whole collection client-side, or rely on payload indexes
that are never created. On a large shared collection these hang or fail.
- qdrant: create keyword payload indexes on metadata.wing/room/source_file
when ensuring the collection (idempotent, backfills existing collections),
so facet_counts() no longer 400s ("No appropriate index for faceting") and
metadata-filtered reads use an index instead of a full scan.
- qdrant: write the local marker when a populated collection is opened for
write, not only on first upsert, so a read-first client can search/status a
shared palace it hasn't written to yet.
- hallways.compute_hallways_for_wing: use a server-side where={"wing": wing}
filter on facet-capable backends (bounded to the wing) instead of scanning
the whole collection and filtering client-side on every mine. ChromaDB
keeps the client-side scan (its where binds one SQL var per matched id and
overflows on >32k wings, MemPalace#1619).
- miner.status: count wing/room via facet_counts on facet-capable backends
instead of streaming every drawer's metadata (mirrors the MCP status tool).
- palace.prefetch_mined_set: on facet-capable backends, resolve skip checks
with lazy, cached, indexed per-source_file lookups (scoped to the files
being mined) instead of one full-collection scan that hangs every
convo-mode mine (auto-save hooks).
All new paths are gated on the backend's supports_metadata_facets capability
and fall back to the existing local-optimized path, so ChromaDB is unchanged.
Fixes MemPalace#2042
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H32fWQrjdZWPNhfY1gzCgH
Replaces the three inline _backend_supports_facets copies added by this branch with a single collection_supports_facets() in backends/base.py, re-exported from the backends package. mcp_server keeps its module-level _supports_metadata_facets name (now a thin delegate) so its call sites stay monkeypatchable per-module. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0a6bdad to
f26f5ba
Compare
|
Rebased onto current Conflicts (two hunks)
Follow-on fix while resolving: Verification (rebased branch vs.
The 4 failures are all in Diff is 206+/25− across 7 files. Still no Actions run has ever executed on this fork branch — a maintainer approving the workflow would give you real CI signal. |
|
Any chance for a review and incorporation into your next release? I've been running this on my cluster of 5 machines for over a month now with no issues. Significantly speeds up use of MemPalace when used across more than one machine. |
What & why
Fixes #2042. Setting up a shared palace across multiple machines on the qdrant network backend surfaces several operations that assume cheap local ChromaDB reads and instead do O(collection) client-side scans, or rely on payload indexes that are never created. On a shared collection of ~184k drawers these hang (mine,
status, auto-save hooks) or fail (facetstatus400s), which makes the network-backend / team setup impractical at scale.Changes
All new paths are gated on the backend's
supports_metadata_facetscapability and fall back to the existing local-optimized path, so ChromaDB behavior is unchanged._ensure_remote_collectionnow creates keyword indexes onmetadata.wing,metadata.room,metadata.source_file(idempotent via the existing 400/409-swallowingcreate_payload_index, and backfills already-existing collections). Fixesfacet_counts()HTTP 400 "No appropriate index for faceting"(which the MCPmempalace_statustool hits) and lets metadata-filtered reads use an index.qdrant_backend.jsonwhen a populated collection is opened for write, not only on first upsert, so a read-first client cansearch/statusa shared palace it hasn't written to yet.hallways.compute_hallways_for_wing— server-sidewhere={"wing": wing}fetch on facet-capable backends instead of scanning the whole collection and filtering client-side on every mine. Chroma keeps the client-side scan (itswherebinds one SQL var per matched id, overflowing on >32k wings, compute_hallways_for_wing crashes (too many SQL variables) on wings > ~32k drawers #1619).miner.status— count wing/room viafacet_countson facet-capable backends instead of streaming every drawer's metadata (mirrors the MCP status tool).palace.prefetch_mined_set— on facet-capable backends, resolve skip checks with lazy, cached, indexed per-source_filelookups scoped to the files being mined, instead of one full-collection scan that hangs every convo-mode mine (auto-save hooks).Testing
py_compile+ import of all four changed modules pass.pytestsuite in my environment (dev deps unavailable in the packaged tool venv) — CI should exercise it.statusand convo-mode mine hung for minutes; facetstatus400'd. After:status~0.5s, project mine ~1.2s, convo-mine ~0.5s, facets fast.Happy to adjust naming/placement (e.g. hoist the small
_backend_supports_facetshelper intobackends/base.pyrather than the three inline copies) to match project conventions.🤖 Generated with Claude Code
https://claude.ai/code/session_01H32fWQrjdZWPNhfY1gzCgH