diff --git a/docs/indexes.rst b/docs/indexes.rst index 5b2ed9d..623d496 100644 --- a/docs/indexes.rst +++ b/docs/indexes.rst @@ -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" @@ -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. diff --git a/tests/test_collection.py b/tests/test_collection.py index bf124d6..0fc9fd4 100644 --- a/tests/test_collection.py +++ b/tests/test_collection.py @@ -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( @@ -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 diff --git a/tests/test_user.py b/tests/test_user.py index 4724927..e3cd2cb 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -4,6 +4,7 @@ from arangoasync.errno import USER_NOT_FOUND from arangoasync.exceptions import ( CollectionCreateError, + CollectionListError, DocumentInsertError, PermissionResetError, PermissionUpdateError, @@ -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"})