Commit Graph

1780 Commits

Author SHA1 Message Date
Ivan Pleshkov
4b9b39c596 Use predefined deferred ID (#8329)
* Adjust points selection for deferred points update

* adjust proxy segment implementation

* simplify

* use simpler proxy impl

* stick to Entry API

* renaming to stay closer to the original

* two passes and simpler impl.

* fmt

* fmt

* use predefined deferred internal id

* calculate deferred point id

* move deferred check to the entry

* fix after rebase

* fmt

* fix tests

* review remarks

* fix tests

* codespell fix

* are you happy clippy

---------

Co-authored-by: Arnaud Gourlay <arnaud.gourlay@gmail.com>
2026-03-10 02:17:20 +01:00
qdrant-cloud-bot
7e15d343c2 Introduce EdgeShardConfig for edge shard (#8322)
* Introduce EdgeShardConfig for edge shard

- Add EdgeShardConfig and EdgeOptimizersConfig in lib/edge/src/config.rs
  - Segment config (vector_data, sparse_vector_data, payload_storage_type)
  - Global hnsw_config and per-vector HNSW in segment config
  - Optimizer params: deleted_threshold, vacuum_min_vector_number,
    default_segment_number, max_segment_size, indexing_threshold,
    prevent_unoptimized (excludes memmap_threshold, flush_interval_sec,
    max_optimization_threads)
- Persist/load as edge_config.json in shard path
- EdgeShard uses RwLock<EdgeShardConfig>; load() accepts Option<EdgeShardConfig>,
  falls back to file or infer from segments; compatibility checked on load
- load_with_segment_config() for backward compatibility (SegmentConfig -> EdgeShardConfig)
- optimize() uses EdgeShardConfig for hnsw and optimizer thresholds
- Public methods: set_hnsw_config(), set_vector_hnsw_config(), set_optimizers_config()
  (update and persist)
- Python and examples use load_with_segment_config with existing config API

Made-with: Cursor

* Refactor EdgeShardConfig: user-facing params only, config module

- Replace SegmentConfig inside EdgeShardConfig with user-facing fields:
  - on_disk_payload (bool) instead of payload_storage_type
  - vectors: HashMap<VectorNameBuf, EdgeVectorParams> with on_disk per vector,
    no per-vector quantization; global quantization_config only
  - sparse_vectors: HashMap<VectorNameBuf, EdgeSparseVectorParams> with on_disk
- EdgeVectorParams / EdgeSparseVectorParams use on_disk (bool) instead of
  storage_type; conversion to VectorDataConfig/SparseVectorDataConfig in
  to_segment_config()
- Add config module: mod.rs, optimizers.rs, vectors.rs, shard.rs
- from_segment_config(&SegmentConfig) fills all inferrable params
- to_segment_config() builds SegmentConfig for segments and optimize()
- load_with_segment_config takes Option<SegmentConfig>, uses from_segment_config

Made-with: Cursor

* Move optimizer threshold helpers to shard crate

- Add get_number_segments, get_indexing_threshold_kb, get_max_segment_size_kb,
  get_deferred_points_threshold_bytes in shard::optimizers::config
- Collection OptimizersConfig and edge EdgeOptimizersConfig delegate to these
- Single place for threshold logic; collection and edge use shard helpers

Made-with: Cursor

* Use destructuring in config conversions to avoid missing new fields

- EdgeVectorParams: destructure VectorDataConfig in from_*, destructure self in to_vector_data_config
- EdgeSparseVectorParams: destructure SparseVectorDataConfig and SparseIndexConfig in from_*, destructure self in to_sparse_vector_data_config
- EdgeShardConfig: destructure SegmentConfig in from_segment_config, destructure self in to_segment_config
Adding new fields to source structs will now cause compile errors until conversions are updated.

Made-with: Cursor

* refactor: centralize on_disk_payload→payload_storage_type, on_disk→storage_type, and appendable quantization logic

- PayloadStorageType::from_on_disk_payload(bool) in segment (Mmap/InRamMmap)
- VectorStorageType::from_on_disk(bool) in segment (ChunkedMmap/InRamChunkedMmap)
- QuantizationConfig::for_appendable_segment(Option<&Self>) in segment (feature flag + supports_appendable)
- collection: use from_on_disk_payload in non-rocksdb branch
- edge shard/vectors: use new helpers; remove duplicated conditionals
- shard optimizers: use from_on_disk and for_appendable_segment

Made-with: Cursor

* refactor(edge): use EdgeShardConfig directly, drop segment_config

- Add plain_segment_config() for create_appendable_segment (no HNSW)
- Add segment_optimizer_config() built from EdgeShardConfig for blocking optimizers
- Add vector_data_config(name) for query/MMR
- build_blocking_optimizers: use segment_optimizer_config() instead of SegmentConfig
- create_appendable_segment: use plain_segment_config()
- search/query: use config().vectors and vector_data_config() instead of segment_config()
- Remove segment_config() from EdgeShardConfig and EdgeShard
- Add to_plain_vector_data_config on EdgeVectorParams

Made-with: Cursor

* [manual] review changes

* refactor(edge-py): wrap EdgeShardConfig, add EdgeVectorParams/EdgeSparseVectorParams

- PyEdgeConfig now wraps EdgeShardConfig (vectors, sparse_vectors, on_disk_payload, etc.)
- PyEdgeVectorParams / PyEdgeSparseVectorParams wrap edge config types
- PyEdgeOptimizersConfig for optional optimizer settings
- EdgeShard.load() uses EdgeShardConfig; edge::config made pub for Python crate
- cargo fmt + clippy (remove map_identity)

Made-with: Cursor

* refactor(edge-py): simplify config API, remove unused Py* types, add EdgeConfig

- Remove unused PyPayloadStorageType, PyVectorDataConfig, PyVectorStorageType,
  PySparseVectorDataConfig, PySparseVectorStorageType from Python bindings
- Move PyEdgeOptimizersConfig to lib/edge/python/src/config/optimizers.rs
- Update qdrant_edge.pyi: EdgeConfig with vectors/sparse_vectors,
  EdgeVectorParams, EdgeSparseVectorParams, EdgeOptimizersConfig
- Update examples (common.py, repr.py) to use new config API
- Run cargo fmt

Made-with: Cursor

* [manual] review changes

* [manual] review changes

* [manual] fix test

* Address CodeRabbit review comments for PR 8322 (#8324)

* Address CodeRabbit review comments for PR 8322

- Python examples: explicit imports (repr.py, common.py) and new EdgeConfig API
- HnswIndexConfig: add max_indexing_threads param and property in .pyi and Rust bindings
- EdgeConfig: make vectors optional for sparse-only configs; validate at least one of vectors/sparse_vectors
- EdgeShardConfig::load: use try_exists(), propagate I/O errors
- from_segment_config: infer hnsw_config from per-vector HNSW when all agree
- EdgeShard setters: atomic clone-mutate-save-then-replace; persist config save errors
- Segment compat: prefix vector name in error messages; resolve None datatype to Float32
- max_indexing_threads: preserve 0 (auto) sentinel in trait default; remove per-optimizer overrides
- SegmentOptimizerConfig:🆕 build plain and optimizer maps in single pass
- config_mismatch_optimizer tests: use VectorNameBuf::from() instead of .into()
- vectors.rs: doc updates for per-vector quantization

Made-with: Cursor

* Address @generall review: SaveOnDisk for config, resolve num_rayon_threads in optimizer

- Use SaveOnDisk<EdgeShardConfig> for EdgeShard config (generall: 'We have SaveOnDisk struct for this')
  - Create via SaveOnDisk::new() after resolving config; setters use .write() for atomic persist
  - set_vector_hnsw_config: clone then mutate then write (fallible setter)
- max_indexing_threads: resolve 0 (auto) via num_rayon_threads inside impl (generall: 'proper solution would be to resolve num_rayon_threads inside the optimizer impl')
  - max_indexing_threads_sentinel_aware() now returns Some(num_rayon_threads(raw)) so callers get actual thread count

Made-with: Cursor

* [manual] reorganize num_rayon_threads -> get_num_indexing_threads to better account per-vector configuration

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
Co-authored-by: generall <andrey@vasnetsov.com>

* update docstring and pyi

* fmt

* fmt

* clipy

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
Co-authored-by: generall <andrey@vasnetsov.com>
2026-03-10 00:10:04 +01:00
Luis Cossío
9c6b23346d Rename to StoredPointToValues (#8302)
* rename trait

* rename MmapPointToValues -> StoredPointToValues

* fmt

* more explicit naming of trait functions
2026-03-09 11:56:56 +01:00
Arnaud Gourlay
43b94d27d5 Adjust points selection for deferred points update (#8279)
* Adjust points selection for deferred points update

* adjust proxy segment implementation

* clean

* simplify

* use simpler proxy impl

* cleanup

* stick to Entry API

* renaming to stay closer to the original

* renaming to stay closer to the original

* nits

* two passes and simpler impl.

* fmt

* fmt

---------

Co-authored-by: Ivan Pleshkov <pleshkov.ivan@gmail.com>
2026-03-09 10:05:27 +01:00
Luis Cossío
c7eadf49de Refactor PointToValues to use UniversalRead (#8298)
* refactor PointToValues to use UniversalRead

It includes a significant change to `MmapValue` trait to be able to
handle Cow reads, instead of just references.

* fix str parsing

* fix incorrect path

* use fallible casting

* clippy

* No eager allocation

this also makes it so that borrowed strs can keep happening :heart-eyes:

* Lifetime cleanup

---------

Co-authored-by: Roman Titov <ffuugoo@users.noreply.github.com>
2026-03-06 16:11:13 -03:00
qdrant-cloud-bot
d7ad2d45f7 fix: codespell 2.4.2 - pre-selected -> preselected, pre-select -> preselect (#8303)
* fix: codespell 2.4.2 - pre-selected -> preselected, pre-select -> preselect

Fixes CI failure with codespell 2.4.2 which flags hyphenated forms.
Updated in: types.rs, query/mod.rs, qdrant.rs, points.proto

Made-with: Cursor

* chore: regenerate OpenAPI spec (tools/generate_openapi_models.sh)

Updates oversampling description to use preselected spelling.

Made-with: Cursor

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
2026-03-06 11:47:16 +01:00
xzfc
628195fafe 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-05 04:38:02 +00:00
Andrey Vasnetsov
aff0ba9669 fix(segment): use div_ceil() to satisfy clippy::manual_div_ceil on Rust 1.94 (#8291)
Replace manual ceiling division (next_multiple_of/div) with div_ceil()
in points_in_storage_count. Fixes clippy with cargo +beta clippy
--workspace --all-targets --all-features -- -D warnings.

Made-with: Cursor

Co-authored-by: Cursor Agent <agent@cursor.com>
2026-03-04 17:15:59 +01:00
Andrey Vasnetsov
b6c1987038 MultiFile Universal UI in gridstore pages (#8256)
* [manual] implement Pages for read-only

* Simpler `ReadMulti`/`WriteMulti` interface (#8263)

* [manual] Dumbify `ReadMulti`/`WriteMulti` interface

* fixup! [manual] Dumbify `ReadMulti`/`WriteMulti` interface

🤷‍♀️

* fixup! [manual] Dumbify `ReadMulti`/`WriteMulti` interface

Remove `VecMultiUniversalIo`

* [manual] review fix + silplify json load option

* [AI] split read and write + revome *Multi traits

* [AI] implement write for pages

* [AI] integrate pages into gridstore

---------

Co-authored-by: Roman Titov <ffuugoo@users.noreply.github.com>
2026-03-03 14:50:44 +01:00
dependabot[bot]
328a6d8819 build(deps): bump cgroups-rs from 0.3.4 to 0.5.0 (#8270)
* build(deps): bump cgroups-rs from 0.3.4 to 0.5.0

Bumps [cgroups-rs](https://github.com/kata-containers/cgroups-rs) from 0.3.4 to 0.5.0.
- [Release notes](https://github.com/kata-containers/cgroups-rs/releases)
- [Commits](https://github.com/kata-containers/cgroups-rs/compare/v0.3.4...v0.5.0)

---
updated-dependencies:
- dependency-name: cgroups-rs
  dependency-version: 0.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: use cgroups_rs::fs API for cgroups-rs 0.5 compatibility

Made-with: Cursor

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cursor Agent <agent@cursor.com>
2026-03-03 14:50:28 +01:00
Andrey Vasnetsov
9b344197a5 feat(universal_io): MultiUniversalRead trait and VecMultiUniversalRead implementation (#8255)
* feat(universal_io): add MultiUniversalRead trait and VecMultiUniversalRead impl

- Add SourceId, MultiUniversalRead<T> trait with read_batch_multi, source_len,
  populate, clear_ram_cache (latter two with default no-op).
- Add UniversalIoError::InvalidSourceId for invalid source id in batch reads.
- Add VecMultiUniversalRead<T, S>: minimal implementation over Vec<S: UniversalRead<T>>
  with attach(source) -> SourceId for adding sources at runtime.
- Add test vec_multi_universal_read_batch_and_attach using MmapUniversal.
- Handle InvalidSourceId in segment OperationError From<UniversalIoError>.

Implements the interface and minimal mmap-based implementation from
docs/design/multi-file-universal-io-plan.md (multi-source universal I/O).

Made-with: Cursor

* refactor(universal_io): move multi-source interface to separate file, drop plan from PR

- Add universal_io/multi_universal_read.rs with SourceId, MultiUniversalRead,
  VecMultiUniversalRead and test; re-export from mod.rs.
- Remove docs/design/multi-file-universal-io-plan.md from the branch.

Made-with: Cursor

* refactor(universal_io): require populate/clear_ram_cache; add new, attach, len, is_empty to trait

- MultiUniversalRead: remove default impls for populate() and clear_ram_cache();
  they are now required.
- Add to trait: new(), len(), is_empty() (default), attach() (default Err).
- Introduce associated type Source for attach; add AttachUnsupported<T>
  placeholder for impls that do not support dynamic attach.
- VecMultiUniversalRead: type Source = S; implement all trait methods.
- Re-export AttachUnsupported from universal_io.

Made-with: Cursor

* refactor(universal_io): remove AttachUnsupported; require attach for all impls

- Drop AttachUnsupported placeholder type and its UniversalRead/Send impls.
- Make attach() a required method on MultiUniversalRead (no default).
- Doc: all implementations must support attaching sources dynamically.
- Remove AttachUnsupported from re-exports.

Made-with: Cursor

* refactor(universal_io): attach by path, new(options), split vec impls, add MultiUniversalWrite

MultiUniversalRead:
- Remove type Source; attach(path, options) opens by path and returns SourceId.
- new(options: OpenOptions) for creating an empty multi-source view.
- Move VecMultiUniversalRead to vec_multi_universal_read.rs.

MultiUniversalWrite (new):
- Trait: new(options), len(), is_empty(), attach(path, options),
  write_batch_multi((SourceId, offset, data)...), source_len, flusher(),
  populate(), clear_ram_cache().
- VecMultiUniversalWrite in vec_multi_universal_write.rs; flusher()
  runs all source flushers.

Re-export MultiUniversalWrite, VecMultiUniversalWrite from universal_io.

Made-with: Cursor

* universal_io: MultiUniversalWrite extends MultiUniversalRead

Make MultiUniversalWrite<T>: MultiUniversalRead<T> like UniversalWrite
extends UniversalRead. Remove duplicated methods (new, len, is_empty,
attach, source_len, populate, clear_ram_cache) from the write trait;
keep only write_batch_multi and flusher. VecMultiUniversalWrite now
impl MultiUniversalRead and MultiUniversalWrite separately.

Made-with: Cursor

* [manual] final fixes

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
2026-03-02 18:19:56 +01:00
Andrey Vasnetsov
82c49df611 feat(universal_io): add read_whole and read_json_via for config files (#8251)
* feat(universal_io): add read_whole and read_json_via for config files

- Extend UniversalRead with read_whole() for single-access whole-file read
- Default impl uses len() + read(0..len()); MmapUniversal overrides with one slice
- Add UniversalIoError::SerdeJson for JSON deserialization errors
- Add read_json_via<S,T>(path, options) in common::universal_io
- Gridstore: use read_json_via for config in read_config_and_tracker
- Segment: use read_json_via in ChunkedVectors::load_config, handle NotFound
- Segment: extend From<UniversalIoError> for OperationError with SerdeJson variant

Made-with: Cursor

* feat(universal_io): add UniversalIoError::NotFound for file-not-found

- Add NotFound { path } variant so callers can match without io::ErrorKind
- MmapUniversal::open maps io::ErrorKind::NotFound to NotFound { path }
- ChunkedVectors::load_config matches NotFound => Ok(None)
- OperationError From<UniversalIoError> handles NotFound

Made-with: Cursor

* style: apply cargo fmt

Made-with: Cursor

* fix(common): satisfy clippy explicit_auto_deref in read_json_via

Use &bytes instead of &*bytes; auto-deref handles Cow

Made-with: Cursor

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
2026-03-02 16:38:17 +01:00
Arnaud Gourlay
15be52f122 Introduce Segment API point_is_deferred (#8259)
* Introduce Segment API point_is_deferred

* improve everything

* cheaper implementation

* explicit conversions

* test reopening segment

* test unify logger
2026-03-02 14:39:09 +01:00
Ivan Pleshkov
30cf43382b Deferred threshold integration (#8246)
* Deferred threshold integration

* update deferred id

* apply update_deferred_internal_id

* fix segment inspector

* use avaliable bytes count

* renamings

* review remarks

* review remarks

* move has_deferred_points

* remove todo

* update comments
2026-03-02 09:57:19 +01:00
Luis Cossío
5403ea68ab Chunked vectors with UniversalWrite storage (#8233)
* use CowMultiVector as return type from storages

* add advice to OpenOptions

* Implement ChunkedVectors with generic storage

* rename ChunkedVectors->VolatileChunkedVectors and ChunkedMmapVectors-> ChunkedVectors

* propagate everywhere

fix tests

* [auto] rename BytesRange -> ElementsRange

* [auto] rename BytesOffset -> ElementOffset

* coderabbit nits

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-02-27 12:47:15 -03:00
krapcys1-maker
3ddf6234e1 test(segment): stabilize building cancellation timing assertions (#8243)
Co-authored-by: local-user <local-user@local>
2026-02-27 13:08:35 +01:00
Luis Cossío
21890d2738 use Cow<'_, [T]> as return type in dense vector storages (#8221)
* use `Cow<'_, [T]>` as return type in vector storages

* extract complex type

* clippy

* improve maybe_uninit_fill_from

* don't commit to graphlinks yet
2026-02-26 13:30:21 -03:00
Sapphire
ada810896a Optimize ImmutablePointToValues: inline single-value points to reduce RAM usage and increase performance (#8235)
* optimize: performance improve

* Optimize ImmutablePointToValues to store single values inline

- Replace PointMeta with PointValueEntry enum to distinguish single vs
  multi-value points
- Store single values directly in point_entries, reducing container
  overhead
- Only multi-value and empty points use the shared values_container
- Update all methods and tests to use new representation
- Add tests for edge cases and single-value optimizations

* Explicit branch for zero sized value

* Update comment

* Remove zero count branch as it appears to make it slightly slower

---------

Co-authored-by: 1995chen <chenl2448365088@gmail.com>
Co-authored-by: timvisee <tim@visee.me>
2026-02-26 16:44:45 +01:00
Andrey Vasnetsov
03c0fa2cf7 Universal IO: gridstore pages (#8223)
* [manunal] Gridstore page use universal IO

* fmt

* Apply review feedback for universal IO gridstore pages (#8230)

* Apply review feedback from PR #8223

- Use `super::Result` import in mmap.rs instead of fully-qualified `crate::universal_io::Result`
- Restructure ValuePointer destructuring in get_value and delete_value to
  first match Some(pointer), then destructure separately

* Replace Either<E, GridstoreError> with E: From<GridstoreError> in Gridstore::iter

Use a trait bound instead of Either to combine callback and gridstore
errors, allowing `?` to work directly on GridstoreError. This simplifies
callers by removing Either matching and io::Error conversion workarounds.

---------

Co-authored-by: qdrant-claw <qdrant-claw@users.noreply.github.com>

---------

Co-authored-by: qdrant-claw <qdrant-claw@users.noreply.github.com>
2026-02-25 19:46:00 +01:00
Arnaud Gourlay
b91b3017da Remove unused dependencies (#8226) 2026-02-25 15:42:11 +01:00
dependabot[bot]
18a7587d4b build(deps): bump rand_distr from 0.5.1 to 0.6.0 (#8148)
* build(deps): bump rand_distr from 0.5.1 to 0.6.0

Bumps [rand_distr](https://github.com/rust-random/rand_distr) from 0.5.1 to 0.6.0.
- [Release notes](https://github.com/rust-random/rand_distr/releases)
- [Changelog](https://github.com/rust-random/rand_distr/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand_distr/compare/0.5.1...0.6.0)

---
updated-dependencies:
- dependency-name: rand_distr
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Migrate main code base to rand 0.10

* Migrate tests

* Migrate benches

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: timvisee <tim@visee.me>
2026-02-25 14:15:04 +01:00
krapcys1-maker
200675741d fix(segment): guard min_should estimator edge cases (#8217)
Co-authored-by: local-user <local-user@local>
2026-02-25 11:07:34 +01:00
Luis Cossío
e28543a604 use UniversalRead in ImmutableDenseVectors (#8210)
* use UniversalRead in ImmutableDenseVectors

...renamed from MmapDenseVectors

* remove madvise arg

* async_raw_scorer
2026-02-24 13:55:16 -03:00
xzfc
28d9c5be12 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-02-24 16:43:59 +00:00
Ivan Pleshkov
6382d1a7d2 remove rocksdb from gpu tests (#8211) 2026-02-24 16:17:26 +01:00
Ivan Boldyrev
9bf8369a6a Use IdTrackerEnum type instead of dyn IdTracker (#8168)
* Use `IdTrackerEnum` type instead of `dyn IdTracker`

It would allow to be more flexible on the IdTracker trait, making it
dyn-incompatible eventually.

Coauthored with Claude Code.

* Review fixes
2026-02-24 10:53:23 +01:00
Andrey Vasnetsov
e1b8c05786 [AI] do not extend file before write (#8195) 2026-02-23 16:50:14 +01:00
xzfc
488765007f Use qdrant-rust-stemmers from crates.io (#8199) 2026-02-23 15:22:59 +00:00
Arnaud Gourlay
6ea4e74f3d Optimize HNSW plain-search filtered allocation (#8175)
* Optimize HNSW plain-search filtered allocation

* keep comment
2026-02-19 10:58:37 +01:00
Arnaud Gourlay
8813241975 Optimize process search results (#8163) 2026-02-17 15:42:18 +01:00
xzfc
4cabb7fd8e 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 10:58:59 +01:00
Arnaud Gourlay
cb533644c8 Optimize MmapPointToValues from_iter (#8158)
* Optimize MmapPointToValues from_iter

* fix const typo
2026-02-17 10:36:33 +01:00
Andrey Vasnetsov
0b68c7d0eb [manual] skip extra links indexing if vectors are deleted (#8125) 2026-02-13 13:58:42 +01:00
Luis Cossío
a43780941b [relevance feedback] add rest and grpc interfaces (#7399)
* add rest and grpc interfaces

Also handle inference for this query

* follow refactor from base branch

* renaming from Ms Cooper

* get started on validation testing

* more validations

* test equivalence with query when less than 2 feedback elements

* rename feedback query to relevance_feedback query

* fix extraction of context pairs

* rename feedback vector to example

* make coderabbit happier

* upd test

---------

Co-authored-by: Arnaud Gourlay <arnaud.gourlay@gmail.com>
2026-02-11 16:05:11 +01:00
Andrey Vasnetsov
688c65bf6f parse round floats as integers on payload indexing (#8100)
* parse round floats as integers on payload indexing

* use backward conversion to validate if float is actualy integerable

* fmt

* Use then_some

---------

Co-authored-by: timvisee <tim@visee.me>
2026-02-11 10:39:25 +01:00
Luis Cossío
a87c22f56b fix: handle score_threshold in Formula queries (#8097)
* handle `score_threshold` in Formula queries

* AI: add openapi test

prompt: Upload 4 points with a numeric payload, use the payload as the
score, and set a score threshold. We can assert which ids should be in
the result and which shouldn't
2026-02-10 17:28:27 -03:00
Andrey Vasnetsov
4437edb775 Weighted rrf (#8063)
* weighted rrf implementation

* test

* fmt

* fix edge

* validate number of sources and number of weights

* do not partial match

* upd schema

* review fixes

* update formula

* remove calcualtions from tests

* update comment, because AI have OCD

* fmt
2026-02-06 19:36:27 +01:00
Jojii
cf4158094b Don't lock SegmentHolder for the entire duration of read operations (#8056)
* Don't lock SegmentHolder during read operations

* Add comment clarifying eager segment allocation

* review fixes

* Remove TODO

* Shorter locking of segment holder in calculate_local_shard_stats

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-02-06 11:32:09 +01:00
xzfc
6bced54ca1 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-05 16:02:28 +01:00
Ivan Boldyrev
56799122b0 Split SegmentEntry into appendable and non-appendable part (#8047)
* Split `SegmentEntry`

Add `ImmutableSegmentEntry` for operations that can be applied to
immutable segments, and make the `SegmentEntry` as it subtrait.

* Rename to `NonAppendableSegmentEntry`

It differs semantically from `ImmutableSegmentEntry` by allowing point
deletion.  Move point deletion to the trait too.

* Fix docstring

* use NonAppendableSegmentEntry where possible

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
2026-02-05 15:46:58 +01:00
Luis Cossío
de3e7c58c1 cfg import behind linux flag (#8058) 2026-02-04 16:25:40 +01:00
xzfc
5a3dd12e02 Callback-based DenseVectorStorage::for_each_in_dense_batch (#8033)
* Generalized vector offset

* Replace get_batch-like methods with for_each-like methods
2026-02-04 07:06:23 +00:00
Daniel Boros
039d66fe40 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-03 18:13:38 +01:00
Jojii
a24377d615 Fix test consistency in random memory id tracker (#8043) 2026-02-03 15:37:43 +01:00
Andrey Vasnetsov
f403f6d00d Streaming snapshot unpacking (#8025)
* download tar

* compute sha256 for stream download

* wip: propagate unpacking into down to the logic, todo: validation

* unpacked snapshot validation

* Minor tweaks

* Fix typo

* validation during unpack

* cancellation token

* update docstring

* remove redundant dep

* Rearrange unpack functions

- Rename `safe_unpack.rs` into `tar_unpack.rs` so it would be listed
  near `tar_ext.rs` in IDEs.
- Replace calls like `ar = open_snapshot_archive(…); safe_unpack(ar, …);`
  with a single call to `tar_unpack_file(…)`.
- Put calls to `Archive::new(); Archive::set_overwrite(false);` inside
  `tar_unpack_reader` (was `safe_unpack`). So, now it is the only place
  that does `set_overwrite`.

* Let clippy complain if tar::Archive::unpack used

* Mock snapshot download URL

Instead of downloading from storage.googleapis.com every time the test
runs, put small snapshot file to the repo.

The snapshot file is created using this command:

    curl -s \
      https://storage.googleapis.com/qdrant-benchmark-snapshots/test-shard.snapshot \
    | tar \
      --delete segments/4ea958d8-0b64-4312-9a53-0cd857e93535.tar \
      --delete segments/65ac6276-8cca-4f5c-b767-9722190cee8b.tar \
      > lib/storage/src/content_manager/snapshots/test-shard.snapshot

File contents:

    $ tar tf lib/storage/src/content_manager/snapshots/test-shard.snapshot
    wal/
    wal/closed-255
    newest_clocks.json
    replica_state.json
    shard_config.json
    
    $ du -sh lib/storage/src/content_manager/snapshots/test-shard.snapshot
    12K	lib/storage/src/content_manager/snapshots/test-shard.snapshot
    
    $ sha256sum < lib/storage/src/content_manager/snapshots/test-shard.snapshot       
    5d94eac5c1ede3994a28bc406120046c37370d5d45b489a0d2252531b4e3e1f2  -

---------

Co-authored-by: timvisee <tim@visee.me>
Co-authored-by: xzfc <xzfcpw@gmail.com>
2026-02-03 12:19:18 +01:00
Ivan Boldyrev
984a9e8bd1 Fix gridstore Option unsoundness (#8011)
* Implement `Optional<T>` type

Define a type with the same presumed layout as `Option<T>`, but with defined behavior.

* Make `transmute_*` functions unsafe

The functions `memory::mmap_ops::transmute_*` are inherently unsafe, but
are not marked as are.  Their usage is documented, but it is not always clear
if the code is correct.

* Add `CsrHeader` to resolve another unsoundness

Tuples have no defined layout.
2026-02-03 17:57:09 +07:00
Tim Visée
7211d58b77 Apply clippy suggestions (#8029) 2026-02-02 15:11:43 +01:00
dependabot[bot]
18ef0758ca build(deps): bump sysinfo from 0.37.2 to 0.38.0 (#7994)
Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.37.2 to 0.38.0.
- [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/GuillaumeGomez/sysinfo/compare/v0.37.2...v0.38.0)

---
updated-dependencies:
- dependency-name: sysinfo
  dependency-version: 0.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-27 09:43:56 +01:00
Andrey Vasnetsov
64040511bc gridstore iter livelock (#7983)
* granular lock for writing and flushing pending updates in gridstore tracker

* avoid grigstore tracker lock in iterator
2026-01-26 11:47:26 +01:00
xzfc
ae607ee213 Fix hnsw_incremental_build benchmark (#7978)
* Fix hnsw_incremental_build benchmark

* More docs
2026-01-23 15:48:15 +01:00