100 Commits
Author SHA1 Message Date
xzfc 943b9c3a0c [combined-storage] Derive inline-storage warnings from the optimizer's vector config (#10430)
* Refactor: Untangle SegmentOptimizerConfig

* Derive inline-storage warnings from the optimizer's vector config
2026-09-03 12:46:01 +02:00
xzfc 60e60f2446 Pass vector-index path to the vector-storage opens (#10434) 2026-09-03 12:46:00 +02:00
xzfc a764bfe6a4 Integrate batched HNSW (#10194)
* [14] HnswGraph: wrapper enum over in-RAM and batched graphs

* [15] HnswGraph: route async backends to the batched graph

* [15.a] De-tautologize `test_open_matrix`

Anti-pattern: `expect_batched` mirrors `format_is_batched` logic.

* [16] HNSW healing: reopen as direct

* [17] Add async_hnsw_graph feature flag

* Batch size
2026-09-03 12:41:05 +02:00
xzfc e2080ec980 Batched HNSW: search implementation (#10010)
* [12] GraphLayersBatched: batched-IO HNSW search

* [12.a] Batched ACORN, simplify
2026-09-03 12:39:03 +02:00
xzfc c0e4c41682 Batched HNSW reader (#10054) 2026-09-03 12:38:59 +02:00
xzfc 174dee0a3e Batched HNSW: preliminary refactoring (#10052)
* [1] refactor: EntryPoint: derive Copy

* [2] refactor: extract GraphLayers::probe_links_format

* [3] refactor: merge …/graph_links/{links, storage}.rs

* [4] refactor: GraphLinks: inline GraphLinksEnum methods

* [5] refactor: graph_links/view.rs split into view_utils.rs

Later these utils would be used in links_file.rs.

* [6] spelling: clarify error_size

* [7] refactor: TestGraphLinksVectors::{assert_base_vector, assert_link_vector}

* [8] refactor: extract entry-point selection out of GraphLayers::search

* [9] refactor: Introduce GraphWithVectorScorers

* [10] refactor: extract load_or_derive_config
2026-09-03 12:36:31 +02:00
xzfc 3d4f9c2f69 cargo +nightly fmt (#10057) 2026-08-04 11:18:45 +02:00
xzfcandLuis Cossío efd3bfd617 bitpacking_ordered: batched reads (#10038)
* bitpacking_ordered: batched reads

* Replace ranges with pairs

* "unsufficient" -> "insufficient"

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-08-04 11:18:45 +02:00
xzfc 2a91dd4a5d uio-grpc-client/build.rs: don't bump mtime every build (#10048) 2026-08-04 11:18:45 +02:00
xzfc ca3fe18f16 Remove dead code (#10030)
* Remove dead code

* Remove unused dependencies

* `allow(dead_code)` -> `expect(dead_code)`

* ast-grep: rule-tests/*-test.yml => tests/*-test.yml

For brevity.

* ast-grep: forbid allow(dead_code)
2026-08-04 11:18:44 +02:00
xzfc 8e2e6b5f4c chore: bench_cache (#10028) 2026-08-04 11:18:44 +02:00
xzfc 4645c498a9 Cleanup UniversalRead methods interface (#9934)
* use common::generic_consts::{Random, Sequential};

* UniversalRead::read_batch: generic over E

* UniversalRead::read_batch: pass `AccessPattern` as ZST arg

* UniversalRead::read_bytes_iter: pass `AccessPattern` as ZST arg

* UniversalRead::read_iter: pass `AccessPattern` as ZST arg

* UniversalRead::read: pass `AccessPattern` as ZST arg

* UniversalRead::read_bytes: pass `AccessPattern` as ZST arg
2026-08-04 11:18:42 +02:00
xzfc a4a805acac UioResult (#9933) 2026-08-04 11:18:42 +02:00
xzfc 5e2bba7148 ConditionChecker::check_batched: use in hnsw (#9845) 2026-08-04 11:18:42 +02:00
xzfcandLuis Cossío 8b7b7faee6 Batched ConditionChecker (#9740)
* ConditionChecker::check_batched: trait + ConditionCheckerEnum

* check_batched for OptimizedFilter

* OnDiskPointToValues::values_iter_batch: improve performance

* OnDiskPointToValues::values_iter_batch: update interface

Accept bitvec, call on every point, pass UserData.

* check_batched for geo index

* geo_index tests: add same_geo_index_between_points_with_dups_test

Catches broken load_from_on_disk/for_all_points_values.

* check_batched for map index

* check_batched for numeric index

* check_batched for full-text index

* tests for check_batched

* Review fixups

- default_check_batched: avoid running pred twice at boundary
- condition_checker: use explicit match over matches!/if-else
- Partitioner: use assert! over debug_assert!

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>

* ConditionChecker::check_batched: &mut self -> &self

* ConditionChecker::check_batched: make mandatory

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-08-04 11:18:42 +02:00
xzfc cd01cabbfb deps: drop proc-macro-error2 (#9931) 2026-08-04 11:18:42 +02:00
xzfc ce4b665798 Optimize debug build time (less generics) (#9895)
* Non-generic TransformInto::transform

I think dyn is fine here because it is executed once per query, not in a
hot loop.

* Query::score_by impls: manual loops

Iterator chains (`.iter().map(..).sum()`) produce a lot work for the
compiler to do.

* QuantizedCustomQueryScorer: move generics from struct to `new` method
2026-08-04 11:18:40 +02:00
xzfc caed08a60d Refactor unit-tests (#9787)
* Refactor geo_index tests: shorer geopoints

GeoPoint is serializable, no need to write json fields manually.

* Refactor geo_index tests: extract filtered_points() helper

* Refactor geo_index tests: extract assert_cardinality helpers

* Refactor geo_index tests: hoist duplicated check_cardinality_match to module level

* Normalize point_to_values test

Instead of two separate copypaste geo/string tests, make the test
generic and instantiate it 4 times.

* Refactor geo_index tests: reload_index
2026-08-04 11:17:00 +02:00
xzfc fcb1c3db8a Refactor: add DeletedBitVec (#9738) 2026-08-04 11:16:59 +02:00
xzfc bc2c40d93c Tidy up Debug impls (#9653) 2026-08-04 11:16:56 +02:00
xzfc b02267e743 Cleanup FieldCondition validation (#9557) 2026-08-04 11:16:55 +02:00
xzfc 24e4fe7afa Replace DynConditionChecker with ConditionCheckerEnum (#9560)
* Add UniversalReadExt

Need this trait for the upcoming `ConditionCheckerEnum`.

* Replace DynConditionChecker with ConditionCheckerEnum
2026-08-04 11:16:55 +02:00
xzfc cd1d38e57a ConditionChecker fixups (#9559)
* Add NumericIndexValue

* MapConditionChecker: get rid of `F: Fn() -> bool` bound

To put this type into the upcoming `ConditionCheckerEnum`, it should be
nameable.

* filter_context: `Box<dyn ConditionChecker>` -> `OptimizedFilter`

Removes one level of dyn indirection, so faster checks.

* NullConditionChecker: merge IsEmpty/IsNull checkers into one

So, less variants in the upcoming `ConditionCheckerEnum`.
2026-08-04 11:16:55 +02:00
xzfc 4c87b9c4fc OptimizedFilter: Option<Vec<T>> -> Vec<T> (#9555) 2026-08-04 11:16:54 +02:00
xzfc ee152a7ec5 Generalize BorrowCow (#9556) 2026-08-04 11:16:54 +02:00
xzfc 5b9539fec7 Remove callback-based ConditionChecker (#9487)
* Add BoolConditionChecker

* Add IsEmptyConditionChecker, IsNullConditionChecker

* Add RangeConditionChecker

* Add GeoConditionChecker

* MapIndexRead: move <'a> to the trait level

Reason: avoid repetetive `where N: 'a` in every method

* Add MapConditionChecker

* Add ConstantConditionChecker

* Add FullTextConditionChecker

* Add {Ids,HasVector,Payload}ConditionChecker

* Get rid of fn-based ConditionChecker
2026-08-04 11:16:52 +02:00
xzfc bded4c15c3 Move trait ConditionChecker to common (#9486)
* Add DynConditionChecker type alias

* Add DynConditionChecker type alias (point_scorer.rs)

* Move trait ConditionChecker to `common`

Reason: will be used both in `segment` and `sparse` crates.
2026-08-04 11:16:52 +02:00
xzfcandLuis Cossío 211c64608c Sparse InvertedIndex: bring back generic methods (#9485)
* sparse InvertedIndex: bring back generics

* nits

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-08-04 11:16:52 +02:00
xzfc 0405bb5057 [UIO] condition checker: fallible checks (#9405)
* condition checker: fallible checks

* Update
2026-08-04 11:16:51 +02:00
xzfc 4da3e97812 [UIO] condition checker: fallible constructor (#9404)
* Drop StructFilterContext, use OptimizedFilter directly

Reason: it's a no-op wrapper around OptimizedFilter.

* GeoMapIndexRead::check_values_any: return OperationResult

* condition checker: fallible constructor
2026-08-04 11:16:50 +02:00
xzfc 1780aef255 [UIO] Batched sparse index (#9304)
* Add UniversalRead::read_bytes_iter

* Batched sparse vector index

* Clarify
2026-08-04 11:16:47 +02:00
xzfc 03ab9cc97a edge: use cargo metadata instead of parsing Cargo.toml (#9287)
* edge: refine ast-grep rules

* edge: use `cargo metadata` instead of parsing Cargo.toml
2026-08-04 11:16:47 +02:00
xzfc aa74ccdd67 Sparse: use blink-alloc instead of typed-arena (#9303)
* Use blink-alloc

* Pool arena
2026-08-04 11:16:47 +02:00
xzfc 779a66f783 Migrate InvertedIndexCompressedMmap to UIO (#9144)
* Migrate InvertedIndexCompressedMmap to UniversalRead

* Rehaul search_scratch.rs (was scores_memory_pool.rs)

- Use `typed_arena::Arena` instead of `bumpalo::Bump`.
  Reason: bump don't drop.
  Drawback: `Arena::new()` is not free, and `Arena::clear()` doesn't
  exist; but this commit has workarounds.
- Use names that make more sense.

* Misc fixes

* InvertedIndexCompressedMmap: explicit S type parameter
2026-06-03 14:53:11 +02:00
xzfc 3a51e32391 [UIO] Dynamic alignment (#9040)
* universal_io bench: skip io_uring/8bytes/read_batch_full

* ACow

* [UIO] Dynamic alignment [v2]

* override MmapFile::read_iter/read_multi_iter for better performance
2026-06-03 14:49:45 +02:00
xzfc 9109542993 Replace PendingSlots with slab::Slab (#9190) 2026-06-03 14:49:44 +02:00
xzfc 3729c62117 Cache sparse benchmark setup (#9141)
* dataset: add features to fs-err

Reason: fix `cargo check --all-targets -p dataset`. Feature unification
pulls `fs-err/debug` + `fs-err/tokio` without `fs-err/debug_tokio`.

* dataset: run `cargo metadata` to get target dir

Reason: avoid re-downloading in separate worktrees. The old
`cargo locate-project` ignores custom target dirs.

* sparse/benches/search: cache vectors/indices
2026-06-03 14:46:35 +02:00
xzfc a57df81e1f sparse: use zerocopy (#9140)
* sparse: use zerocopy for mmap reads

* loaders::Csr: use zerocopy
2026-06-03 14:45:26 +02:00
xzfc aa4bafdcc2 Restore pre-UIO-migration OpenOptions behavior (#9107)
* [ai] segment dynamic_stored_flags: need_sequential(true -> false)

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/common/flags/dynamic_mmap_flags.rs#L115-L146

* [ai] segment immutable_id_tracker: need_sequential(true -> false)

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/id_tracker/immutable_id_tracker.rs#L249-L262

* [ai] segment geo_index: need_sequential(true -> false)

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/index/field_index/geo_index/mmap_geo_index.rs#L239

* [ai] segment geo_index: populate(Auto -> from(!is_on_disk))

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/index/field_index/geo_index/mmap_geo_index.rs#L239

* [ai] segment numeric_index: need_sequential(true -> false)

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/index/field_index/numeric_index/mmap_numeric_index.rs#L171

* [ai] segment map_index: need_sequential(true -> false)

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/index/field_index/map_index/mmap_map_index.rs#L68-L71

* [ai] segment map_index: populate(Auto -> from(!is_on_disk))

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/index/field_index/map_index/mmap_map_index.rs#L71

* [ai] segment full_text_index: need_sequential(true -> false)

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/index/field_index/full_text_index/inverted_index/mmap_inverted_index/mod.rs#L117-L133

* [ai] segment full_text_index: populate(Auto -> from(populate))

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/index/field_index/full_text_index/inverted_index/mmap_inverted_index/mod.rs#L133

* [ai] gridstore bitmask: need_sequential(true -> false)

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/gridstore/src/bitmask/mod.rs#L120

* [ai] gridstore bitmask: advice(Global -> Random)

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/gridstore/src/bitmask/mod.rs#L40

* [ai] gridstore bitmask/gaps: advice(Global -> Normal) in create

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/gridstore/src/bitmask/gaps.rs#L103

* [ai] gridstore bitmask/gaps: populate(Blocking -> No) in open

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/gridstore/src/bitmask/gaps.rs#L119

* [ai] segment quantized_storage: need_sequential(true -> false)

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/segment/src/vector_storage/quantized/quantized_mmap_storage.rs#L32-L40

* [ai] gridstore pages: advice(Global -> Random) in attach_page

https://github.com/qdrant/qdrant/blob/v1.17.0/lib/gridstore/src/page.rs#L38

* [ai] tonic storage_read_api: update OpenOptions for read-only handlers

Rationale:
- writeable: false — all 6 are read-only APIs; true would fail on
  read-only mounts.
- need_sequential: false — opening a second mmap with MADV_SEQUENTIAL on
  Linux costs a VMA per call. For one-shot reads driven by a single gRPC
  request, the second mmap isn't justified — better to put the hint on
  the primary mmap via advice.
- populate: No — these are one-shot reads, no point warming the page
  cache.
- advice: Sequential for read_bytes_stream (streams the file in 1MB
  chunks) and read_whole (reads everything) — the kernel can read ahead.
- advice: Normal for file_length (doesn't read content), read_bytes
  (single range), read_batch / read_multi (random ranges).
2026-05-22 10:48:11 +02:00
xzfc 9df8ae95e1 Make OpenOptions explicit (#9104)
* Refactor: make OpenOptions explicit

* Refactor: remove unused OpenOptions::disk_parallel

* Refactor: do not wrap `advice` in Option

* Refactor: Add OpenOptionsExtra
2026-05-22 10:47:59 +02:00
xzfc 2b5cf80f66 Warn on clippy::wildcard_enum_match_arm (#9096) 2026-05-22 10:46:36 +02:00
xzfc ed1b7da030 BorrowedReadPipeline/OwnedReadPipeline (#9079)
* BorrowedReadPipeline/OwnedReadPipeline

* `fn new(file: &Self::File)` -> `fn new(file: Self::File)`

Also, partially revert some related changes from the previous commit.
2026-05-22 10:44:53 +02:00
xzfc 1634d430e2 Reorganize universal_io modules (#9078)
* Let's not expose `universal_io` internal modules.
* Reorganize universal I/O code files
2026-05-22 10:44:33 +02:00
xzfc 7035440f4c Error propagation for sparse InvertedIndex (#9076)
* Remove unused InvertedIndexMmap / InvertedIndexImmutableRam

* Error propagation for InvertedIndex trait
2026-05-22 10:44:28 +02:00
xzfc ba710e1c50 Remove unused InvertedIndexMmap / InvertedIndexImmutableRam (#9074) 2026-05-22 10:44:15 +02:00
xzfc 840e72db6e UniversalReadFileOps: require Debug (#9063) 2026-05-22 10:43:12 +02:00
xzfc aabc99fdd3 Replace Meta with U: UserData (#9009) 2026-05-22 10:38:32 +02:00
xzfc 47943f9b20 Integrate UniversalHashMap (#8954)
* Callback-based InvertedIndex::for_each_vocab_with_postings_len

* Integrate UniversalHashMap into full-text index

* Integrate UniversalHashMap into immutable_map_index
2026-05-22 10:34:55 +02:00
xzfcandgenerall 44ccae7a98 Split mmap_hashmap into multiple files (#8933)
Co-authored-by: generall <andrey@vasnetsov.com>
2026-05-08 13:48:30 +02:00
xzfc dbe6ba567a Callback-based InvertedIndex::for_each_token_id (#8905)
* TokenizerTextKind

* IteratorExt::try_any

* Callback-based InvertedIndex::for_each_token_id
2026-05-08 13:48:27 +02:00
bde40eb44a UniversalReadPipeline (#8798)
* UniversalReadPipeline

* Performance: cache pointers in MmapFile

The previous commit removed `MmapFile::read_batch` method override. So,
`MmapFile` now re-uses the default `UniversalRead::read_batch` impl,
which is implemented using `UniversalReadPipeline` interface.

Unsurprisingly, it caused a slowdown in the benchmarks, particularly
this one:

    cargo bench -p common --bench universal_io -- mmap/8bytes/read_batch_full

This commit reclaims the performance back.

* remove unfulfilled lint

* Review suggestions

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
Co-authored-by: Roman Titov <ffuugoo@users.noreply.github.com>
2026-05-08 13:47:43 +02:00
xzfc c93f63b122 Fix NullIndex/for_each_payload_block build (#8796) 2026-05-08 13:47:31 +02:00
xzfc 3a4f59816d Callback-based for_each_payload_block (#8766) 2026-05-08 13:47:31 +02:00
xzfcandLuis Cossío 58083c694a Callback-based FacetIndex (#8764)
* Segment::approximate_facet: don't use iter

* Callback-based FacetIndex

* take deferred internal id out of the loop

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-05-08 13:47:30 +02:00
a9c62acfec Migrate geo_index to UIO (#8507)
* Add common::iterator_ext::fallible helpers

* refactor: counts_of_hash

* Add ReadRange::one

* UniversalRead::read_iter: return Result

* Add binary_search module

* Migrate geo_index to UIO

* minor review fixes

* Review fixups

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-05-08 13:46:41 +02:00
xzfc a306702563 Propagate OperationResult in PayloadFieldIndex::filter (#8647) 2026-05-08 13:46:39 +02:00
xzfc 3c413cdf86 Misc edge fixes (#8622)
* fix(amalgamate): strip `mod gpu`

Fixes `cargo +nightly fmt` in `lib/edge/publish`. Previously we had to
run `cargo +nightly fmt -p examples` to avoid the error.

* fix(Justfile): unset VIRTUAL_ENV

Otherwise it causes problems when running that Justfile from other
(unrelated) venvs. Particularly, `uv pip install` and `maturin develop`
will mess with cached venvs created by `uv run --script` which sounds
insane.
2026-05-08 13:46:36 +02:00
xzfc a8024b8c4b shell.nix: update pinned dependencies (#8623)
Problems:
- The pinned `uv` version sometimes pulls broken python interpreter.
- The pinned `just` is too old to read `lib/edge/Justfile`.

Solution: update everything.

    nix-shell --run 'cd tools/nix && npins update' # for default.nix
    nix-shell --run 'cd tools/nix && npins upgrade' # for sources.json

Also, in this nixpkgs version, renames `nixfmt-rfc-style` into `nixfmt`.
2026-05-08 13:46:36 +02:00
xzfc 14b4f717cc UniversalIO: generic RequestId (#8601)
* IoUringState: generic `RequestId`

* UniversalRead: generic `RequestId`

* Simplify `gridstore::Pages::get_page_value_ranges`

Now we don't need two separate `SmallVec`s as we can put `buffer_offset`
into `RequestId`.

* Better doc comment

* Rename `RequestId` -> `Meta`
2026-05-08 13:46:04 +02:00
xzfc a152d7c38e IoUringState: replace HashMap with flat slice (#8599) 2026-05-08 13:46:03 +02:00
xzfc 6600349794 Separate GeoHash/GeoHashRaw (#8618)
* GeoHash: convert to tuple struct for consistency

* GeoHash: clarify code

* Separate `GeoHash`/`GeoHashRaw`
2026-05-08 13:46:03 +02:00
xzfc 90f1fd6942 UIO read benchmark (#8575) 2026-05-08 13:46:01 +02:00
xzfc 85b524e2c3 IoUringFile: don't use io_uring for single operations (#8576) 2026-05-08 13:45:58 +02:00
xzfc 5638d1799c Drop RocksDB (#8529)
* Skip broken tests

* Add rocksdb dropper

This is a temporary tool. It will be removed later in this PR.

* [automated] Drop rocksdb

This commit is made by running tools/rocksdb/drop.sh

* Touch-up after ast-grep

The previous automated commit removed items, but not their comments.
Also, some blocks are left with only one item.
Also, ast-grep can't handle macros like `vec![]`.

This commit completes the job.

* Remove RocksDB dropper

* Remove mentions of rocksdb feature in CI

* Fix clippy warnings

These `FIXME` comments added previously in this PR by ast-grep by
"peeling" cfg_attr like this:

    -#[cfg_attr(not(feature = "rocksdb"), expect(...))]
    +#[expect(...)] // FIXME(rocksdb): ...

This commit removes these allow/expect attributes and fixes clippy
lints.

* Remove leftover rocksdb-related code

Removed:
- Cargo.toml: rocksdb cargo feature flag and dependencies.
- code: rocksdb-related items that was not under feature flag.
- flags.rs: rocksdb-related qdrant feature flags.

Disabled:
- Some benchmarks because these do not compile now.

* Print warning if rocksdb leftovers found in snapshots

* Remove Clone from tokenizer

* Regenerate openapi.json
2026-05-08 13:45:44 +02:00
xzfc 45c519995a Add TypedStorage wrapper (#8508)
* Remove UniversalRead::is_empty

Reason: Less methods to override in wrappers. And I don't think this
method makes much sense.

* Move common::universal_io::{ => wrappers}::read_only

* Update ReadOnly wrapper

Implement missing methods, and follow the code style of the upcoming
TypedStrorage wrapper.

* Add TypedStorage

* Use TypedStorage

* Add reminder comments

* Clarify TypedStorage use-case
2026-03-26 18:52:41 +01:00
xzfc 07f5341e98 Propagate OperationResult (#8433) 2026-03-26 18:44:06 +01:00
xzfc 33c97e8120 Propagate OperationResult [3/4]: estimate_cardinality (#8446) 2026-03-26 18:35:41 +01:00
xzfc 530027002a edge 0.6.0 (#8459) 2026-03-26 18:28:52 +01:00
xzfc 4d560bd88f Touch-up UIO traits (#8457)
* UIO traits: require Sized

I don't think we ever going to add unsized implementation. So, lets,
require it on the whole trait rather than on individual methods.

* Move `AccessPattern` to the `common` package

Was: segment::vector_storage::vector_storage_base::AccessPattern
Now: common::generic_consts::AccessPattern

* UIO traits: replace `bool` with `AccessPattern`
2026-03-26 18:28:33 +01:00
xzfc 09c96ead01 Propagate OperationResult [2/4]: SegmentEntry (#8445) 2026-03-26 18:24:24 +01:00
xzfc 206a5c65f4 Propagate OperationResult [1/4]: payload_blocks (#8444) 2026-03-26 18:23:40 +01:00
xzfc 6a719a7726 Use GeoHash instead of &GeoHash (#8443) 2026-03-26 18:22:51 +01:00
xzfc e6497cb31e Edge flat api (#8381)
* refactor(edge): let edge re-export segment/shard/sparse

* chore(ast-grep-rules): handle path like `::shard::blah::Blah`

This commit was required during the refactoring. It turns out we don't
need it right now, but it might be useful in the future. Or not.

* refactor(edge-rs): Rehaul public API
2026-03-26 18:21:40 +01:00
xzfc da4c15a5fc DiscoveryQuery -> DiscoverQuery (#8378) 2026-03-26 17:55:57 +01:00
xzfc c41a582296 Chores (#8370)
* chore: gitignore .idea and .vscode globally

Reason: `lib/edge/publish` is a separate Cargo workspace and I'd like to
have a separate rust-analyzier configuration for it, which is stored in
`.vscode/settings.json`. Not sure about `.idea`, but I guess the same
logic applies.

* chore: Use Iterator::is_sorted (stabilized in Rust 1.82)

* chore: remove unrelated files

These were added in #5501 (42fd2e27), perhaps by accident?
2026-03-26 17:52:01 +01:00
xzfc 6d16442357 Test edge examples on CI (#8318)
* lib/edge/publish/cargo: improve target directory discovery

Don't hardcode workspace root, ask cargo instead.

* Fix warning in qdrant-edge amalgamation

`cargo check` in `lib/edge/publish` produces the following warning:

    warning: type `PointerUpdates` is more private than the item `gridstore::tracker::Tracker::<S>::write_pending`

* lib/edge/publish/examples: fix compiler warnings

* refactor: lib/edge/publish/examples: put DATA_DIRECTORY into lib.rs

To match python examples that have the same constant in `common.py`.

* Use `lib/edge/data` dir for both Python and Rust examples

Before this commit, `lib/edge/publish/data` and `lib/edge/python/data`
were used. I'd like Python and Rust to use the same prepared resources
in the future.

* Add lib/edge/Justfile with recipes to build/run examples

I constantly keep forgetting how to compile and run edge stuff.
Also, this would be used in CI in subsequent commits.

* doc: lib/edge/README.md: Combine Rust and Python Edge readmes

Also now we can rename `creates-io-readme.md` to `README.md` like
reasonable people.

* doc: Add qdrant-edge-py README.md

Since the previous commit removed qdrant-edge-py README.md, we need to
add something in its place instead.
The new README is adapted from Rust edge README.
And the previous README wasn't good anyway, see [1], it mentions maturin
which is irrelevant for users.

[1]: https://pypi.org/project/qdrant-edge-py/0.5.0/

* GHA: Add "Setup Qdrant" composite action

We need running Qdrant instance to test edge examples on CI. We can't
use docker for this because we want to run tests on Windows and macOS.
OTOH, this action downloads binaries for all platforms provided in
https://github.com/qdrant/qdrant/releases/tag/v1.17.0

* GHA: Use single worflow for python and rust edge examples

Merge workflows to reuse build cache. Also, modernize it by using `uv`,
and recently introduced `setup-qdrant` and Justfile. Also, make it run
on three platforms (only on merges).

* GHA: edge-{py,rust}-release: also run examples before publishing

Use similar approach as in the previous commit. But note that this time
we build/test also on ARM Linux and Windows.
2026-03-26 17:51:49 +01:00
xzfc 1f9946f6d3 Update Readmes/manifest for qdrant-edge Rust package (#8316) 2026-03-26 17:40:36 +01:00
xzfc 2efc29507f Synchronize Rust and Python edge examples (#8312) 2026-03-26 17:39:38 +01:00
xzfc 89333b49eb Fix edge examples (#8295)
* amalgamate.py: replace `env!("CARGO_PKG_VERSION")`

Otherwise segment thinks it's v0.0.0 which breaks examples.

* Fix lib/edge/python/examples/repr.py

It it broken by d9393acac6 (#7933), which renamed `SegmentConfig` →
`EdgeConfig` and removed `index` parameter from `VectorDataConfig` by
hardcoding it to `Plain`.

Before:

    $ python lib/edge/python/examples/repr.py
    NameError: name 'SegmentConfig' is not defined

After:

    $ python lib/edge/python/examples/repr.py
    EdgeConfig(vector_data={"": VectorDataConfig(size=128, ...)}, ...)

* gitignore output of Rust edge examples

* Restore `lib/edge/python/examples/.gitignore`

I'm not sure why it's removed in 65312a1e82e6ae4d/#7522.

* Add `prepare_facet_snapshot.sh` for `facet_test.rs`

The script is based on steps mentioned in #8045.

* Remove `edge-cli.rs` example

It was added in 895318913afbad4a/#7140 and seems incomplete.
2026-03-26 17:37:53 +01:00
xzfc e23cc13d0a Remove shard dependency on api (#8284)
* Move `DenseVector`/`MultiDenseVector` from `api` to `segment`

* Move `OrderByInterface` from `api` to `segment`

Reason: it's used in `edge` which shouldn't depend on `api`.

* Make `shard` -> `api` dependency optional

* Remove `api` from the amalgamation

* Don't install protoc in edge Actions
2026-03-26 17:37:48 +01:00
xzfc 91d2d7cbb1 Qdrant edge rust fixes (#8277)
* amalgamate.py: specify encoding="utf-8"

For legacy platforms that still default to cp1252.

* amalgamate.py: use `shutil.which`

In case if `ast-grep` is a cmd wrapper.

* amalgamate.py: write rules to temporary file

Windows runner don't like inline-rules.

* amalgamate.py: Add decription to package

Required for publishing to crates.io.

* amalgamate.py: package build scripts for `common` and `segment`

Also, add more comments.

* amalgamate.py: keep generated module order deterministic

Not an issue, but nice to have. Suggested by CodeRabbit.

* edge-rust-release.yml: also check on arm machines

* edge-rust-release.yml: Use cargo build instead of cargo check

To catch linker errors.

* edge-rust-release.yml: disable fail-fast (for easier debugging)

* edge-rust-release.yml: add --no-verify to cargo publish

The previous job `edge-rust-check` already builds it, no need to build
it again in the `publish` job.
2026-03-26 17:30:44 +01:00
xzfc 7e2d6b588c Workflow to publish qdrant-edge on crates.io (#8260)
* [ai] Workflow to publish qdrant-edge on crates.io

* Doc, tune Cargo.toml
2026-03-26 17:29:53 +01:00
xzfc 3fa476865b Single edge crate (#8173)
* Fixups of amalgamator

Fix issues that break `qdrant-edge` build process:
- `use … as segment;` - this causes `ast-grep` rules to replace wrong
  paths. So, rename to avoid collisions.
- `#[macro_use]` and `extern crate` required be in the top-level
  `lib.rs`.
- `format!("…", crate::something::…)` - `ast-grep` can't fix paths
  inside macros. Fixed by moving `crate::something::…` out of the macro.

* Add lib/edge/publish workspace and amalgamation script

* Move `lib/edge/examples` into `lib/edge/publish/` workspace

And fix them to use the generated `qdrant-edge` crate.

* Add github workflow

* Cleanup `qdrant-edge` public API

Removes empty modules. Checked by `cargo doc`.
2026-03-26 17:02:24 +01:00
xzfc bc838f6aa9 Use qdrant-rust-stemmers from crates.io (#8199) 2026-03-26 16:56:05 +01:00
xzfc 8fb7adea98 Move github.com/qdrant/wal into lib/wal (#8185)
* Copy github.com/qdrant/wal into lib/wal

Commit: c07fb56ebc8120ebe4e3c602d31ce98f356f4676 2026-02-18

* Clean cruft

* Integrate lib/wal into workspace

* Cargo fmt

* Fix clippy warnings

* Adhere to our conventions

* Fix codespell warnings
2026-03-26 16:53:55 +01:00
xzfc 66d0c36009 Merge io and memory into common (#8155)
* Unify parking_lot/arc_lock feature

* Move lib/common/{io,memory}/* -> lib/common/common/*

- Mmap-related items are grouped into `common::mmap` sub-module:
  - `memory/src/chunked_utils.rs`      -> `common/src/mmap/chunked.rs`
  - `memory/src/madvise.rs`            -> `common/src/mmap/advice.rs`
  - `memory/src/mmap_ops.rs`           -> `common/src/mmap/ops.rs`
  - `memory/src/mmap_type_readonly.rs` -> `common/src/mmap/mmap_readonly.rs`
  - `memory/src/mmap_type.rs`          -> `common/src/mmap/mmap_rw.rs`
- Filesystem-related items are grouped into `common::fs` sub-module:
  - `common/src/fs.rs`          -> `common/src/fs/sync.rs`
  - `io/src/file_operations.rs` -> `common/src/fs/ops.rs`
  - `io/src/move_files.rs`      -> `common/src/fs/move.rs`
  - `io/src/safe_delete.rs`     -> `common/src/fs/safe_delete.rs`
  - `memory/src/checkfs.rs`     -> `common/src/fs/check.rs`
  - `memory/src/fadvise.rs`     -> `common/src/fs/fadvise.rs`
- Rest is moved straight into `common`:
  - `io/src/storage_version.rs` -> `common/src/storage_version.rs`

The old `io` and `memory` are now hollow crates that re-export items
from `common`. These hollow crates will be removed in next commits.

* Replace uses of `io` and `memory` with new paths in `common`

Since `io` and `memory` are just re-exports of `common`, these
replacements are no-op.

* Remove `io` and `memory` crates
2026-02-17 11:01:14 +01:00
xzfc 22e8a56b86 Fix Cargo.lock (#8157) 2026-02-17 11:01:14 +01:00
xzfc 88c51ae772 Add doc for #[pyclass_repr] (#8110) 2026-02-13 09:55:46 +01:00
xzfc b1e3e421b0 Chore: promote dependencies to workspace level (#8061)
* Promote `env_logger` to workspace dependency

* Promote `anyhow` to workspace dependency

* Promote `rmp-serde` to workspace dependency

* Promote `tinyvec` to workspace dependency

* Promote `async-trait` to workspace dependency

* Promote `url` to workspace dependency

* Promote `self_cell` to workspace dependency

* Promote `cc` to workspace dependency

* Promote `bitpacking` to workspace dependency
2026-02-10 00:02:45 +01:00
xzfc 5d72481af3 Callback-based DenseVectorStorage::for_each_in_dense_batch (#8033)
* Generalized vector offset

* Replace get_batch-like methods with for_each-like methods
2026-02-09 23:58:14 +01:00
xzfc 8fb203eeb5 Update GET collections/{}/optimizations (#7946)
* refactor(SegmentOptimizer::name): make it `&'static`

* refactor(TrackerStatus): add is_running()

* refactor: add TrackerSegmentInfo

* feat: rework optimizations endpoint

* feat(collections/{}/optimizations): trim spaces
2026-02-09 23:28:03 +01:00
xzfc 5c8da73447 Fix hnsw_incremental_build benchmark (#7978)
* Fix hnsw_incremental_build benchmark

* More docs
2026-02-09 23:26:12 +01:00
xzfc de04a66d3c Sync LocalShard::optimizers (#7962) 2026-02-09 23:20:48 +01:00
xzfc 6abd5a1776 Enforce segment UUIDs (#7958)
* Swap docstrings for segment_ids/segment_uuids

Terse internal docs, detailed user-facing docs, not vice versa.

* Enforce segment UUIDs

* Export upcoming segment UUID to telemetry

* Add `optimize_for_test` wrapper

* Tune log message

Reason: the UUID is now guaranteed.

* Improve argument naming/docs
2026-02-09 23:20:44 +01:00
xzfc cada712738 GET /optimizations: re-plan on each request (#7945) 2026-02-09 23:14:02 +01:00
xzfc d9d2801c71 Expose planned optimizations in API (#7784)
* Expose pending optimizations in API

* Address review comments
2026-02-09 23:07:34 +01:00
xzfc 722fa2fc31 OptimizationPlanner (#7752)
* refactor(SegmentHolder::iter): use SegmentId, not &SegmentId

* refactor(SegmentHolder): Add SegmentHolder::iter_original

* refactor: inline *Optimizer::worst_segment() into SegmentOptimizer::check_condition

* refactor(ConfigMismatchOptimizer): extract config_mismatch function

* Fix comments

* refactor: consistent variable naming

It's `segment_id`/`_segment_id`, not `idx`/`sid`/`x.0`/`_`.

* refactor(IndexingOptimizer): extract large chunks of logic

* refactor(SegmentOptimizer): simplify unwrap_proxy/handle_cancellation

* SegmentHolder: add running_optimizations counter

* OptimizationPlanner

* MergeOptimizer: allow merging two segments, update doc
2026-02-09 23:03:57 +01:00
xzfc fbb310e633 Put unreliable unsafe block behind "testing" feature flag (#7884) 2026-02-09 22:52:07 +01:00
xzfc b08c19ed88 Use syncfs (#7883)
* Remove call to Archive::set_sync

Also, this method was the last remaining part of our `tar-rs` fork,
so we can switch to the upstream version now.

* Do syncfs
2026-02-09 22:48:16 +01:00
xzfc 0c8dad0db3 Remove ProgressState::Skipped (#7873) 2026-02-09 22:39:45 +01:00