Skip to content

feat(config): add runtime property reindex support (Weaviate v1.39 GA API) - #2098

Open
g-despot wants to merge 12 commits into
mainfrom
feat/runtime-property-reindex
Open

feat(config): add runtime property reindex support (Weaviate v1.39 GA API)#2098
g-despot wants to merge 12 commits into
mainfrom
feat/runtime-property-reindex

Conversation

@g-despot

@g-despot g-despot commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Closes #2097

Adds client support for the Runtime Property Reindex GA API (Weaviate v1.39), per the RFC linked from #2097. The server side (weaviate/weaviate#12252) merged on 2026-07-22; CI runs against 1.39.0-rc.1.

New API (sync + async)

  • collection.config.update_property_index(property_name, index_name: InvertedIndexType, *, tokenization=None, algorithm=None, tenants=None, wait_for_completion=False): declarative upsert (create the index or migrate its config). Returns InvertedIndexTask (202 STARTED with task id, or 200 NO_OP); with wait_for_completion=True polls the status endpoint until the index reports ready and returns the final InvertedIndexStatus (raises ReindexFailedError / ReindexCanceledError on terminal failure). An identical re-submit while the task is in flight joins it: 202 STARTED with the existing task id.
  • collection.config.rebuild_property_index(property_name, index_name, *, tenants=None, wait_for_completion=False): same-config rebuild.
  • collection.config.cancel_property_index_task(property_name, index_name): cancels the in-flight reindex task on the index (CANCELLED or NO_OP, idempotent).
  • collection.config.get_property_indexes(): per-property, per-index status listing (CollectionInvertedIndexes), including migration progress, task ids, and in-flight target tokenization/algorithm.
  • delete_property_index keeps its v1.36 behavior; its index_name parameter is widened (backward-compatibly) to Union[InvertedIndexType, IndexName].

index_name on the new methods takes the new InvertedIndexType enum (SEARCHABLE, FILTERABLE, RANGE_FILTERS); only delete_property_index also accepts the v1.36 string literals. The client always sends canonical index type values (filterable, searchable, rangeFilters). tenants accepts a single tenant name or a list. All new methods are gated on server >= 1.39.0 and raise WeaviateUnsupportedFeatureError below that.

A tokenization change submitted via the searchable index also retokenizes an existing filterable index (one coupled task, shared task id on both status entries); this contract is stated explicitly in the docstrings.

Implementation notes

  • Executor pattern with regenerated sync/async stubs (tools/stubs_regen.sh); wait_for_completion overloads modeled on the export executor.
  • New read-side dataclasses (InvertedIndexTask, InvertedIndexStatus, PropertyInvertedIndexes, CollectionInvertedIndexes) and enums (InvertedIndexType, InvertedIndexState, InvertedIndexTaskStatus) exported via weaviate.classes.config / weaviate.outputs.config; new exceptions ReindexFailedError / ReindexCanceledError.
  • InvertedIndexTask.status is open-vocabulary (Union[InvertedIndexTaskStatus, str]): known values parse to the enum, unknown server values pass through as strings, matching the spec (the field has no enum there).
  • Read-side leniency: data_type on status entries stays str because the endpoint also lists reference properties, whose dataType is the qualified target collection name.

Testing

  • 86 mock tests: exact routes and bodies for all endpoints, enum vs literal route equality, 202 + task id and 200 NO_OP parsing, join semantics, cancel semantics, tenants encoding (including a bare-string regression test), version-gate errors, wait-path failed/cancelled raises, tolerant status parsing, and reference-property dataType handling.
  • Integration tests (sync + async, skipped below server 1.39): searchable lifecycle (create, wait ready, in-flight join, NO_OP re-put, rebuild, cancel, delete), rangeFilters creation, coupled tokenization change with shared task id, multi-tenant scoping.
  • Verified live against semitechnologies/weaviate:1.39.0-rc.1: all reindex integration tests pass. This PR also bumps the CI WEAVIATE_139 image from a stale pre-merge build to 1.39.0-rc.1.

Status

Draft until Weaviate 1.39.0 GA is released.

g-despot added 3 commits July 19, 2026 21:49
Adds collection.config methods for the GA runtime property reindex API:
- update_property_index: declarative create-or-migrate upsert (PUT
  /schema/{class}/properties/{prop}/index/{indexType}) with optional
  wait_for_completion polling of the index status endpoint
- rebuild_property_index: rebuild an existing index from scratch, with
  tenant selection and optional wait_for_completion
- cancel_property_index_task: idempotent cancellation of a live task
- get_property_indexes: parse GET /schema/{class}/indexes into new
  CollectionPropertyIndexes/PropertyIndexStatus read-side types

All methods raise WeaviateUnsupportedFeatureError below server 1.39.0.
Mock tests exercise the exact REST routes against a 1.39-advertising mock
server (upsert 202/NO_OP, rebuild, cancel CANCELLED/NO_OP, tenants csv
encoding, status parsing incl. coupled task entries) and assert
WeaviateUnsupportedFeatureError against a 1.36 mock. Integration tests
cover the searchable lifecycle, rangeFilters creation, coupled
tokenization changes, multi-tenant selection and the async client,
skipping below server 1.39.0.
- accept a bare string for the tenants argument of update_property_index
  and rebuild_property_index, normalizing it to a single-element list so
  it cannot be exploded into a per-character csv (export API precedent)
- override to_dict on _PropertyIndexes/_CollectionPropertyIndexes so the
  nested dataclass lists serialize to JSON-compatible dicts
  (_CollectionConfig precedent)
- drop the dead list branch for dataType in the index status parser
- cover the ReindexFailedError/ReindexCanceledError wait paths of both
  update and rebuild, pin the empty request body of the rebuild/cancel
  mocks, and prove json.dumps(...to_dict()) round-trips

@orca-security-eu orca-security-eu Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Orca Security Scan Summary

Status Check Issues by priority
Passed Passed Infrastructure as Code high 0   medium 0   low 0   info 0 View in Orca
Passed Passed SAST high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Secrets high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Vulnerabilities high 0   medium 0   low 0   info 0 View in Orca

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds client support for Weaviate v1.39’s Runtime Property Reindex GA API by introducing new collection-config methods (sync + async), output models, and errors, plus mock and integration test coverage for the new endpoints and wait/poll behavior.

Changes:

  • Add update_property_index, rebuild_property_index, cancel_property_index_task, and get_property_indexes to the collection config executor, including wait_for_completion polling and version gating (>= 1.39.0).
  • Introduce new output dataclasses/enums for property index tasks/status listings and export them via weaviate.outputs.config, plus new terminal exceptions for failed/canceled reindex tasks.
  • Add mock tests and integration tests covering routes/bodies, parsing, tenants encoding, version gating, and wait-path terminal failures.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
weaviate/outputs/config.py Re-exports new property-index output types for public consumption.
weaviate/exceptions.py Adds new exceptions for terminal reindex outcomes (failed/canceled).
weaviate/collections/config/sync.pyi Adds typed sync stubs for the new property-index config methods (incl. overloads).
weaviate/collections/config/async_.pyi Adds typed async stubs for the new property-index config methods (incl. overloads).
weaviate/collections/config/executor.py Implements the new runtime property index endpoints + polling logic + version gating.
weaviate/collections/classes/config.py Adds enums/dataclasses representing property-index task and status payloads.
weaviate/collections/classes/config_methods.py Adds JSON->dataclass parsing helpers for the new property-index responses.
mock_tests/test_property_reindex.py Adds mock tests for request/response shapes, tenants encoding, version gating, and wait-path errors.
integration/test_collection_config.py Adds integration tests for the searchable/rangeFilters lifecycle and async variants (skipping <1.39).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread weaviate/collections/config/executor.py
Comment thread weaviate/collections/config/executor.py
@codecov-commenter

codecov-commenter commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.51553% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.49%. Comparing base (95b5d76) to head (de8c7be).
⚠️ Report is 31 commits behind head on main.

Files with missing lines Patch % Lines
integration/test_collection_config.py 92.47% 7 Missing ⚠️
weaviate/collections/config/executor.py 95.86% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2098      +/-   ##
==========================================
+ Coverage   86.64%   88.49%   +1.85%     
==========================================
  Files         300      303       +3     
  Lines       23172    23756     +584     
==========================================
+ Hits        20077    21024     +947     
+ Misses       3095     2732     -363     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Validate the tenants argument of update_property_index and
rebuild_property_index as str | List[str] | None before the csv join so
invalid input raises WeaviateInvalidInputError instead of a raw
TypeError, matching the library's _validate_input idiom already applied
to property_name/index_name. Document the WeaviateInvalidInputError in
the affected docstrings and cover the validation with mock tests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comment thread weaviate/collections/classes/config.py
Comment thread weaviate/collections/classes/config_methods.py
g-despot added 6 commits July 21, 2026 09:31
The static delete_property_index error prefix asserted a single cause
("Property may not exist") but the DELETE 422 also covers an invalid
index type and the in-flight-reindex mutation guard, whose server
message the prefix contradicted. Name the failed operation instead and
let the appended response body carry the cause, matching the file's
phrasing style. Pin the behavior with a mock test surfacing a
server-style 422 in-flight-reindex message.
Adds a PropertyIndexType str-enum (SEARCHABLE, FILTERABLE,
RANGE_FILTERS) accepted alongside the IndexName literals on
update_property_index, rebuild_property_index,
cancel_property_index_task and delete_property_index (backward-
compatible widening of the v1.36 signature). The value is normalized to
its wire form at the top of each method so paths, params and error
messages never render the enum repr. Route-equality mock tests pin that
the enum and literal forms hit identical routes, incl. RANGE_FILTERS ->
rangeFilters. Read-side status types keep plain literals/str for
forward compatibility.
Documents on update_property_index that a tokenization change via the
searchable index also retokenizes an existing filterable index as one
coupled task (shared taskId) and thereby changes filter matching, with
filterable as the target for bucket-only changes and cancellation
applying to the whole task. Explains why PropertyIndexes.data_type is a
plain str (primitives match the DataType enum, references carry the
target collection name) and pins reference-property parsing with a mock
test.
The RANGE_FILTERS docstring said "rangeable", the internal write-path
alias the RFC deliberately keeps unsurfaced — say rangeFilters instead.
Extends the route-equality parametrization with FILTERABLE and adds
enum-vs-literal route cases for rebuild_property_index and
cancel_property_index_task.
Renames the unreleased public types PropertyIndexType/State/Status/
Task/TaskStatus to InvertedIndexType/State/Status/Task/TaskStatus and
PropertyIndexes/CollectionPropertyIndexes to PropertyInvertedIndexes/
CollectionInvertedIndexes, incl. private counterparts and parser names.
The runtime reindex API only ever touches inverted indexes; a future
vector reindex must not collide with these names. Method names, the
released IndexName alias and the deliberately generic Reindex*Error
exceptions are unchanged.
Tightens index_name to InvertedIndexType only on update_property_index,
rebuild_property_index and cancel_property_index_task (all overloads
and impls); delete_property_index keeps accepting the IndexName
literals as released v1.36 API. Runtime leniency is preserved — the
value is still normalized and validated as a str, so raw strings keep
working and keep hitting the same routes (pinned by the literal legs of
the route-equality mock tests, which sit outside the pyright scope).
g-despot added 2 commits July 29, 2026 10:49
The CI pin 1.39.0-rc.0-b41225e was a stale mid-review build of core
#12252 that emitted an IN_PROGRESS task status which never shipped; pin
1.39.0-rc.1 instead. Parse the task status tolerantly — known values
map to InvertedIndexTaskStatus, unknown values pass through as plain
strings, since the spec declares the field an open-vocabulary string —
and pin that with a mock test. Upgrade the coupled-tokenization test to
the final join contract: an identical re-PUT while the task is in
flight returns 202 with the existing taskId and STARTED, verified live
against 1.39.0-rc.1 (post-completion re-PUT stays 200 NO_OP).
@g-despot
g-despot requested a review from Copilot July 29, 2026 12:20
@g-despot
g-despot marked this pull request as ready for review July 29, 2026 12:20
@g-despot
g-despot requested a review from a team as a code owner July 29, 2026 12:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (8)

weaviate/collections/config/sync.pyi:125

  • rebuild_property_index is currently typed to only accept InvertedIndexType, but the runtime accepts the canonical IndexName literals too. Widen index_name to Union[InvertedIndexType, IndexName] for both overloads to match the supported API surface.
    def rebuild_property_index(
        self,
        property_name: str,
        index_name: InvertedIndexType,
        *,

weaviate/collections/config/async_.pyi:127

  • rebuild_property_index is currently typed to only accept InvertedIndexType, but the runtime accepts canonical IndexName literals too. Widen index_name to Union[InvertedIndexType, IndexName] for both overloads to match the supported API surface.
    async def rebuild_property_index(
        self,
        property_name: str,
        index_name: InvertedIndexType,
        *,

weaviate/collections/config/async_.pyi:142

  • cancel_property_index_task is currently typed to only accept InvertedIndexType, but the runtime accepts canonical IndexName literals as well. Widen index_name to Union[InvertedIndexType, IndexName] to match runtime behavior and avoid forcing # type: ignore at call sites.
    async def cancel_property_index_task(
        self, property_name: str, index_name: InvertedIndexType
    ) -> InvertedIndexTask: ...

weaviate/collections/config/sync.pyi:140

  • cancel_property_index_task is currently typed to only accept InvertedIndexType, but the runtime accepts canonical IndexName literals as well. Widen index_name to Union[InvertedIndexType, IndexName] to match the supported API and avoid # type: ignore at call sites.
    def cancel_property_index_task(
        self, property_name: str, index_name: InvertedIndexType
    ) -> InvertedIndexTask: ...

weaviate/collections/config/executor.py:781

  • update_property_index/rebuild_property_index/cancel_property_index_task accept IndexName literals at runtime (see the else index_name cast), but the public type signature here restricts index_name to InvertedIndexType. This forces callers using the canonical string literals (e.g. "searchable") to use # type: ignore, and is inconsistent with delete_property_index, which already advertises Union[InvertedIndexType, IndexName]. Consider widening these signatures (and their overloads + the .pyi stubs) to Union[InvertedIndexType, IndexName] so the declared API matches the supported runtime behavior.
    def update_property_index(
        self,
        property_name: str,
        index_name: InvertedIndexType,
        *,

weaviate/collections/config/sync.pyi:119

  • update_property_index is currently typed to only accept InvertedIndexType, but the API is also invoked throughout the repo with canonical IndexName literals (e.g. "searchable"). Align the stub with delete_property_index and the runtime behavior by allowing Union[InvertedIndexType, IndexName] for index_name in both overloads.

This issue also appears in the following locations of the same file:

  • line 121
  • line 138
    def update_property_index(
        self,
        property_name: str,
        index_name: InvertedIndexType,
        *,

weaviate/collections/config/async_.pyi:121

  • update_property_index is currently typed to only accept InvertedIndexType, but the API is also used with canonical IndexName literals (e.g. "searchable"). Align the async stub with delete_property_index and the runtime behavior by allowing Union[InvertedIndexType, IndexName] for index_name in both overloads.

This issue also appears in the following locations of the same file:

  • line 123
  • line 140
    async def update_property_index(
        self,
        property_name: str,
        index_name: InvertedIndexType,
        *,

weaviate/outputs/config.py:10

  • The PR description and the implemented/exported naming don’t match: the description refers to PropertyIndexTask/PropertyIndexStatus/CollectionPropertyIndexes, but this PR exports InvertedIndexTask/InvertedIndexStatus/CollectionInvertedIndexes (and the executor/stubs/tests use those names). Please update the PR description (and any user-facing docs/release notes) to reflect the actual public API names, or rename consistently if the PropertyIndex* naming is still intended.
    CollectionInvertedIndexes,
    GenerativeConfig,
    GenerativeSearches,
    InvertedIndexConfig,
    InvertedIndexState,

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.

Add support for Runtime Property Reindex

3 participants