Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions docs/indexes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ on fields ``_from`` and ``_to``. For more information on indexes, refer to
},
)

# Index creation may succeed even if vector training fails.
# Index creation may succeed even if there is insufficient training data.
if vector_index.training_state != "ready":
raise RuntimeError(
vector_index.error_message or "Vector index is not ready"
Expand All @@ -86,7 +86,10 @@ Omitted or scaling-object ``nLists``, ``numberOfDocsPerCentroid``, factory
placeholders such as ``IVF{},Flat``, and successful-but-unusable creation
behavior require ArangoDB 3.12.10 or later. A successful creation response
means that the index exists, but callers should check ``training_state`` before
using it. If training fails permanently, the state is ``"unusable"`` and
``error_message`` describes the failure.
using it. If there is insufficient data to train the index, the state is
``"unusable"`` and ``error_message`` describes the failure. Invalid index
definitions, such as an ``nLists`` value that disagrees with the number of
centroids in the factory string, are rejected during creation with
``IndexCreateError`` and no index is created.

See :class:`arangoasync.collection.StandardCollection` for API specification.
42 changes: 24 additions & 18 deletions tests/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,24 +337,6 @@ async def test_collection_index(doc_col, bad_col, cluster, db_version):
await doc_col.delete_index(default_index.id)
await doc_col.delete_index(scaling_index.id)

# A permanent training failure still creates an unusable index.
unusable_index = await doc_col.add_index(
"vector",
["embedding1"],
{
"name": "vector_index_unusable",
"params": {
"metric": "cosine",
"dimension": 128,
"nLists": 2,
"factory": "IVF3,Flat",
},
},
)
assert unusable_index.training_state == "unusable"
assert unusable_index.error_message
await doc_col.delete_index(unusable_index.id)

# Invalid requests continue to fail at the HTTP layer.
with pytest.raises(IndexCreateError) as err:
await doc_col.add_index(
Expand All @@ -378,6 +360,30 @@ async def test_collection_index(doc_col, bad_col, cluster, db_version):
assert await doc_col.delete_index(idx2.id, ignore_missing=True) is False


@pytest.mark.asyncio
async def test_unusable_vector_index(doc_col, db_version):
if db_version < version.parse("3.12.10"):
pytest.skip("Unusable vector index test requires ArangoDB 3.12.10+")

# One training vector is insufficient for two centroids.
await doc_col.insert({"embedding": [1.0, 1.0]})
index = await doc_col.add_index(
"vector",
["embedding"],
{
"name": "vector_index_unusable",
"params": {
"metric": "cosine",
"dimension": 2,
"nLists": 2,
},
},
)
assert index.training_state == "unusable"
assert index.error_message
await doc_col.delete_index(index.id)


@pytest.mark.asyncio
async def test_collection_truncate_count(docs, doc_col, bad_col):
# Test errors
Expand Down
9 changes: 9 additions & 0 deletions tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from arangoasync.errno import USER_NOT_FOUND
from arangoasync.exceptions import (
CollectionCreateError,
CollectionListError,
DocumentInsertError,
PermissionResetError,
PermissionUpdateError,
Expand Down Expand Up @@ -176,6 +177,14 @@ async def test_user_change_permissions(sys_db, arango_client, db):
with pytest.raises(PermissionResetError):
await db.reset_permission(username, db.name)
await sys_db.reset_permission(username, db.name)
assert await sys_db.permission(username, db.name) == "none"
# ArangoDB 4.0 returns 403 where earlier versions returned 401.
with pytest.raises(CollectionCreateError) as err:
await db2.create_collection(generate_col_name())
assert err.value.http_code in {401, 403}
with pytest.raises(CollectionListError) as err:
await db2.collections()
assert err.value.http_code in {401, 403}
with pytest.raises(DocumentInsertError):
await col.insert({"_key": "test"})

Expand Down
Loading