Commit Graph
74 Commits
Author SHA1 Message Date
Daniel BorosandLuis Cossío c02ad2b3e0 feat: ReadOnlySegment::open (S3-verified) (#9466)
* feat: ReadOnlyStructPayloadIndex::open

* use expect instead of allow

* fix: review comments

* fix: read immutable dense vector count through fs

* feat: ReadOnlySegment::open + read-only segment over S3 test

* fix: linter

* rename + TODO

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-08-04 11:16:52 +02:00
Daniel BorosandLuis Cossío e31b6d1e0d feat: ReadOnlyStructPayloadIndex::open (#9465)
* feat: ReadOnlyStructPayloadIndex::open

* use expect instead of allow

* fix: review comments

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-08-04 11:16:52 +02:00
Daniel BorosandLuis Cossío 08634d0b6d fix: enable disk cache over a network (S3) remote (#9467)
* fix: disk cache maps logical (non-local) remote paths

* feat: derive Clone for BlobFile

* nits

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-08-04 11:16:52 +02:00
Daniel Boros 5048149be9 fix: read-only on-disk field index opens are non-writeable (#9468) 2026-08-04 11:16:52 +02:00
Daniel Boros f126b89d3c fix: BlobFs::list_files honors byte-prefix contract (#9464) 2026-08-04 11:16:52 +02:00
Daniel Boros baf9b4ae2f refactor: explicit index-type arms for Turbo4 in read-only open (#9479) 2026-08-04 11:16:51 +02:00
cc8d5d25fa feat: add open for read-only sparse vector index (#9435)
* feat: add open for read-only sparse vector index + enum sparse dispatcher

* fix: universal-IO loads for read-only sparse index open

* refactor: rename load_via/open_via to load_universal/open_universal

* refactor: drop StorageVersion::load in favor of load_universal

The regular-IO `load` duplicated `load_universal` over plain `File` IO.
Remove it and route all callers through `load_universal(&MmapFs, ..)`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(sparse): decouple inverted index from concrete storage; split segment_constructor_base (#9461)

Make the read-only index enum generic over storage `S` (no concrete MmapFile),
and remove construction callbacks from the sparse index open paths.

- InvertedIndex is now a pure read/search trait: `open`/`from_ram_index`/
  `type Fs` moved off the trait to inherent methods on each concrete index
  type, so construction no longer requires `S::Fs: Default`.
- SparseVectorIndex open split into a generic `plan` (load-vs-build decision +
  RAM-index build) and generic `finish` (assembly); callers do the concrete
  per-type construction, so no construction callbacks are needed.
- ReadOnlySparseVectorIndex::open takes the already-constructed inverted index
  and caller-loaded config instead of a `load_inverted_index` callback.
- VectorIndexReadEnum is generic over `S: UniversalRead`; sparse mmap variants
  hold `InvertedIndexCompressedMmap<_, S>` rather than a concrete `MmapFile`.
- Split the 1182-line segment_constructor_base.rs into a module (paths,
  vector_storage, payload_storage, id_tracker, vector_index,
  sparse_vector_index, create_segment, segment, legacy_state); the sparse
  dispatcher's match arms collapse into three per-family helpers.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* feat: LiveReload (no-op) dispatch for read-only vector index enum (#9436)

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 11:16:51 +02:00
Daniel BorosandLuis Cossío 35c17c8fa0 feat: live_reload for read-only immutable id tracker + enum dispatch (#9434)
* feat: live_reload for read-only immutable id tracker + enum dispatch

* deleted should be already sorted

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-08-04 11:16:51 +02:00
Daniel BorosandLuis Cossío 10e91166cf feat: add VectorIndexReadEnum open dispatcher (#9428)
* feat: add VectorIndexReadEnum open dispatcher

* review nit

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-08-04 11:16:51 +02:00
17958c9cad feat: add open to read-only HNSW index (#9427)
* feat: add open to read-only HNSW index

* fix: dedicated universal-IO load for read-only graph

* fix: report actual graph residency in read-only is_on_disk

* refactor: rename load_via to load_universal

* refactor: unify graph links loading on universal IO

Replace the dual GraphLinks load paths (regular mmap + universal IO) with a
single universal-IO loader, and the `Mmap` GraphLinksEnum variant with a
`Universal` variant that keeps a type-erased `UniversalRead` handle alive
behind `Box<dyn GraphLinksStorage>` (UniversalRead is not object-safe).

- GraphLinksEnum::from_storage picks the variant from UniversalKind:
  borrowable (mmap-backed) kinds stay `Universal`, others are materialized
  into `Ram`, so the borrowability invariant in GraphLinksStorage::bytes
  holds by construction.
- Loading takes a `Populate` parameter, derived from `hnsw_config.on_disk`:
  on_disk -> Populate::No (lazy), otherwise Populate::Blocking.
- is_on_disk is reported from config again instead of the enum variant.
- Split graph_links.rs into a graph_links/ module (format, vectors, storage,
  links, tests) with a relationship diagram in mod.rs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: drop LoadOption in favor of a Populate parameter

After unifying the link load paths on universal IO, LoadOption only encoded a
populate choice with a fs that was always MmapFs. Replace it with a `Populate`
argument to GraphLayers::load, removing the enum, its constructors, the
load_links helper, and the unused generic backend.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 11:16:51 +02:00
Daniel Boros 14b68ca2a5 feat: read-only immutable id tracker open + enum open dispatcher (#9433) 2026-08-04 11:16:51 +02:00
Daniel Boros 7eb6194f8f feat: add open to read-only plain vector index (#9426) 2026-08-04 11:16:51 +02:00
Daniel Boros 7ead47675f feat: read-only sparse vector index for VectorIndexReadEnum (#9406)
* feat: read-only sparse vector index for VectorIndexReadEnum

* fix: review comments
2026-08-04 11:16:50 +02:00
Daniel Boros eb91244daa feat: add live-reload for immutable dense vector (#9392) 2026-08-04 11:16:50 +02:00
4d446ff46e feat: live_reload for read-only quantized vectors (#9375)
* feat: live_reload for read-only quantized vectors

* Propagate live_reload params through quantized chunked storage

Thread fs, deleted_points, new_points and hw_counter through the full
quantized live_reload chain instead of synthesizing empty deltas and a
disposable hardware counter at the leaf storages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: use LiveReload trait in chunked mmap

* fix: use LiveReload trait

* fix: compiler errors

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 11:16:50 +02:00
Daniel Boros a7038cc7ad feat: live_reload dispatch for VectorStorageReadEnum (#9344)
* feat: live_reload for read-only sparse vector storage

* fix: pass multi_vector_config in multi read-only live_reload test

* feat: live_reload dispatch for VectorStorageReadEnum
2026-08-04 11:16:50 +02:00
Daniel Boros 65114be97e feat: live_reload for read-only sparse vector storage (#9343)
* feat: live_reload for read-only sparse vector storage

* fix: pass multi_vector_config in multi read-only live_reload test
2026-08-04 11:16:50 +02:00
ee8d41b154 feat: live_reload for read-only chunked vector storage (#9342)
* feat: live_reload for ChunkedVectorsRead

* feat: live_reload for read-only chunked dense/multi storage

* fix: full reread

* fix: linter

* refactor: chunked vectors live_reload as trait impl

* refactor: route chunked-vectors reads through the Fs backend

Use the `fs: &S::Fs` argument for filesystem access in the read-only
chunked-vectors path instead of going through `fs_err` (direct local FS),
so non-local backends are addressed correctly:

- `read_chunks_from`: list chunk files via `Fs::list_files` with the
  `chunk_` prefix instead of `fs_err::read_dir` over the whole directory,
  avoiding enumeration of unrelated files.
- `read_status_len`: read the status file via `read_whole_via(fs, ...)`
  instead of `fs_err::read`; thread `fs` through its `open`/`live_reload`
  call sites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fmt

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 11:16:49 +02:00
Daniel Boros f406305289 refactor: split read-only vector storage modules (#9379) 2026-08-04 11:16:48 +02:00
Daniel Boros 8bd997e62a feat: open dispatcher for VectorStorageReadEnum (#9337)
* feat: read-only open for ReadOnlyChunkedDenseVectorStorage

Add ReadOnlyChunkedDenseVectorStorage::open, the read-only counterpart of
open_appendable_memmap_vector_storage_impl: open the chunked vectors/
directory via ChunkedVectorsRead::open and materialize the deleted/ flags
into an owned bitvec via DynamicStoredFlags::load_bitvec, threading every
file open through the UniversalRead backend without writing anything.

Share the vectors/ and deleted/ directory names with the writable storage
by exposing them pub(crate).

Covered by a round-trip test: write and delete through the writable
storage, reopen read-only, and assert vectors, deletions and counts match.

Part of the read-only vector-storage open constructors (#9241).

* feat: read-only open for ReadOnlyChunkedMultiDenseVectorStorage

Add ReadOnlyChunkedMultiDenseVectorStorage::open, the read-only counterpart
of open_appendable_memmap_multi_vector_storage_impl: open the chunked
vectors/ and offsets/ directories via ChunkedVectorsRead::open and
materialize the deleted/ flags into an owned bitvec via
DynamicStoredFlags::load_bitvec, threading every file open through the
UniversalRead backend without writing anything.

Share the vectors/, offsets/ and deleted/ directory names with the writable
storage by exposing them pub(crate).

Covered by a round-trip test: write and delete multivectors through the
writable storage, reopen read-only, and assert per-point multivector
contents, deletions and counts match.

Part of the read-only vector-storage open constructors (#9241).

* feat: read-only open for ReadOnlySparseVectorStorage

Add ReadOnlySparseVectorStorage::open, the read-only counterpart of
MmapSparseVectorStorage::open: open the Gridstore store/ directory via
GridstoreReader::open and materialize the deleted/ flags into an owned
bitvec via DynamicStoredFlags::load_bitvec, threading every file open
through the UniversalRead backend without writing anything.
next_point_offset is reconstructed the same way the writable storage does
on reopen (highest deleted id or the Gridstore pointer count).

Share the store/ and deleted/ directory names with the writable storage by
exposing them pub(crate).

Covered by a round-trip test: write and delete sparse vectors through the
writable storage, reopen read-only, and assert live contents, deletions and
the reconstructed point count match.

Part of the read-only vector-storage open constructors (#9241).

* feat: open dispatcher for VectorStorageReadEnum

Add VectorStorageReadEnum::open, the read-only counterpart of
open_vector_storage: route a VectorDataConfig to the matching read-only
variant. The storage type selects the on-disk layout (mmap -> immutable
DenseVectorStorageImpl, chunked-mmap -> appendable chunked storage), the
datatype selects the element type, and a multivector config routes to the
chunked multi-dense storage (mmap multivectors are appendable-only).
advice/populate are derived from the storage type exactly as the writable
path does.

Expose open_dense_vector_storage_impl as pub(crate) so the dispatcher can
build the immutable Dense* variants. Sparse storage keeps its own
ReadOnlySparseVectorStorage::open and is wrapped at the call site.

Covered by tests asserting each config routes to the expected variant and
round-trips.

Part of the read-only vector-storage open constructors (#9241).
2026-08-04 11:16:48 +02:00
Daniel Boros 845ea36253 feat: implement LiveReload for null index (#9300)
* fix: false values update

* fix: linter

* fix: ci/cd

* chore: add comment

* fix: reopen and update trues_count and falses_count

* feat: implement LiveReload for null index

Reload the null index incrementally through the roaring-flags LiveReload trait: reopen the has_values/is_null bitslices and re-read only the changed points, then grow total_point_count, instead of re-materializing both bitmaps via a full open.

* chore: trigger ci
2026-08-04 11:16:48 +02:00
Daniel Boros e1fb578aa1 feat: read-only open for ReadOnlySparseVectorStorage (#9336)
* feat: read-only open for ReadOnlyChunkedDenseVectorStorage

Add ReadOnlyChunkedDenseVectorStorage::open, the read-only counterpart of
open_appendable_memmap_vector_storage_impl: open the chunked vectors/
directory via ChunkedVectorsRead::open and materialize the deleted/ flags
into an owned bitvec via DynamicStoredFlags::load_bitvec, threading every
file open through the UniversalRead backend without writing anything.

Share the vectors/ and deleted/ directory names with the writable storage
by exposing them pub(crate).

Covered by a round-trip test: write and delete through the writable
storage, reopen read-only, and assert vectors, deletions and counts match.

Part of the read-only vector-storage open constructors (#9241).

* feat: read-only open for ReadOnlyChunkedMultiDenseVectorStorage

Add ReadOnlyChunkedMultiDenseVectorStorage::open, the read-only counterpart
of open_appendable_memmap_multi_vector_storage_impl: open the chunked
vectors/ and offsets/ directories via ChunkedVectorsRead::open and
materialize the deleted/ flags into an owned bitvec via
DynamicStoredFlags::load_bitvec, threading every file open through the
UniversalRead backend without writing anything.

Share the vectors/, offsets/ and deleted/ directory names with the writable
storage by exposing them pub(crate).

Covered by a round-trip test: write and delete multivectors through the
writable storage, reopen read-only, and assert per-point multivector
contents, deletions and counts match.

Part of the read-only vector-storage open constructors (#9241).

* feat: read-only open for ReadOnlySparseVectorStorage

Add ReadOnlySparseVectorStorage::open, the read-only counterpart of
MmapSparseVectorStorage::open: open the Gridstore store/ directory via
GridstoreReader::open and materialize the deleted/ flags into an owned
bitvec via DynamicStoredFlags::load_bitvec, threading every file open
through the UniversalRead backend without writing anything.
next_point_offset is reconstructed the same way the writable storage does
on reopen (highest deleted id or the Gridstore pointer count).

Share the store/ and deleted/ directory names with the writable storage by
exposing them pub(crate).

Covered by a round-trip test: write and delete sparse vectors through the
writable storage, reopen read-only, and assert live contents, deletions and
the reconstructed point count match.

Part of the read-only vector-storage open constructors (#9241).
2026-08-04 11:16:48 +02:00
Daniel Boros ead9dc4cef feat: read-only open for ReadOnlyChunkedMultiDenseVectorStorage (#9335)
* feat: read-only open for ReadOnlyChunkedDenseVectorStorage

Add ReadOnlyChunkedDenseVectorStorage::open, the read-only counterpart of
open_appendable_memmap_vector_storage_impl: open the chunked vectors/
directory via ChunkedVectorsRead::open and materialize the deleted/ flags
into an owned bitvec via DynamicStoredFlags::load_bitvec, threading every
file open through the UniversalRead backend without writing anything.

Share the vectors/ and deleted/ directory names with the writable storage
by exposing them pub(crate).

Covered by a round-trip test: write and delete through the writable
storage, reopen read-only, and assert vectors, deletions and counts match.

Part of the read-only vector-storage open constructors (#9241).

* feat: read-only open for ReadOnlyChunkedMultiDenseVectorStorage

Add ReadOnlyChunkedMultiDenseVectorStorage::open, the read-only counterpart
of open_appendable_memmap_multi_vector_storage_impl: open the chunked
vectors/ and offsets/ directories via ChunkedVectorsRead::open and
materialize the deleted/ flags into an owned bitvec via
DynamicStoredFlags::load_bitvec, threading every file open through the
UniversalRead backend without writing anything.

Share the vectors/, offsets/ and deleted/ directory names with the writable
storage by exposing them pub(crate).

Covered by a round-trip test: write and delete multivectors through the
writable storage, reopen read-only, and assert per-point multivector
contents, deletions and counts match.

Part of the read-only vector-storage open constructors (#9241).
2026-08-04 11:16:48 +02:00
Daniel Boros c3315154b1 feat: read-only open for ReadOnlyChunkedDenseVectorStorage (#9334)
Add ReadOnlyChunkedDenseVectorStorage::open, the read-only counterpart of
open_appendable_memmap_vector_storage_impl: open the chunked vectors/
directory via ChunkedVectorsRead::open and materialize the deleted/ flags
into an owned bitvec via DynamicStoredFlags::load_bitvec, threading every
file open through the UniversalRead backend without writing anything.

Share the vectors/ and deleted/ directory names with the writable storage
by exposing them pub(crate).

Covered by a round-trip test: write and delete through the writable
storage, reopen read-only, and assert vectors, deletions and counts match.

Part of the read-only vector-storage open constructors (#9241).
2026-08-04 11:16:48 +02:00
Daniel Boros e0a1548fdb feat: add in-memory bitvec flags (#9333) 2026-08-04 11:16:48 +02:00
Daniel Boros f682e9e396 feat: implement LiveReload for bool index (#9299) 2026-08-04 11:16:48 +02:00
Daniel Borosandgenerall b827433f46 feat: add payload storage constructor (#9315)
* refactor: move LiveReload trait to common module

* feat: add payload storage constructor

* for read-only components we should always expect file presense, as we cant recreate

* feat: implement LiveReload for read-only payload storage (#9316)

* adjust docstring

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-08-04 11:16:48 +02:00
Daniel Boros fc3406ba41 feat: implement LiveReload for read-only roaring flags (#9329)
* feat: implement LiveReload for read-only roaring flags

Make ReadOnlyRoaringFlags<S> implement the shared LiveReload trait (open retains the StoredBitSlice; reopen + read only the changed positions on reload), threading the backend S through the read-only bool/null index structs, the field-index enum and the facet enum. The per-index reload impls live in the bool/null branches stacked on top.

* fix: review commits

* feat: add remark comment
2026-08-04 11:16:48 +02:00
Daniel Boros 2c4b4a8c4b fix: read_values in fulltext index (#9324) 2026-08-04 11:16:47 +02:00
Daniel Boros 848443613c feat: live reload fulltext index (#9313)
* feat: implement LiveReload for full text index

* chore: remove comment
2026-08-04 11:16:47 +02:00
Daniel Boros 05f6948cfa refactor: move LiveReload trait to common module (#9314) 2026-08-04 11:16:47 +02:00
Daniel Boros 463d72531b feat: implement LiveReload for geo index (#9298)
* feat: implement LiveReload for geo index

* chore: rename ingest_raw_points to ingest

* chore: rebase to dev
2026-08-04 11:16:47 +02:00
Daniel Boros bec9e90c99 fix: remove remove_point from read_only appendable numeric index live_reload (#9318)
* feat: implement LiveReload for numeric index

* fix: missing remove_point method

* fix: remove comments

* chore: trigger ci

* fix: remove remove_point

* fix: rebase
2026-08-04 11:16:47 +02:00
Daniel Boros e020bcb623 feat: implement LiveReload for numeric index (#9297)
* feat: implement LiveReload for numeric index

* fix: missing remove_point method

* fix: remove comments

* fix: bad var usage

* chore: trigger ci

* fix: dev rebase
2026-08-04 11:16:47 +02:00
Daniel Boros cd1cd46c34 feat: add LiveReload trait for read-only field indexes (#9295)
* feat: add LiveReload trait for read-only field indexes

* fix: ci

* chore: remove comment

* feat: implement LiveReload for map index (#9296)
2026-08-04 11:16:47 +02:00
0f0c27d1e6 feat: wire up read only field indexes (#9224)
* feat: wire up read only field indexes

* feat: add missing indexes

* feat: add try_from impl for TextIndexParams

* refactor: unify read-only field index open and drop RocksDB storage

Merge ReadOnlyFieldIndex::open_gridstore/open_mmap into a single `open`
that picks the appendable vs immutable path from the stored
FullPayloadIndexType::storage_type. The choice is modeled as a ReadMode
(Appendable/Immutable) rather than a concrete backend, since the
read-only stack is generic over UniversalRead and mmap is now just one
implementation of it.

Also remove the unsupported RocksDb variant from payload_config's
StorageType and its now-dead match arms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: linter

* fix: linter

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 15:18:39 +02:00
Daniel BorosandLuis Cossío b0dc310c27 feat: avoid payload-index rebuild (#9138)
* feat: add swap on_disk methods

* fix: linter

* feat: add swap in disk for indexes

* fix: linter

* fix: std::fs::read -> fs_err::read

* feat: add on_disk swap bool & null indexes

* refactor: use macro instead boilerplate

* feat: add better error propagation

* fix: review comments -> remove try_swap.. and mut lock

* fix: linter

* chore: remove try_open_mmap

* fix: match -> ?

* review nits

* fix: seperate edge case for appendable segment

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-06-03 14:58:27 +02:00
Daniel Boros e795d40cfb feat: add open for read only numeric index (#9213)
* feat: add open for read only numeric index

* feat: add parent open_*, get_mutability_type for ReadOnlyNumericIndex

* fix: naming and generic fs

* feat: detect not-found via error in numeric index open

* fix: hw counter write -> read
2026-06-03 14:57:11 +02:00
Daniel Boros 0e244662d3 feat: detect not-found via error in bool, null and geo index open (#9265)
* feat: detect not-found via error in bool, null and geo index open

* fix: error on inconsistent storage in bool and null index open

* fix: hw counter write -> read
2026-06-03 14:57:11 +02:00
Daniel Boros 7c4140f2a0 feat: add open for read only fulltext index (#9222)
* feat: add open methods for fulltext

* fix: naming

* feat: detect not-found via error in fulltext index open

* fix: hw counter write -> read
2026-06-03 14:57:11 +02:00
Daniel Boros 2365d1a3ef feat: add_ref_payload_index_io_read_counter (#9266) 2026-06-03 14:57:10 +02:00
Daniel Boros 0033a867cf feat: remove generic in Roaring flag & move into open method (#9236)
* feat: add readonly null index open

* feat: add open method

* refactor: split variants into modules

* chore: remove duplicated impl

* feat: remove generic in Roaring flag move into open method
2026-06-03 14:57:10 +02:00
4bf579b1b4 feat: add open for read only map index (#9223)
* feat: add open methods for map

* fix: review comments

* feat: detect not-found via error instead of path.exists in map index open

Replace the path.exists() pre-check in the read-only appendable map index
open path with error-driven detection through ok_not_found(). Generalize
OkNotFound over an IsNotFound trait, implemented for io::Error, mmap::Error,
UniversalIoError, and GridstoreError so a NotFound surfacing through any
layer (including mmap's inner io::Error) maps to Ok(None).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* review: revert internal error conversion

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:57:09 +02:00
Daniel Boros b16bd255f5 feat: readonly geo index open (#9211)
* feat: add geo index open method

* fix: test

* feat: add open_mmap and open_gridstore methods
2026-06-03 14:57:09 +02:00
Daniel Boros 62b7fad0f9 feat: readonly bool index open (#9200)
* feat: add readonly null index open

* feat: add open method

* refactor: split variants into modules

* feat: add get_mutability_type to ReadOnlyBoolIndex

* chore: remove duplicated impl

* fix: remove populate

* chore: add immutable bool index docs
2026-06-03 14:53:12 +02:00
Daniel BorosandLuis Cossío ada6e82157 feat: add readonly null index open (#9197)
* feat: add readonly null index open

* feat: add get_mutability_type to ReadOnlyNullIndex

* fix: pr reviews

* simpler phantomdata

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-06-03 14:53:11 +02:00
Daniel Boros 3ee7789ab9 feat: add writable option for gridstore open (#9210) 2026-06-03 14:51:12 +02:00
Daniel BorosandAndrey Vasnetsov 539606e5d4 feat/edge-bm25 (#8827)
* feat: integrate bm25 into edge

* fix: linter

* fix: imports

* fix: qdrant-edge build errors

* fix: spell check

* feat: integrate inference

* fix: api missmatch

* chore: remove inference

* fix: coderabbit comments

* fix: compiler error

* chore: remove wrapper type

* feat: add some temp tests for legacy check

* add example

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
2026-06-03 14:47:48 +02:00
bd8a6ae655 feat: sync->async bridge (#9093)
* feat: add io_bridge

* fix: cached dispatcher

* feat: add open_with_handle

* fix: naming

* fix: wording

* fix: rebase io_bridge onto split BorrowedReadPipeline/OwnedReadPipeline

* fix: linter

* feat: add S3 backend

* chore: remove io_bridge

* fix: linter

* fix: linter

* fix: read handle

* chore: simplify S3Source

* fix: s3 test

* feat: support multi runtime

* fix: clippy errors

* fix: review comments

* feat: add io design

* feat: add S3 backend

* chore: fix docs

* fix: dev changes

* chore: add some docs

* chore: remove explicit type

* feat: add new methods

* [WIP] review refactor

* fmt

* fix: bytes alignment

* fix: linter

* feat: remove Bytes

* fix: ci/cd

* fix: tests

* fix: tests

* refactor: simplify io_bridge pipeline to Handle-based dispatch

Replace the BridgeRuntime worker thread + request channel + boxed
BridgeRequest with direct tokio Handle usage:

- BridgeRuntime is now just an Arc<Runtime>; schedule() spawns the read
  future via Handle::spawn instead of routing it through a dispatcher
  thread. Removes BridgeRequest and the now-unreachable S3RuntimeShutDown
  error variant.
- Guard against a panicking read task hanging wait() forever: the spawned
  task catches unwinds and converts them into a TaskPanicked error reply,
  so every scheduled slot is always answered.
- Encapsulate slot bookkeeping in PendingSlots, exposing only the needed
  operations instead of a public map + counter.
- Split the grown pipeline.rs into a pipeline/ module (slots / inner /
  borrowed / owned), de-duplicating the shared read-future construction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: move pipeline buffer ownership into the read future

Instead of the pipeline owning the destination Vec<T> in a slot map and
the future writing through a SendBytePtr raw pointer, let the future
allocate the buffer itself and return it through BridgeResponse. The
buffer crosses the worker-thread boundary as a normal move via the reply
channel, wrapped in a SendableVec<T> newtype that asserts Send for
T: bytemuck::Pod only.

This removes the entire unsafe SendBytePtr apparatus from the pipeline:
no raw pointer, no unsafe fn, no per-call-site unsafe blocks, no
heap-stability invariants. The only remaining unsafe in the crate is one
bounded `unsafe impl<T: Pod> Send for SendableVec<T>` with a trivially
true invariant (Pod types are plain bytes).

PendingSlots collapses back to PendingSlots<U>: slots no longer carry
buffers. AlignedBufWriter::from_raw_bytes (used only by the SendBytePtr
path) and its test are removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: drop SendableVec wrapper now that Item: Send

UniversalRead's element type is now bound to `Item` (`Pod + Send`),
so the io_bridge pipeline no longer needs a hand-rolled `Send` wrapper
around `Vec<T>` to ship buffers through the reply channel. Replace
`SendableVec<T>` with `Vec<T>` end-to-end and tighten the local impls
to `T: Item`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: implement UniversalRead::reopen for BlobFile

BlobFile has no cached file metadata or mapping — `len()` queries the
object store fresh on each call — so reopen is a no-op, matching the
io_uring impl.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: add new fs impl for Blob

* fix: is_in_ram_or_mmap for S3

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 14:47:41 +02:00
3818ff593d refactor: read-only-fulltext (#9035)
* refactor: read only full text

* fix: linter

* refactor: follow new file structure

* chore: remove storage enums

* fix: linter

* fix: FullTextReadIndex methods

* chore: remove duplicated impls

* fix: format

* refactor: unify FullTextIndex telemetry via trait default method

Add a `get_telemetry_data` default method to `FullTextIndexRead` built
from the existing telemetry methods, so the `ReadOnlyFieldIndex` match
arm is consistent with every other variant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: move full-text lifecycle methods off FullTextIndexRead trait

`populate`, `clear_cache`, `files` and `immutable_files` are lifecycle
concerns, not part of the read surface. Move them from the
`FullTextIndexRead` trait to inherent methods alongside the rest of each
index's lifecycle code (open / wipe / flusher). Also split the
`mutable_text_index` tests into their own `tests.rs`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: restructure full_text_index module layout

Move the `FullTextIndex` enum into `full_text_index/mod.rs` and split its
impls following the inner-module convention: lifecycle (constructors,
builders, ValueIndexer, PayloadFieldIndex) into `lifecycle.rs`, read-path
impls and shared free functions into `read_ops.rs`. Extract the
`FullTextIndexRead` trait into its own `full_text_index_read.rs`.

Drops the inherent `FullTextIndex::get_telemetry_data`, which duplicated
the `FullTextIndexRead::get_telemetry_data` default method.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: read-only counterpart of MutableFullTextIndex

Extract the shared in-memory state of `MutableFullTextIndex` into
`MutableFullTextIndexInner` (inverted index, config, tokenizer), which
implements `FullTextIndexRead`. `MutableFullTextIndex` now wraps it
alongside a writable `Gridstore`.

Add `ReadOnlyAppendableFullTextIndex<S>`, wrapping the same inner state
with a `GridstoreReader` over generic `UniversalRead`. Mirrors the
`MutableMapIndex` / `ReadOnlyAppendableMapIndex` split; loading and
lifecycle land in a follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: turn ReadOnlyFullTextIndex into a two-variant enum

Rename the `read_only_text_index` module to `read_only` and reshape
`ReadOnlyFullTextIndex` from a thin `MmapFullTextIndex` wrapper into an
`Appendable` / `Immutable` enum, mirroring `ReadOnlyMapIndex`. Its
`FullTextIndexRead` impl is now a dispatcher forwarding to the active
variant.

Drop the no-op inherent `populate` (mutable, immutable) and
`immutable_files` (mutable) methods that tripped `clippy::unused_self`
and `clippy::unnecessary_wraps` after the earlier trait-to-inherent
move; `FullTextIndex::populate` inlines the in-RAM no-op directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 10:40:40 +02:00
Daniel Boros e784896753 feat: restructure null index (#9042) 2026-05-22 10:40:11 +02:00
Daniel Boros 652af06f9a refactor: read only geoindex (#9033)
* refactor: read only geo index

* fix: linter

* fix: drop open temp

* fix: read_ops

* fix: address review fixes and use same file structure like map index

* fix: review comments

* fix: linter
2026-05-22 10:40:05 +02:00
Daniel Boros 9c709e7891 feat: add readonly bool (#9030) 2026-05-22 10:39:03 +02:00
Daniel Boros 731293bcb8 refactor: read only boolindex (#9023)
* feat: add read only boolean index

* fix: linter

* chore: merge BoolIndex impl
2026-05-22 10:38:52 +02:00
Daniel Borosandgenerall eb4bac0782 refactor: read only nullindex (#9019)
* feat: add read only null index

* fix: linter

* chore: remove unused impl

* chore: revert impl deletion

* fix: linter errors and rename shared->read_ops

* fix: linter

* review fixes

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-05-22 10:37:53 +02:00
Daniel Boros e34a9c2621 feat/vector-index-read-only (#8891)
* feat: add vector index read only

* fix: linter

* chore: trigger ci

* feat: add blank impls

* refactor: split hnsw (#8991)

* feat: split hnsw

* refactor: split sparse vector index (#8992)

* refactor: split hnsw

* fix: linter

* refactor: split sparse vector index
2026-05-22 10:33:24 +02:00
Daniel Borosandgenerall bfb33c56b6 feat/vector-storage-read-only (#8889)
* feat: add vector storage read enum

* fix: linter

* chore: remove open functions

* fix: compiler error

* review fix 1: remove constructiors (for now), use UniversalReadFamily, implement 1st part of VectorStorageReadEnum

* fmt

* read only chucked_vector_storage

* fnt

* feat: add dense chunked variants to vector storage read enum (#8916)

* feat: add multi dense chunked (#8918)

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-05-08 13:48:28 +02:00
Daniel Boros 6d8f739bee feat: split read only payload index (#8858)
* feat: split read only payload index

* fix: imports

* fix: linter
2026-05-08 13:47:46 +02:00
Daniel Boros 7ebec73926 feat: split read only payload storage (#8857) 2026-05-08 13:47:46 +02:00
Daniel Boros 87f1a8b497 feat: add internal shard level storage api (#8778) 2026-05-08 13:47:31 +02:00
Daniel Boros fc99a67fc9 feat/internal-grpc-auth (#8676) 2026-05-08 13:47:17 +02:00
Daniel Boros 9aa391d1ff fix: timeout tests (#8591) 2026-05-08 13:46:01 +02:00
Daniel Borosandgenerall 8d8a1477f9 Feat/storage api over universal io (#8311)
* feat: add storage_read_service proto definition

* feat: update qdrant tonic definition

* feat: add list_files

* feat: add read_bytes

* feat: add read_bytes_stream

* feat: add read_batch & read_whole api

* feat: add read_multi

* fix: mod.rs

* feat: update resolve_path

* feat: add path resolve

* feat: add more tests and fix stream api

* feat: better error handling

* feat: add collection_base_path

* fix: potential EOF error

* fix: nested runtime panic on tests

* fix: github actions

* fix: auth tests

* fix: coderabbit pr review

* fix: linter

* fix: clippy

* fix: range validation and path resolve

* fix: linter

* fix: clippy

* fix: clippy

* fix: universal io error

* fix: incoming changes

* fix: compiler error

* feat: spilt impl

* fix: pr review

* fix: linter

* fix: dev changes

* fix: linter

* review fixes

* fmt

* chore: fix naming

* fix: pr reviews

* fix: rebase dev

* fix: clippy

* fix: tests

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-05-08 13:45:41 +02:00
Daniel Boros dc47b15378 fix: edge optimize example (#8352)
* fix: edge optimize example

* fix: use DATA_DIRECTORY
2026-03-26 17:49:05 +01:00
Daniel Borosandgenerall 5d74df25e5 feat/edge segment opt (#8224)
* feat: add edge shard optimize

* feat: refactor edge optimize logic

* chore: remove unused &self

* feat: add more tests

* fix: linter

* fix: missing threshold prop

* fix: local nightly version

* fix: linter

* fix: linter issues

* fix: use of explicit from

* feat: add some notes

* fix: feature_flags call once

* [manual] review refactor

* fix:
- default_segment_number -> move shard
- rename: default_hnsw_config -> hnsw_config
- infer existing hnsw_config

* feat: add optimize to python

* feat: add python optimize example

* feat: add hnsw config load tests

* fix: linter

* feat: make unified build config

* fix: linter

* fix: openapi definition'

* fix: review comments

* fix: remove mut self & reset_temp_segments_dir

* fix: linter

* review: rename for simpler public name + use explicit strucuture deconstruction

* clipy

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-03-26 17:39:02 +01:00
Daniel Boros 0be340cdd2 refactor/opt (#8065)
* refactor: opt system

* feat: move tracker seperately

* feat: migrate opt logic to shards

* feat: add OptStrategy trait

* fix: missing drop

* fix: linter error

* fix: clippy errors

* fix: linter error

* fix: missing fns

* fix: linter

* fix: missing import

* fix: missing import

* fix: schema_gen imports

* chore: remove comment

* feat: add missing comments

* feat: restore optimize_segment_propagate_changes fn

* chore: move fs4 to workspace deps

* fix: compiler error

* chore: add import fixes

* feat: move optimzers to shard

* fix: clippy errors

* chore: restore tests and adjust them

* fix: linter issues

* fix: linter issue

* fix: remove CollectionResult where call is infallible

* fix: comment
2026-03-26 16:51:37 +01:00
Daniel Boros 7422d20f19 feat/edge-facet-api (#8045)
* feat: add sync facet api

* feat: add facet-tests

* fix: formatting

* chore: remove exact typing

* feat: reduce code duplication

* fix: add missing type def

* fix: serde default value
2026-02-09 23:57:47 +01:00
Daniel Boros 02b9373772 feat: add x-forwarded support (#8028)
* feat: add x-forwarded support

* fix: port parsing & add tests

* fix: case-insensitive mode
2026-02-09 23:52:47 +01:00
Daniel Borosandgenerall fdccb8c367 feat/ext-api-keys (#7809)
* feat: forward api keys header

* fix: linter

* feat: add api_keys to grpc

* fix: imports

* fix: extract api keys from grpc headers

* refactor: make apikeys extracor more compact

* fix: linter issue

* feat: update header key logic

* fix: clippy issues

* make external keys a part of InferenceParams::new argument, so we wont forget using it

* avoid cloning metadata on header extraction

* combine inference token with ext api key for simpler usage

* clippy

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-02-09 23:43:11 +01:00
Daniel Borosandgenerall 00e0a7fc24 feat/test-timeout (#7920)
* feat: add timeout tests

* fix: timeout test

* fix: api urls

* fix: test

* feat: add staging api def

* feat: add parallel executor for tests

* fix: imports

* fix: ci/cd

* rollback openapi schema change

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-02-09 23:15:44 +01:00
b85176a11a feat/shard-ops-timeout (#7750)
* feat: add shard-ops timeout

* feat: add shard-ops timeout

* feat: add missing timeout

* fix: format

* fix: type serialization

* fix: bad wal flush logic

* feat: add seperate wait_time

* fix: linter issues

* fix: linter

* chore: make select more readable

* fix: linter issues

* chore: remove comment

* chore: adjust comment

* chore: update definition

* chore: remove extra wait_timeout -> make timeout global

* chore: remove wait_timeout from point_ops

* chore: remove wait_timeout from grpc

* refactor: make shard_ops more readable

* chore: remove timeout from update_all

* feat: propagate wait_timeout error

* fix: clippy recommendation

* chore: update wait timeout

* refactor: update merge_successful_update_results

* fix: tests inconsistency

* fix: revert global ord, partialord for UpdateStatus

* fix: integration test

* fix: res ingoring

* fix: review requests

* fix: clippy

* chore: revert back futures unordered

* fix: resolve response status

* force timeout for remote operations

* fix: pr reviews

* fix: switch to duration

* Bump OpenAPI spec

* feat: add serde_as

* fix: timeout statu condition

* Minor tweaks

* Use tokio timeout directly rather than deadline

* Revert schema generator permissions

* Remove obsolete semi-colon

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: timvisee <tim@visee.me>
2026-02-09 23:02:15 +01:00
Daniel Boros 568f574429 feat/update-timeout (#7694)
* feat: add timeout to update params

* feat: update timeout params

* feat: add timeout for grpc

* fix: add missing timeout params

* fix: clippy warnings

* feat: update openapi definition

* chore: format

* fix: redoc master.json

* feat: add missing timeout to grpc api

* fix: missing timeout

* chore: update comments
2025-12-18 17:27:29 +01:00
Daniel Borosandgenerall 8b7c9f051f fix/inference timeout error (#7598)
* fix: inference timeout error

* chore: cleanup timeout from inference config

* cleanup timeout from InferenceConfig

* chore: revert config.toml changes

* inference_token -> infrence_params for timeout propagation

* always use at least some timeout

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2025-11-25 14:25:39 +01:00
Daniel Boros 2c734e52a4 feat: handle 429 properly on infer svc (#7377)
* feat: handle 429 properly

* feat: change to rate limit error

* feat: handle http_date

* chore: remove unsued imports

* chore: make it more readable
2025-11-14 12:28:14 +01:00