feat: pristine harness JSON interfaces and require-existing semantic mode (P2)
This commit is contained in:
@@ -39,6 +39,7 @@ class FakeQdrantHttp:
|
||||
self.malformed_query = False
|
||||
self.malformed_scroll = False
|
||||
self.scroll_pages: list[dict] | None = None
|
||||
self.drop_collection_on_points = False
|
||||
|
||||
def request(self, method, url, *, json=None, timeout=None):
|
||||
self.calls.append((method, url, json))
|
||||
@@ -75,6 +76,9 @@ class FakeQdrantHttp:
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
|
||||
if method == "PUT" and path == "/collections/workspace-semantic/points":
|
||||
if self.drop_collection_on_points:
|
||||
self.collection = None
|
||||
return FakeResponse(404, {"status": "error"})
|
||||
for point in json["points"]:
|
||||
self.points[point["id"]] = point
|
||||
return FakeResponse(200, {"result": {"status": "acknowledged"}})
|
||||
@@ -161,13 +165,16 @@ def _write_record(record_id: str, kind: str, *, metadata=None):
|
||||
)
|
||||
|
||||
|
||||
def _store(fake: FakeQdrantHttp) -> QdrantVectorStore:
|
||||
def _store(
|
||||
fake: FakeQdrantHttp, *, collection_lifecycle: str = "self_heal"
|
||||
) -> QdrantVectorStore:
|
||||
return QdrantVectorStore(
|
||||
base_url="http://qdrant:6333",
|
||||
collection="workspace-semantic",
|
||||
workspace_id="demo",
|
||||
workspace_revision="a" * 40,
|
||||
expected_dimension=1024,
|
||||
collection_lifecycle=collection_lifecycle,
|
||||
request=fake.request,
|
||||
)
|
||||
|
||||
@@ -212,6 +219,87 @@ def test_upsert_refuses_collection_dimension_or_distance_mismatch_without_recrea
|
||||
assert creates == []
|
||||
|
||||
|
||||
def test_upsert_require_existing_refuses_missing_collection_without_creating():
|
||||
fake = FakeQdrantHttp()
|
||||
store = _store(fake, collection_lifecycle="require_existing")
|
||||
|
||||
with pytest.raises(VectorStoreError, match="semantic_index_incompatible"):
|
||||
store.upsert("memory", [_write_record("memory:1", "memory")])
|
||||
|
||||
assert fake.collection is None
|
||||
creates = [
|
||||
call
|
||||
for call in fake.calls
|
||||
if call[0] == "PUT" and call[1].endswith("/collections/workspace-semantic")
|
||||
]
|
||||
assert creates == []
|
||||
|
||||
|
||||
def test_upsert_require_existing_refuses_incompatible_collection_without_mutating():
|
||||
fake = FakeQdrantHttp(dimension=384, distance="Dot")
|
||||
fake.collection = {"vectors": {"size": 384, "distance": "Dot"}}
|
||||
store = _store(fake, collection_lifecycle="require_existing")
|
||||
|
||||
with pytest.raises(VectorStoreError, match="semantic_index_incompatible"):
|
||||
store.upsert("memory", [_write_record("memory:1", "memory")])
|
||||
|
||||
assert fake.payload_indexes == set()
|
||||
mutating = [call for call in fake.calls if call[0] == "PUT"]
|
||||
assert mutating == []
|
||||
|
||||
|
||||
def test_upsert_require_existing_writes_to_existing_compatible_collection():
|
||||
fake = FakeQdrantHttp()
|
||||
fake.collection = {"vectors": {"size": 1024, "distance": "Cosine"}}
|
||||
fake.payload_indexes = {
|
||||
"content_hash",
|
||||
"document_id",
|
||||
"kind",
|
||||
"record_key",
|
||||
"record_kind",
|
||||
"vector_generation",
|
||||
"workspace_id",
|
||||
"workspace_revision",
|
||||
}
|
||||
store = _store(fake, collection_lifecycle="require_existing")
|
||||
|
||||
assert store.upsert("memory", [_write_record("memory:1", "memory")]) == 1
|
||||
|
||||
create_or_index = [
|
||||
call
|
||||
for call in fake.calls
|
||||
if call[0] == "PUT" and not call[1].endswith("/points?wait=true")
|
||||
]
|
||||
assert create_or_index == []
|
||||
|
||||
|
||||
def test_upsert_require_existing_fails_if_collection_disappears_after_preflight():
|
||||
fake = FakeQdrantHttp()
|
||||
fake.collection = {"vectors": {"size": 1024, "distance": "Cosine"}}
|
||||
fake.payload_indexes = {
|
||||
"content_hash",
|
||||
"document_id",
|
||||
"kind",
|
||||
"record_key",
|
||||
"record_kind",
|
||||
"vector_generation",
|
||||
"workspace_id",
|
||||
"workspace_revision",
|
||||
}
|
||||
fake.drop_collection_on_points = True
|
||||
store = _store(fake, collection_lifecycle="require_existing")
|
||||
|
||||
with pytest.raises(VectorStoreError, match="HTTP 404"):
|
||||
store.upsert("memory", [_write_record("memory:1", "memory")])
|
||||
|
||||
creates = [
|
||||
call
|
||||
for call in fake.calls
|
||||
if call[0] == "PUT" and call[1].endswith("/collections/workspace-semantic")
|
||||
]
|
||||
assert creates == []
|
||||
|
||||
|
||||
def test_health_fails_when_the_bound_collection_is_missing():
|
||||
fake = FakeQdrantHttp()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user