mirror of
https://github.com/milvus-io/milvus.git
synced 2026-10-12 02:19:10 +00:00
master
571
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
48faae3b3a |
enhance: parallelize json stats build (#52120)
issue: #53765 JSON stats build benchmark — 500K rows per segment Concurrent segments || Non-parallel || 8 workers || Speedup 1 || 6.810 s || 1.641 s || 4.15× faster 4 || 7.140 s || 4.806 s || 1.49× faster 8 || 10.878 s || 9.658 s || 1.13× faster Setup: Release build, 12 CPUs, local filesystem, one warm-up followed by five measured runs; median values are reported. Data generation is excluded from the timing. Note: “Non-parallel” means each segment is built serially internally. Multiple segment builds are still launched concurrently in 8-segment cases. Signed-off-by: luzhang <[email protected]> Co-authored-by: luzhang <[email protected]> |
||
|
|
0df04194a6 |
fix: safely reuse Cargo build artifacts (#53522)
### What this PR does
- invokes the Tantivy Cargo build target on every CMake build so Cargo
fingerprinting decides whether Rust artifacts are fresh
- adds the optional `MILVUS_CARGO_TARGET_ROOT` Make variable for
persistent Rust build artifacts
- assigns separate `tantivy` and `milvus-storage` subdirectories below
that root
- redirects Corrosion's existing `cmake_build/cargo/build` target
through a symbolic link, without modifying the generated Cargo command
- migrates an existing generated `cmake_build/cargo` directory when the
persistent root is enabled for the first time
- preserves the current workspace-local build directories when the new
variable is unset
- keeps the existing direct `CARGO_TARGET_DIR` behavior as a
compatibility fallback for current CI callers
### Motivation
The previous `add_custom_command(OUTPUT libtantivy_binding.a)` did not
declare Rust sources, `Cargo.toml`, or `Cargo.lock` as dependencies.
Once the archive existed, CMake/Ninja could skip Cargo entirely and
silently reuse a stale library after Rust inputs changed.
Both Tantivy and milvus-storage's Rust bridge currently place Cargo
build artifacts below `cmake_build`, which CI workspace cleanup removes.
A single Milvus-owned cache root lets CI mount and manage one persistent
directory without knowing Rust component names, while Cargo remains
responsible for freshness within each workspace target.
### Cache layout
When `MILVUS_CARGO_TARGET_ROOT=/path/to/cache` is set:
```text
/path/to/cache/
├── tantivy/
└── milvus-storage/
└── build/
```
The `milvus-storage/build` suffix is retained because Corrosion already
passes `--target-dir=<cmake_build>/cargo/build`.
### Validation
- configured the updated Tantivy CMake file in an isolated CMake/Ninja
harness
- built `install_tantivy_target` repeatedly and verified Cargo was
invoked on every build
- verified an external Cargo target directory was used for the generated
archive
- verified `copy_if_different` preserved the installed archive timestamp
when its content was unchanged
- verified an existing generated `cmake_build/cargo` directory is
replaced by the persistent-root symlink
- verified a non-directory path at `cmake_build/cargo` is rejected and
preserved
- `bash -n scripts/core_build.sh`
- `git diff --check`
Full Milvus compilation with the new shared root has not been run
locally. The follow-up Jenkins change will mount a PR-scoped persistent
root and validate cold/warm builds for all three build-ut-cov variants.
Jenkins integration PR: zilliztech/vdc-jenkins#636.
Previous CI integration experiments: zilliztech/vdc-jenkins#631 and
zilliztech/vdc-jenkins#632.
---------
Signed-off-by: Zhikun Yao <[email protected]>
|
||
|
|
8c359cbaf6 |
enhance: Defer JSON stats initialization until first use (#53708)
## Purpose With JSON stats enabled, loading a sealed segment currently calls `JsonKeyStats::Load()` even when cache warmup is disabled. That reads JSON metadata and opens shredding Parquet readers before any query needs those stats. Collections with many sealed segments therefore pay storage-access and initialization costs for stats that may never be used. This change follows the deferred initialization model of file-backed text stats: with warmup disabled, segment loading registers the stats, and the first actual stats access performs initialization. The goal is to remove unused JSON stats initialization from the segment-load path. Fixes #53707 ## Implementation - Store a single-cell `CacheSlot<JsonKeyStats>` with a `JsonStatsTranslator`. `HasJsonStats()` checks registration without loading; `GetJsonStats()` pins the cell and returns an aliasing shared pointer that keeps the accessor alive. - Keep initialized metadata, path/type mappings, and column-management structures resident. Existing shredding-column and BSON-index slots continue to own and evict their payloads independently. The outer slot does not duplicate their payload accounting; its metadata remains segment-management overhead. - Aggregate the existing warmup inputs for the outer slot (`sync > async > disable`) and continue passing the existing configuration into `JsonKeyStats::Load()`. - Share the immutable load proto and create temporary loading configuration on demand. Register different fields through the existing thread pool, draining submitted work before unwinding on failure. ## Behavior and scope Cold first access pays the deferred initialization cost, and file-reading errors can surface at that access. Stats file formats and inner payload eviction granularity are unchanged. This PR does not claim a measured end-to-end latency or memory improvement. ## Validation - `CLANG_FORMAT=clang-format make cppcheck` passed on the rebased tree (clang-format 15.0.7); the working tree is clean. - Before rebasing from `56c674fabd`: C++ build with unit tests passed; all four focused cases passed after the final test cleanup (initial load, concurrent first access, expression routing/first-use/reuse, and warmup-policy aggregation). - An earlier broader JSON stats run passed 13/14 cases. The existing `JsonStatsBinaryRangeTest.ShreddingMatchesRawData` failed at the macOS bitmap cast in `ExprBatchTestUtils.h`; debugger inspection located the failure in the raw-data segment evaluation, before the stats-segment evaluation. - Rebased without conflicts onto `5ddad821c9`. `make verifiers` was attempted, but its C++ build is blocked on macOS by unchanged upstream code from #53483: `POSIX_FADV_DONTNEED` is undeclared in `BitmapIndex.cpp`, and `SaturatingAdd`/`SaturatingMultiply` have conflicting `size_t`/`uint64_t` template arguments in `IndexFactory.cpp`. Tests have not been rerun against the rebased tree; CI validation is pending. - No remote-S3 failure injection or end-to-end performance benchmark was run. --------- Signed-off-by: sijie-ni-0214 <[email protected]> |
||
|
|
2cbbb72041 |
feat: add an in-tree extension mechanism for distributions (#52981)
issue: #52979 design doc: docs/design-docs/design_docs/20260831-in_tree_extension_mechanism.md A distribution that compiles its own behavior into the milvus binary needs little from milvus: a way to install its request hook, the QueryNode's tuning hook and the cipher without a `.so`, a callback that starts its control-plane engine when the coordinator becomes active and stops it on shutdown, and a declaration that it runs the deployment shape its coordinator behaviors are written for. This PR is that seam and nothing else. A stock binary installs nothing and behaves exactly as before. An earlier revision of this PR shipped a table of typed capabilities consulted from many places in the tree. Reviewing it against what the distribution actually needs showed most entries were constants per deployment (configuration), duplicates of what the request hook already does, or answers that belonged on the wire. The table is gone; what remains is small enough to state here. ## Public surface (`pkg/extension`) ```go func SetHook(h hook.Hook) // hookutil prefers it over proxy.soPath func InstalledHook() hook.Hook type QueryHook interface { ... } // the queryNode.soPath plug-in's method set func SetQueryHook(h QueryHook) // the QueryNode prefers it over queryNode.soPath func InstalledQueryHook() QueryHook func SetCipher(c hook.Cipher) // hookutil prefers it over cipherPlugin.soPathGo func InstalledCipher() hook.Cipher type Coordinator interface { // the coordinator as its own clients see it rootcoordpb.RootCoordClient querypb.QueryCoordClient datapb.DataCoordClient } type CoordinatorEngine interface { Start(ctx context.Context, coord Coordinator) error Stop() error } func SetCoordinatorEngine(e CoordinatorEngine) func InstalledCoordinatorEngine() CoordinatorEngine func SetForm() // marks a deployment form installed, in every role func FormInstalled() bool // the coordinators' form-gated behaviors read it func WithQueryResourceGroup(ctx, rg) context.Context // set by a hook's Before func QueryResourceGroupFromContext(ctx) string ``` A distribution calls the setters it needs, then `cmd/milvus.Main(os.Args)` (exported so a distribution can ship its own `main`). - **Request hook.** `hook.Hook` (milvus-proto) is consulted by the proxy's unary interceptor for every RPC on the gRPC and REST surfaces, and by hand by the service's two streams, `CreateReplicateStream` and `DumpMessages`, in the same order and with the handler under the context `Before` returns; a test fails if the service declares a stream that does not. A compiled-in hook is used in preference to `proxy.soPath`; configuring both is refused at start-up. The compiled-in hook is initialized as a plug-in is: `Init` with the `hook.*` configuration before it is stored, and the `hook.*` reload watcher re-inits it on a config change. A failing `Init` is fatal at start-up when a form is installed, whatever `common.panicWhenPluginFail` says; a hook installed without a form follows the setting like any plug-in. - **Query hook and cipher.** The QueryNode's tuning hook (`SetQueryHook`) and the Go half of the cipher pair (`SetCipher`) can be compiled in the same way. Each is used in preference to its so path (`queryNode.soPath`, `cipherPlugin.soPathGo`), is refused beside it, and gets the same `Init` calls and watchers a plug-in gets. `cipherPlugin.soPathCpp` still declares that encryption is on, so a compiled-in cipher in a deployment without it stays idle. `optimizers.QueryHook` is now an alias of `extension.QueryHook`. None of the three slots implies another or `FormInstalled`. - **Coordinator engine.** `mixcoord` starts the installed engine once the replica is ACTIVE (a standby never starts it), on the coordinator client it uses itself, and stops it on shutdown. A start failure on activation is fatal. The engine reaches the coordinator only through `Coordinator`, so it can do exactly what a proxy can do. - **Query resource-group mark.** `WithQueryResourceGroup` pins a query to one resource group: the shard client routes it to the leaders whose replica lives in that group (`ShardLeadersList.resource_groups`, added on master by #52716) and the proxy attributes its latency to that group. Nothing in a stock binary sets it. ## Behaviors a form turns on by declaring itself These apply only when a form is declared (`extension.SetForm()`, which a distribution does in every role); a stock binary keeps master's semantics unchanged. `FormInstalled` is independent of `SetHook`: a distribution may install a request hook without switching any coordinator behavior on. - **Delegators on regular query nodes.** Under a form, a replica's shard delegators live on its regular RW query nodes, which watch the channel and read the WAL remotely, instead of on the streaming node's embedded query node; the streaming node is kept for DDL and the write ahead log. This lets a form load the same collection into several resource groups, one streaming node total. The trade is stated in the design doc: a Strong-consistency search no longer takes the WAL-MVCC shortcut, and the manual-flush prepare step is skipped with a warning. This shape has been exercised on a real one-streaming-node / multi-RG cluster, not only in unit tests: `scripts/walkthrough.py` (create, bulk-import ingest, index, load into a query cluster, cold and warm query, drop) and the e2e suite (55 tests, including two resource groups loading the same collection) run against a local k8s lake-form instance, and five concurrent rounds of two resource groups querying one collection return correct results with both replicas intact. - **A load request speaks only for the resource groups it names.** Loading a collection into `rg_b` does not restate the whole placement and evict it from `rg_a`; the groups the request does not name keep their replica count. A request naming no group states the whole placement. Per-group load progress is readable through `ShowLoadCollections` with `resource_group` set (appended proto field; `-1` means the group holds no replica of the collection). A load that only adds resource groups or replicas to an already loaded collection keeps the collection serving (an incremental expansion) instead of resetting it to loading, whether the added replica lands in a group the request newly names or one that already serves it; the checkers load the added replicas, as they do on every other path. An expansion replayed after a crash stays idempotent. - **Index engine version with no QueryNode session.** With no QueryNode registered, datacoord answers the index engine version compiled into the coordinator itself instead of `0`, and bounds an explicit target version by that same value, on the assumption that a QueryNode started later runs the same image. ## Removed from the earlier revision `common.security.requireAPIKey`, the `proxy.internalDomain.*` listeners, `queryCoord.resourceGroupScopedLoad`, `queryCoord.reloadSegmentOnIndexDrop`, `dataCoord.index.allowVectorIndexDropOnLoadedCollection`, `dataCoord.index.queryNodesScaleToZero`, the `RefusalResponse` hook extension, the capability table and `Provider`, and the link-time primary configuration file name. Each is either a deployment constant (configuration a distribution ships in its own files), something the request hook already does, or a default this PR now makes unconditional. ## Compatibility - `ShowCollectionsRequest.resource_group` is the only proto field this PR appends; an old peer leaves it empty and both sides read empty as "no scope". `ShardLeadersList.resource_groups`, which the query mark also reads, was added on master by #52716, not here; an old peer leaves it empty too and empty is read as "unknown". - `hook.Hook` is milvus-proto's and unchanged. No new configuration key. - `ResetForTest` is built only under the `test` tag. ## Testing - `pkg/extension`: setters, getters, the context mark, and the split between `SetHook` and `SetForm` (each answers without the other). - hookutil: compiled-in hook used, refused beside a plug-in, absent by default, initialized with the hook configuration, re-initialized by the reload watcher, a failing `Init` fails start-up when a form is installed even with `common.panicWhenPluginFail` off but follows the setting without one; compiled-in cipher used when `soPathCpp` is set, refused beside `soPathGo`, idle without `soPathCpp`, re-initialized on a `cipherPlugin.*` edit. - querynode: compiled-in query hook used, refused beside `queryNode.soPath`, initialized with the `autoIndex.params.*` configuration, not installed when it cannot initialize. - proxy: a hook-pinned resource group reaches the search task; per-group latency series exist only for pinned requests; both streams consult the hook, and every stream the service declares is one of them. - mixcoord: the engine starts on activation only, receives the coordinator client, is stopped once. - querycoordv2: scoped `ShowLoadCollections` (100 / -1 / unknown group refused); scoped load placement with and without a form declared; the expansion predicate's legs, a request that only adds a replica to an already-loaded group, and a replayed expansion; delegators placed on a regular query node under a form and on a streaming query node without one. - datacoord: zero-session engine version and its upper bound with a form declared; `0` without. - `golangci-lint` with the repo config on every touched package. One deliberate difference from the "stock binary is untouched" claim, listed rather than hidden: a stock binary with the streaming service on bypasses the channel checker's version cache for a tick when a replica's read-write node set is empty at that tick (a streaming node mid-restart). The cost is one extra `checkReplica` per tick; the case it exists for, a deployment that starts a replica's nodes on demand, is the form's. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_015JwRUhmz28AXHyuAJTSs3E --------- Signed-off-by: Cai Zhang <[email protected]> Signed-off-by: cai.zhang <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]> |
||
|
|
d510696ac2 |
enhance: load packed scalar indexes asynchronously (#53483)
issue: #51245 design doc: [Async packed scalar index loading](https://github.com/sparknack/milvus/blob/feat/async-packed-scalar-index/docs/design-docs/design_docs/20260907-async-packed-scalar-index-loading.md) Load packed scalar indexes through the shared async executor when `queryNode.segcore.storageV2.enableAsyncLoad` is enabled. Stream open and range reads use the milvus-common async interfaces. `PlanLoad` selects entry destinations; `ReadEntriesAsync` interleaves slices under global byte/slot admission and verifies CRCs; `FinishLoadAsync` initializes query state from the completed targets. File preparation, explicit writes, and cleanup use `LocalFileIOPool`. StringSort and Bitmap validity entries, and FMIndex null bitmap entries, read directly into their final `TargetBitmap` allocations. Preserve tail-bit handling and synchronous-path staging reservations. Bitmap mmap loading converts postings to frozen format in 16 MiB write batches during `FinishLoadAsync`. Includes packed scalar indexes and TextMatch `.v3`, with cancellation and failure cleanup. Small magic/footer and directory reads bypass admission; `_meta` payloads use slice admission. The design document includes architecture and sequence diagrams. Legacy index streaming, Knowhere, BSON, and JSON stats remain separate follow-ups. Dependency: [milvus-common #132](https://github.com/zilliztech/milvus-common/pull/132) and [Conan recipe #189](https://github.com/milvus-io/conanfiles/pull/189) are merged. The pinned version is `v1.0.0-fe62001`. The production Conan remote lists the recipe but returned no binary packages in the latest check. Local validation used a staged build matching the merged milvus-common source; installation from the production package remains unverified. --------- Signed-off-by: Shawn Wang <[email protected]> |
||
|
|
995429eb5e |
enhance: update master deployment image references to v3.0.2 (#53616)
Release v3.0.2: update the six deployment and standalone image references from v3.0.1 to v3.0.2 (GPU: v3.0.2-gpu). After the bind-mount ownership changes, both Compose services share the updated image anchor and standalone_embed.sh uses the updated MILVUS_IMAGE variable. Source tag: https://github.com/milvus-io/milvus/releases/tag/v3.0.2 Validation: git diff --check; bash -n scripts/standalone_embed.sh; docker compose config --quiet for CPU and GPU. No source-code or image-build changes. Signed-off-by: Zhikun Yao <[email protected]> |
||
|
|
ed7c7ff0d6 |
fix: initialize Docker bind mount ownership (#53549)
issue: #51221 related: #49775 ## What this changes - Add a one-shot volume initializer to the CPU and GPU standalone Compose files. - Resolve the numeric UID/GID from the same Milvus image and migrate `/var/lib/milvus` before the non-root server starts. - Write a UID/GID-specific marker only after a successful recursive migration, so large existing volumes are not scanned on every start and interrupted migrations remain retryable. - Prepare the bind mount in `standalone_embed.sh`, including when a previously created container is stopped after a permission failure. - Teach Docker deployment health checks to exclude one-shot services. - Document the ownership and restore contract. The initializer has no network, uses a read-only root filesystem, and mounts only the Milvus data directory. The Milvus server continues to run as `milvus:milvus`. This fixes both fresh rootful-Docker installations, where Docker creates the bind source as `root:root`, and upgrades from root-running images with root-owned data or cache files. It avoids the ineffective image-layer `chmod` approach from #51226 because a bind mount hides image-layer ownership and mode. ## Compatibility - The recursive ownership migration runs once for each image UID/GID. - A failed or interrupted migration does not create the marker and is retried. - Root-running older images can still read and write the migrated files on rollback. - After restoring files owned by another user, remove `.milvus-volume-owner-*` before starting Milvus to rerun migration. ## Validation - `git diff --check` - `bash -n scripts/standalone_embed.sh tests/python_client/deploy/utils.sh tests/python_client/deploy/check_healthy.sh` - `docker compose -f deployments/docker/standalone/docker-compose.yml config --quiet` - `docker compose -f deployments/docker/gpu/standalone/docker-compose.yml config --quiet` - Verified the deployment health-count expressions return the three long-running services. - Simulated the existing release bump regexes and confirmed both init/server image references and `MILVUS_IMAGE` are updated. Container-level startup was not run locally because the Docker daemon is unavailable; the Linux deployment CI must exercise the fresh-install and root-owned upgrade paths. --------- Signed-off-by: Zhikun Yao <[email protected]> |
||
|
|
ed018a736f |
[automated] Bump milvus version to v3.0.1 (#53142)
Bump milvus version to v3.0.1 on master Signed-off-by: sre-ci-robot <[email protected]> Validation: - exactly six release files changed - deployment and standalone embed CPU image tags validated - GPU image tag validated - git diff --check Signed-off-by: sre-ci-robot <[email protected]> Co-authored-by: sre-ci-robot <[email protected]> |
||
|
|
37f3a829e7 |
fix: make local storage keys complete paths at every layer (#53145)
issue: #53051, #53052, #53152 ## Summary Align local storage around one path contract: a key is a complete absolute filesystem path, and the local loon/Arrow filesystem is rooted at `/`. Previously, some writers used `minio.rootPath` while others supplied complete local paths to an already-prefixed filesystem, placing files in different physical locations from those expected by readers and GC. Remote keys remain complete bucket-relative object keys; their filesystem-root convention is unchanged. ## Changes - Unify Go/C++ local filesystem roots and StorageV3 manifest-base construction across writers. Preserve the existing base/version pair when continuing a growing-source manifest. - Fix local JSON/TEXT stats reads, rejected-stats cleanup, and explore temporary paths. Exercise resolved V3 stats paths through the actual `LocalChunkManager.MultiRead` interface. - Resolve legacy local manifest bases in loaded metadata and locally referenced snapshots, without eager catalog or manifest-file writes. Preserve manifest CAS compatibility and pathless V3 summaries; copy/restore writes use the target storage root. - Require an absolute, nonempty `localStorage.path` at initialization, including on remote deployments where it is a cache directory. Freeze forbidden parameters against configuration-source refresh while retaining explicit runtime/test overrides, and derive mmap, pprof, and disk-capacity defaults from the same canonical startup value. - Make segment deletion prefixes segment-boundary aware, retain root/identity and snapshot checks, and add BM25 orphan scanning. These shared GC changes also apply to remote storage; this PR does not claim every remote code path is untouched. - Remove the local test-only root override and unused local-only property initialization chain; use the production storage-config initialization path. ## Automatic local upgrade Let `R = localStorage.path` and `M = minio.rootPath`. Before standalone components start, local deployments check the known legacy locations: | Existing data | Upgrade handling | | --- | --- | | Canonical files under `R/<layout>` | Leave in place. | | Double-root files under `R/<R-without-leading-slash>/<layout>` | Move into `R/<layout>` for `insert_log`, `text_log`, `json_stats`, `index_files`, and `index_v1`. | | Recognized late-2.6 unified packed indexes under the process CWD | Move into the corresponding directory under `R`, if visible to the new process. | | Legacy manifest base `M/insert_log/<c>/<p>/<s>`, with files under `R/M/insert_log/<c>/<p>/<s>` | **Do not move the files.** Resolve the loaded manifest base to that existing absolute location. New segment layouts use the canonical root; updates to an existing legacy manifest can retain its base. | Migration prefers directory/subtree rename and recursively merges overlapping directories. Cross-filesystem moves fall back to copy-then-remove. Existing same-name files cause a conflict rather than content comparison or overwrite, except a published copy recognized as this migration's own interrupted work. The copy path synchronizes the file and target directory chain before deleting the source. Remaining sources are rediscovered on retry; empty legacy directories are pruned. Once migrated, restarts probe the known old locations without rescanning canonical data. The initial pass walks legacy file metadata but does not hash file contents. There is no configured migration timeout. SIGTERM/SIGINT cancels the migration and prevents etcd or components from starting; directory walks and cross-filesystem copies observe cancellation between filesystem reads. A canceled partial copy is never published and is recopied from the intact source on the next start. No user migration script, offline command, reverse migration, journal, or backup is provided. Successfully moved sources are removed. ## Compatibility and limits - Preserve the absolute local root, data mounts, and legacy `minio.rootPath` when upgrading. Canonical 2.6 data stays in place; misplaced late-2.6 indexes and affected 3.0.0/3.0.1 layouts are handled as above. Relative roots from older versions are unsupported. - Automatic migration is standalone/local-only. If old CWD indexes disappeared with an old container, they cannot be discovered: preserve/make those files visible or rebuild the derived indexes. Cross-filesystem copy has no configured timeout and can extend the first startup, but a shutdown signal cancels it and the next start resumes from the remaining source. - Downgrade to the affected old layout is unsupported after migration. Symlink layouts require manual resolution. - Known legacy LOB/orphan GC gaps under `R/M/insert_log`, pending old external-refresh paths, and rare interrupted-copy publication residue remain outside scope. This is not a claim that every historical file is recovered or reclaimable. ## Validation At head `898dba4b41`, `ci-v2/build-ut-cov` passed Build, Code Check, Integration UT, Go UT, and C++ UT (9,145/9,145). Diff coverage was 100% for C++ and 81.2% for Go; total patch coverage was 82.8%. Focused local tests for canonical/frozen `localStorage.path` derivation and migration cancellation/deadline/copy recovery passed with `-tags dynamic,test -gcflags='all=-N -l' -count=1`, and `git diff --check` passed before publication. Full paramtable execution remains locally blocked by tests attempting to create `/var/lib/milvus/data`; roles/native-dependent Go tests remain build-blocked by local C++ header/library mismatches. A real 3.0.0/3.0.1 version-to-version upgrade was not executed locally. `ci-v2/e2e-default` and `ci-v2/go-sdk` are still pending for this head. Signed-off-by: xiaofanluan <[email protected]> Co-authored-by: xiaofanluan <[email protected]> |
||
|
|
10a6bd999d |
enhance: make configuration projections safe by default (#52579)
issue: #49846 Design: [Safe Configuration Projections](https://github.com/liliu-z/milvus/blob/enhance/secure-config-projections/docs/design-docs/design_docs/20260826-safe-configuration-projections.md) Configuration diagnostics and management endpoints previously shared raw manager views with runtime consumers. Those views can expose credentials, connection topology, process-environment entries, and deletion tombstones. This change adds declared scalar/group metadata and safe projections while preserving the management configuration API's existing write contract. ## Behavior - Safe configuration views omit undeclared entries and mask sensitive values. Management point reads return `*****` for sensitive keys and reject undeclared keys. Registration and sensitivity decisions account for aliases and dynamic group namespaces. - `ParamItem.Sensitivity` uses `Auto` (zero value), `Sensitive`, and `NonSensitive`; explicit states override inference. Sensitivity controls projections and logging only. Generic management SET/DELETE retains the existing immutable, `mq.type`, and `common.security.adminAuthEnabled` restrictions, original request formats, caller-key handling, duplicate validation, and etcd transaction behavior. Sensitive, unregistered, and security-related settings remain writable unless an existing restriction applies. A successful write does not make its raw value visible through GET. - Built-in file/etcd publication and safe reads share a snapshot lock, keeping source values and their spelling classification together. Collisions and first-time spelling changes retain ambiguity across deferred ownership events and removal. Initial local file spellings are established before environment overrides. Raw manager getters retain their previous locking behavior and source priority. - Effective group reads omit tombstones; deleting or resetting an overlay through an alias addresses equivalent stored overlay spellings. - Sensitivity metadata is installed before scalar/group declarations become visible to concurrent refreshes, including fallback keys and the hook namespace. Positive inventories check actual declarations for reviewed credentials, connection targets, transport, authentication, trust, and routing settings, including the Pulsar tenant and namespace consumed by topic construction. Registration classification stays internal; audit tests use public reads and projections. - WAL configuration maps, management mutations, and dynamic config events omit request names and values from logs. Configuration parser, remote-source TLS initialization, and opaque plugin/callback diagnostics avoid echoing sensitive input. Immutable startup writes mask composite keys containing the protected root path. - Native plugin initialization reports the failed stage without the configured path, plugin-provided name, or opaque exception text. Sanitization precedes native exception observers and Go startup logs while retaining typed codes, allocation-failure classification, and untyped-exception counting. Go plugin wrappers preserve returned errors while suppressing their diagnostic text. - Kafka diagnostic strings mask credentials. `FieldBroadcastID` uses the native `uint64` type and preserves its full range through RPC metadata. Projections remain uncached O(N) diagnostic/management operations. Management authentication, authorization, and additional write restrictions are separate work; endpoint authentication is supplied by #52580, now included through master. This PR does not encrypt stored configuration or audit application-wide backend diagnostics and logs emitted inside out-of-tree plugins. ## Validation ### Merge with current master Validated merge commit `24a8c123fd` with master `2e0677c1d2`. All Go tests used `-tags dynamic,test -gcflags="all=-N -l" -count=1`. - Full `pkg/config` passed with an isolated embedded etcd server. - Focused ParamTable sensitivity, declaration ordering, projection, and lifecycle tests passed. - Config race tests passed for all normalized key spellings, cache entry/byte/concurrency bounds, owned request strings, sensitivity aliases, `knowhere` identity, and refresh consistency. - The actual config GET/ALTER handlers, extracted into an isolated adapter, passed retained coordinator regressions against real embedded etcd. Coverage includes ordinary and sensitive writes, redacted GET, admin-auth SET/DELETE rejection under five spellings, no partial writes in rejected batches, `mq.type` aliases, transaction failures, and omission of payload names/values from logs. - Full `internal/http` and `internal/util/adminauth` passed. `go vet` passed for config, ParamTable, and the extracted handler adapter; `git diff --check` passed. The real coordinator package could not compile locally because RocksDB and `milvus_core` native dependencies are unavailable. The extracted-handler checks do not replace native coordinator CI. ### Feature validation before the master merge Prior local validation used `-tags dynamic,test -gcflags="all=-N -l" -count=1`: - Full `pkg/config` suite passed with an isolated embedded etcd server. - Focused ParamTable tests passed for the sensitivity enum, scalar/fallback overrides, Pulsar resource selectors under dotted/slash/uppercase-underscore/collapsed spellings, raw runtime values, projections, callback logs, declaration audits, and credential/immutability rules. The Pulsar point-read regression failed on the prior head and passed after the fix. - Focused ParamTable `-race` tests passed for enum behavior, Pulsar resource visibility, and sensitivity registration before declaration visibility. - The retained coordinator regressions passed in an isolated adapter that extracts the actual configuration HTTP handlers and connects them to real embedded etcd. The same write-behavior checks passed against the pre-PR write handler. Coverage includes sensitive/unregistered/security settings, Pulsar tenant/namespace SET and DELETE across four key spellings, single and batch requests, empty values, omitted/null resets, raw storage values, redacted GET responses, original key spellings, immutable/WAL rejection, duplicate error behavior, and transaction atomicity. Revised-handler logs omit request canaries on successful writes and transaction failure. - `go vet -tags dynamic,test` passed for config, ParamTable, and the extracted current-handler adapter; `git diff --check` passed. Full ParamTable testing was attempted but stopped because existing tests require creating `/var/lib/milvus/data`, which this host cannot write. Full coordinator tests were attempted but could not compile on this host because RocksDB and `milvus_core` native libraries are unavailable. The extracted-handler checks do not replace the full coordinator/native CI run. Broader backend RPC error descriptions, third-party network-client diagnostics, and logs emitted inside external plugins remain outside the verified log-sanitization coverage. --------- Signed-off-by: Li Liu <[email protected]> Co-authored-by: OpenAI Codex <[email protected]> Co-authored-by: Claude Opus 5 (1M context) <[email protected]> |
||
|
|
e008a8429d |
enhance: add optional root authentication for the management plane (#52580)
issue: #49846 design doc: docs/design-docs/design_docs/20260912-management-plane-authentication.md Merge dependency: #52579 supplies safe configuration projections. Both changes are needed for the full configuration-redaction requirement in #49846. ## Problem and behavior Port 9091 exposes process shutdown, coordinator management, profiling, event logs, the web console, and legacy REST data operations. Add `common.security.adminAuthEnabled`, default **false**, to authenticate this surface independently of the main service port's data-plane authorization. When enabled: | Surface | Policy | | --- | --- | | `/management/*` except readiness; `/debug/pprof/*`; `/log/level`; `/eventlog`; `/webui/`; `/telemetry`; `/api/v1/_*` | Root HTTP Basic authentication | | Legacy REST data operations under `/api/v1` | Existing valid-user/API-key authentication if `authorizationEnabled=true`; otherwise root Basic authentication | | `/healthz`, `/livez`, `/metrics`, `/metrics_default`, `/management/check/ready` | Open | | `/api/v1/health` | Exempt from the new gate; existing data-plane authentication still applies | After the request-origin checks below, missing/incorrect credentials return 401; non-root users are rejected before password lookup with 403; unavailable credential storage and saturated verification return 503. Dependency details and stack traces remain out of unauthenticated response bodies. HTTP and Gin share one decision and carry a verified root principal through a typed request context for in-process telemetry calls. ## Browser and client requirements The gate rejects requests identified as cross-site or same-site. An unknown Fetch Metadata value and `Origin: null` are rejected as well. Top-level GET document navigation is allowed only on document surfaces, not operator actions or console APIs. **Credential-bearing requests without Origin or Fetch Metadata must include `X-Milvus-Admin-Request: true`.** This is required because missing metadata does not establish that a request is from a non-browser client; ordinary remote HTTP is outside the Fetch Metadata trustworthy-URL guarantee. An explicit header does not override a reported cross-site origin. The metrics-port CORS preflight must not grant this header to cross-origin callers. Browser console access requires HTTPS with Fetch Metadata preserved by the reverse proxy. A document request without sufficient request context is refused without a Basic challenge. Non-browser callers add the explicit header, for example: ```sh curl --user root --header 'X-Milvus-Admin-Request: true' \ 'https://milvus-admin.example/management/querycoord/balance/status' ``` The flag remains opt-in. Existing clients with the flag disabled keep their prior behavior. ## Credential lifecycle and resource bounds Verifier ownership is deterministic in standalone: Proxy, then MixCoord, then worker. Workers create a MixCoord client lazily. Each lookup caller has its own five-second wait bound, so a service-discovery call that ignores the backend context cannot block the HTTP request indefinitely. Its accounting slot remains occupied until the shared backend result completes, preserving the resource bound even in that case. Root hashes are cached for 10 seconds, reused for up to 10 minutes after their last successful fetch if refresh fails, and lookup failures are cached for 2 seconds. The stale window preserves management access during a coordinator outage but can also retain acceptance of a password rotated during that outage. Concurrent hash refreshes share work and admit at most 32 callers, including canceled callers whose singleflight result channels remain retained. Worker client construction uses a single shared completion signal; repeated lookup timeout windows no longer append a retained channel to a stuck constructor. Construction failure can be retried, and a client completed after shutdown is closed instead of published. bcrypt concurrency is bounded to a quarter of GOMAXPROCS, floored at two, with a bounded queue. This is a concurrency cap, not an attempt rate limit; on small pods sustained incorrect passwords can still consume substantial CPU. ## Registration, configuration, and event logs - `http.Register` refuses an unmarked operator route, including method- and host-qualified ServeMux patterns. Assembled-router tests and a console-prefix test cover Gin registration. - Milvus-owned handlers use a private mux. Flag-off compatibility with more-specific legacy DefaultServeMux routes is retained when pprof is enabled; enabling the gate removes that fallback. - `/management/config/alter` always rejects this flag, using the same `config.FormatKey` identity as config storage, so an anonymous caller cannot plant a disabling etcd value before the operator enables the gate. - Key-normalization caching admits at most 4096 entries and only keys whose input and normalized forms fit 1024 bytes, using owned string storage so short substrings cannot pin large request buffers. Larger keys still normalize correctly without retained memo entries. This bounds cache retention, not individual HTTP body size. - The eventlog gRPC stream switches to loopback with authentication enabled. A failed security upgrade closes the wildcard listener. Event-log shutdown uses a separate close signal and stops the gRPC server, preserving safe concurrent recording. - `milvus_admin_auth_total{endpoint,result}` records root-gate and origin decisions using registered route patterns; failure logs are rate limited. - The standard Go runner now includes HTTP, adminauth, coordinator, eventlog, and metrics regressions. It restores fail-fast behavior after sourcing the environment so a failed test command returns a failure from the runner. ## Compatibility and deployment Port 9091 remains plaintext. Use a trusted network or TLS-terminating proxy, rotate root using `UpdateCredential` / `db.update_password`, and update graceful-shutdown and profiling clients before enabling. Editing `defaultRootPassword` does not rotate an existing credential. Official compose deployments and embedded standalone scripts publish 9091, so review that exposure. Browser access needs the HTTPS deployment described above. Regardless of the flag, downstream operator routes without `AdminAuth` now fail registration; the admin-auth key cannot be altered through the management API; configuration normalization is bounded; pprof registration is explicit; and the data-plane stored-password comparison shares the credential-format helper. ## Verification and limits CI observed on head `c8992fc7b4d3fcf9a28bf73ad4700283922367f2` at **2026-09-12 14:30 UTC**: `ci-passed` and `dco-passed` are present. | Check | Result | | --- | --- | | [Build / unit / integration / code checks](https://jenkins-milvus-ci.milvus.io/job/MILVUS-CI-V2-PR-PIPELINES/job/milvus-build-ut-ciloop-pipeline/30883/pipeline-overview/) | SUCCESS; status reports build, code checks, integration, Go, and 9,106 C++ tests passed | | [Go SDK E2E](https://jenkins-milvus-ci.milvus.io/job/MILVUS-CI-V2-PR-PIPELINES/job/milvus-go-sdk-pipeline/15021/pipeline-overview/) | SUCCESS | | [Default E2E](https://jenkins-milvus-ci.milvus.io/job/MILVUS-CI-V2-PR-PIPELINES/job/milvus-e2e-pipeline-dispatcher/19796/pipeline-overview/) | SUCCESS | | Main CI trigger / DCO | SUCCESS | The non-gating Tencent Pulsar gray run reports `ERROR` because its downstream job could not be triggered. The previous PR head had the identical start failure. No Pulsar test result is claimed, and the precise trigger failure is unknown because Jenkins logs are inaccessible here. The TC-US shadow build and legacy Jenkins status still show pending; they are outside the master `ci-passed` requirements. No label was added manually. Local verification and remaining limits: All Go tests use `-tags dynamic,test -gcflags="all=-N -l"`. - Full `internal/util/adminauth`, including race detection, passed. A blocked-constructor regression retained 20,011 extra heap objects after 10,000 canceled waits before the fix and no retained growth after it. Cancellation, retry, panic, and a client completing after close are covered. Four blocked-backend scenarios cover cold cache, expired stale state, and correct/incorrect stale passwords; race runs repeated three times passed, including retained slots and recovery after release. - Full `internal/http` and its race run passed with the explicit-request-header changes, including 34 new net/http/Gin cases. `pkg/eventlog`, `pkg/metrics`, and `pkg/util/merr` also passed. - Configuration-normalization tests passed, including oversized inputs, Unicode expansion, and request-buffer ownership. The full config race suite passed excluding `TestEtcdSource`, whose two tests require a reachable external etcd and failed against this host's deliberately unavailable test endpoint. The config comment and ParamItem documentation match exactly. - The newly scheduled HTTP, adminauth, eventlog, and metrics commands passed with the runner's race and coverage flags. A dispatch harness checked all five package additions through the full and selected-group entry points. Ten injected command failures were swallowed before restoring fail-fast and now stop the runner immediately with the original nonzero status. Coordinator execution was unavailable locally; the subsequent native CI aggregate reports Go success. - Legacy Basic challenges are preserved on the main port, gate-off metrics routes, and the health exemption. A regression using the actual extracted parser with real Gin failed before the repair and passed after it; assembled-route and dynamic-gate compatibility tests were added to the native package suites. The subsequent CI Go check reports success; individual native test logs were not accessible here. - `internal/proxy`, `internal/distributed/proxy`, `internal/coordinator`, and `cmd/roles` cannot compile on this host because `milvus_core.pc`, `milvus-storage.pc`, and `rocksdb.pc` are unavailable. The subsequent native CI aggregate reports build and Go success; this does not change the local compilation limitation. - Full `make test-go` was attempted; native dependency construction failed in the host SDK linker (`library 'System' not found`) before the Go suite. This is not recorded as a passing full test run. - golangci-lint v2.11.3 built with Go 1.26.6 reported zero new issues in `internal/http`, `internal/util/adminauth`, and the changed config/eventlog/metrics/paramtable packages. Native-linked packages could not be linted locally; the subsequent CI code-check status reports success. - A real coordinator failover and a real browser console flow remain unverified. Unit and source-level failure tracing do not establish full browser credential replay or transport behavior. --------- Signed-off-by: Li Liu <[email protected]> Co-authored-by: Claude Opus 5 (1M context) <[email protected]> |
||
|
|
a7941e8b6f |
fix: add MinioChunkManager.cpp to segcore error boundary baseline (#53458)
issue: #53283 ## What Add `internal/core/src/storage/minio/MinioChunkManager.cpp` to the `milvus_storage` section of `scripts/segcore_error_boundary_baseline.txt`. ## Why master's `make static-check` is currently broken: ``` Start check segcore error boundaries ERROR: new file(s) reference 'milvus_storage' (ratcheted library). internal/core/src/storage/minio/MinioChunkManager.cpp ``` - #50768 (merged 09-11) introduced the ratcheted segcore error boundary check. - #53284 (merged 09-14 09:13Z) added `milvus_storage::` references to `MinioChunkManager.cpp`. Its CI ran without the check in scope, so the baseline was never updated. Evidence that this breaks things: - master post-merge `build-ut-cov` on `e3654ef` fails in Code-Check with this error ([#31153](https://jenkins-milvus-ci.milvus.io/job/MILVUS-CI-V2-PR-PIPELINES/job/milvus-build-ut-ciloop-pipeline/31153/)). - PRs whose head includes #53284 fail the same way, e.g. #53377 ([#31143](https://jenkins-milvus-ci.milvus.io/job/MILVUS-CI-V2-PR-PIPELINES/job/milvus-build-ut-ciloop-pipeline/31143/)) and #53456 ([#31158](https://jenkins-milvus-ci.milvus.io/job/MILVUS-CI-V2-PR-PIPELINES/job/milvus-build-ut-ciloop-pipeline/31158/)). - PRs merged after #53284 were not affected only because their CI ran before it landed. ## Why a baseline entry is acceptable The check requires a new consumer to classify errors on every path. In the new code, the only failing `milvus_storage` call (`BuildGcpProviderFromConfig`) is already mapped with `throw milvus_storage::ToSegcoreError(provider.status())`. That form is explicitly allowlisted by the script. ## Notes - The line was added by hand. Regenerating with `UPDATE_SEGCORE_ERROR_BASELINE=1` on macOS reorders entries (locale-dependent sort) and drops `pb/index_cgo_msg.pb.h`, which only exists after proto generation. - #53145 also adds this baseline line, but at a different position. A three-way merge applies without conflict but leaves a duplicate line. The duplicate is harmless to the script (it compares sorted sets), but whichever PR lands second should drop its copy. ## Verification `bash scripts/check_segcore_error_boundaries.sh` on upstream master `5c86e948be`: - before: exit 1 with the error above - after: `segcore error boundaries OK`, exit 0 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01PGMeYPnXk9FbvEB2uCJLj9 Signed-off-by: Li Liu <[email protected]> Co-authored-by: Claude Opus 5 (1M context) <[email protected]> |
||
|
|
82bcce8867 |
enhance: classify segcore errors across producers and enforce classification end-to-end (#50768)
## What Consume the producer-owned error classification at the segcore boundary and make the whole C++→Go classification drift-proof, so a segcore error is classified as **input** (caller's fault, non-retriable), **transient** (retriable) or **permanent** (non-retriable) instead of flattening to `UnexpectedError(2001)` or carrying the wrong retry default. Design + tracking: #50903. ## Changes - **T1** — register the storage fallback pair in `pkg/util/merr/segcore.go`: `StorageError(2044)` non-retriable, `StorageTransientError(2045)` retriable. - **T2** — `KnowhereStatusToErrorCode` → a switch with **no `default` + `-Werror=switch`** over the full `knowhere::Status`; add build-path variant `KnowhereBuildStatusToErrorCode` so a build-time OOM / disk read stays **retriable** instead of collapsing into a permanent `IndexBuildError`. - **T3/T4** — `ArrowStatusToErrorCode` delegates to the producer's `milvus_storage::ToSegcoreError` (retires milvus's duplicate mapper); audited and routed **25 storage arrow-status sites** that were collapsing to `2001` through the single mapper (extracted to `storage/StatusToErrorCode.h`), always preserving the arrow sub-code in the message. - **T5** — unmapped-code observability: `UnmappedSegcoreCodeTotal{code}` counter + rate-limited WARN via an observer hook (merr is a leaf package); registered on QueryNode and DataNode. Unknown code degrades to non-retriable, never panics. - **T6** — codegen + compile-time enforcement: a generated `SegcoreCode` type (from milvus-common's `EasyAssert.h`) + an exhaustive `classForCode` switch marked `//exhaustive:enforce`, with the `exhaustive` golangci-lint enabled opt-in — a new C++ code that is not classified fails lint (the C++→Go analog of `-Werror=switch`). - **§3 B-tier** — classify `marisa` and `simdjson` errors (build/load/parse) instead of collapsing to `2001`, sub-code in the message; simdjson optional-access (`NO_SUCH_FIELD`/`INCORRECT_TYPE`) stays a benign skip; the `loon_ffi` FFI boundary is untouched. - **Boundary hardening (adversarial self-review of this PR's own diff)** — closed the escapes that would defeat the mapping above: a `throw e;` slicing rethrow in `LoadWithStrategy` that destroyed the very codes the columnar-read mapping attaches (bare `throw;` now), the same slice in `MinioChunkManager::PreCheck`; `GetCoreMetrics` / `EstimateLoadIndexResource` / init-and-config entry points that could let an exception cross the C ABI and terminate the process; and every remaining extern-C entry that caught only `std::exception` now ends in `catch(...)` via the shared `CGoCatch.h` macros. - **Pin + semantics** — bump `milvus-storage_VERSION` to `11f8a36` (the milvus-io/milvus-storage#574 merge, which also contains #575) and align the no-detail `IOError` expectation with the settled semantics: the producer tags every known-transient failure with a retryable `ExtendStatusDetail`, so a bare `IOError` with no detail is unclassified and deliberately falls back to permanent `StorageError(2044)` — a stripped-detail NotFound now degrades to non-retriable (safe) instead of retriable (retry storm on a permanent 404). - **Wire pass-through (client-visible)** — a segcore error now reaches the client with its ORIGINAL code (2009 stays 2009, 2024 stays 2024) instead of collapsing to the `ErrSegcore(2000)` umbrella with the real code buried in the message. Family identity for `errors.Is` is preserved via inner/Unwrap; input/system/retriable classification unchanged. Guardrails: only in-band (2000-2099) codes pass through (garbage still collapses to 2000); cross-family mappings (2046 → wire 110) keep their sentinel's code. `ErrSegcoreUnsupported`/`ErrSegcorePretendFinished` move to the C++ values they represent (2001→2003, 2002→2033) — their old numbers squatted on C++ UnexpectedError/NotImplemented and would false-match under code-based `errors.Is`. Verified end-to-end on a live standalone (ef<k reaches the client as 2042, unsupported tokenizer as 2001); the three e2e assertions pinning the old 2000 updated. - **Remaining code-destroying sites** — the three classes that still swallowed a producer's classification before the cgo boundary are now gone from `internal/core/src` and `internal/core/thirdparty`: status-consuming `AssertInfo` (104 → 0, incl. ~47 arrow builder paths whose commonest failure is OOM, now retriable `MemAllocateFailed` instead of a permanent 2001), bare `throw std::runtime_error/logic_error/bad_alloc` (68 → 0 — these were not `SegcoreError`, so they collapsed to 2001 *and* falsely fired the untyped-exception observer), and `throw fmt::format(...)` (12 → 0 — it throws a `std::string`, which `catch (std::exception&)` cannot see at all). tantivy's 73 `AssertInfo(res.result_->success, ...)` (plus 10 raw-`RustResult` stragglers found later) now classify the rust error — originally by its Display prefix, since replaced by a proper `#[repr(i32)]` discriminant carried in `RustResult.error_code` (see the Aug-10 update below). Typed `ThrowInfo` sites: 894 → 1081. The ~1500 genuine invariant asserts are untouched — 2001 is correct for them. The long-standing FIXME about `err_code` not surviving the nested LOON FFI boundary is also resolved, delegating to `milvus_storage::ToSegcoreErrorCode` rather than duplicating its table. ## Verification **Verified in this PR:** - **Mapping correctness (unit-tested, in-process):** `test_knowhere_status_mapping.cpp` / `test_storage_error_code.cpp` / `test_exec.cpp` cover every mapper branch (knowhere Status incl. the build variant, arrow/extend status incl. `AwsErrorNotFound→ObjectNotExist(2017)`, permanent-S3 vs transient), plus `FailureCStatus` code preservation and both observer hooks firing. - **Code projection to Go (one hop, unit-tested):** `segcore_test.go` pins `classForCode` for every generated code and asserts `merr.Status(err).GetRetriable()` for transient codes; the T6 generator is idempotent and the `exhaustive` lint fails on an unclassified code. - **Full C++ suite:** 8213/8223 unit tests pass locally (10 skipped; Azure connectivity tests excluded), 8648 in CI, rebased on current master (one pre-existing, unrelated concurrency test excluded: `GrowingConcurrentReopenTest` deadlocks deterministically on current master with or without this PR — rwlock writer starvation in growing-segment reopen code this PR does not touch; reported separately). - **Static audit (grep-verifiable):** every storage arrow-status consumption site on the read path routes through `ArrowStatusToErrorCode`, and every extern-C boundary ends in a `catch(...)` tail. **Explicitly NOT verified here (follow-up):** - **Runtime fault injection.** No S3 throttle / 404 / OOM / corrupt-file failure has been triggered end-to-end in a running cluster. Transient codes reach Go with `retriable=true` (unit-tested projection), but the downstream consumption — `lb_policy` replica reroute on `merr.IsRetryableErr`, index/analyze scheduler retry — is pre-existing logic from #50221 and has **not** been driven by a real segcore transient error in this PR. This PR preserves classification for observability and correct retry defaults; the retry behavior itself is exercised only by its own pre-existing tests. ## Dependencies - ~~milvus-common `StorageTransientError(2045)` — zilliztech/milvus-common#102~~ **merged**. - ~~milvus-storage `ToSegcoreError` / packed `ExtendStatusCode` — milvus-io/milvus-storage#575 + #574~~ **merged; pin bumped in-tree to `11f8a36`**. - ~~knowhere three-way classification — zilliztech/knowhere#1704~~ **merged** (the milvus-side `KnowhereStatusToErrorCode` → thin delegate to knowhere's own `ToSegcoreErrorCode` is a follow-up, gated on a knowhere version bump). - ~~milvus-common untyped-cgo-exception observer — zilliztech/milvus-common#112~~ **merged and released as `1.0.0-1fd1160`; the pin now points at the published package.** All dependencies are in. ## Update (Aug 10) — full-population audit, LOON path, runtime observability The originally deferred FFI/LOON path is now **done on the milvus side**, and the audit was extended from the three grep-able classes to the *entire* 2001-producing population: - **Every remaining 2001 site read.** All 1,517 `AssertInfo` (four sweeps: errno fingerprint, failure-keyword messages, condition morphology, and finally **data provenance** — does the guarded value come from disk/network?) and all 198 explicit `ThrowInfo(UnexpectedError)` sites. ~290 were externally-triggerable and now carry typed codes: file/remote IO -> `FileOpen/Create/Read/WriteFailed` (retriable), mmap/allocation -> `MmapError`/`MemAllocateFailed` (retriable), persisted-format damage (CRC/magic/parquet meta/index-meta keys) -> `DataFormatBroken`, deployment config -> `ConfigInvalid`, request content -> `InvalidParameter`, a cancel-race -> `FollyCancel`. The ~1,400 kept sites are genuine invariants or cgo contracts where 2001 is the correct report. - **Two infinite-retry bugs.** Statically-impossible conditions (index_type x metric blacklist, per-type metric allowlists, json/geometry index gates) threw 2001 -> generic retry -> the build task spun forever; they now throw `Unsupported`, which `getStateFromError` maps to a terminal `JobStateFailed`. Missing `index_type`/`metric_type`/`min_gram`/`max_gram` keys in persisted index meta had the same loop on the load path; they are `DataFormatBroken` now. - **knowhere `expected<>` bypasses closed** (8 sites in `QueryResult.h`/`CachedSearchIterator`): iterator failures went through `AssertInfo` and discarded the Status knowhere had already classified; they now route through `KnowhereStatusToErrorCode`, so an OOM/disk failure during search iteration stays retriable. Preflight rewraps in `segment_c`/`boost_score` similarly preserved the original `SegcoreError` code instead of flattening to 2001+string. - **tantivy discriminant over the FFI.** `RustResult` now carries `error_code` (`#[repr(i32)] TantivyBindingErrorCode`, cbindgen-exported); the C++ mapper switches on the enum instead of parsing the Display text, and the inner `tantivy::TantivyError` is discriminated too (`IoError/Open*Error` -> Io/retriable, `DataCorruption/IncompatibleIndex` -> DataCorruption). Wording changes on the rust side can no longer silently degrade classification. - **LOON / FFI path (the deferred item), milvus side complete.** The Go funnel `HandleLoonFFIResult` dropped `err_code` entirely and wrapped every failure as `ErrLoonTransient` — a 404/access-denied/corrupt-data retried as transient. It now classifies by the producer's own `loon_ffi_is_retryable_errcode`; permanent failures carry the new `ErrLoonPermanent` and terminate retry loops (`pack_writer_v3` via `retry.Unrecoverable`; the external-refresh manager guard extended so behavior does not invert). On the C++ side `LoonErrCodeToErrorCode` is the single classification entry (low band -> hand table, extend band -> producer's `ToSegcoreErrorCode`, unknown -> producer's retryable probe), unifying the two previously-divergent `ThrowIfFFIError` helpers — `LOON_FILE_NOT_FOUND(12)` now converges to `ObjectNotExist(2017)` on both integration paths. Remaining LOON items (e.g. promoting FileNotFound into `ExtendStatusCode`) live in the milvus-storage repo. - **Regression guards.** `scripts/check_segcore_error_boundaries.sh` wired into `make static-check`: every `throw` in `internal/core/src` must carry a milvus ErrorCode (zero-tolerance; currently 0 violations); vendored `fmindex::` is confined to its boundary files; knowhere/arrow/milvus_storage/tantivy are ratcheted by a checked-in file-set baseline (new consumer files fail the check; shrinking is free). - **Runtime observability for what is left.** `milvus_cgo_unexpected_segcore_origin_total{origin="<file>:<line>"}` counts every 2001 crossing the cgo boundary by its C++ source location (parsed from the ` at file:line` suffix `AssertInfo` already emits, build paths collapsed to repo-relative). A site that fires in production names itself — reclassification becomes evidence-driven instead of re-reading ~1,400 asserts. Site count for the 2001 family: 1,955 on master -> 1,525 on this branch; the delta is reclassification into actionable codes, not deletion of checks. ## Deferred - milvus-storage-side LOON improvements: promote `LOON_FILE_NOT_FOUND` into `ExtendStatusCode`, category byte (design §4.7) — tracked in the storage repo. - knowhere-side: thin-delegate `KnowhereStatusToErrorCode` to knowhere's own `ToSegcoreErrorCode`, gated on a knowhere version bump. issue: #50903 --------- Signed-off-by: Zack <[email protected]> Co-authored-by: Zack <[email protected]> Co-authored-by: Claude Fable 5 <[email protected]> Co-authored-by: xiaofanluan <[email protected]> |
||
|
|
73e495d7d5 |
fix: keep installed C++ debug info self-contained (#53214)
## What this fixes Linux builds currently enable split DWARF by default, but Milvus installation and published debug images do not include the generated `.dwo` files. The installed ELF files therefore contain dangling DWO references and GDB cannot load the expected debug information. ## Changes - make split DWARF an explicit CMake opt-in, defaulting to OFF - expose `USE_SPLIT_DWARF=ON` through `scripts/core_build.sh` for build-only workflows that preserve `.dwo` files - keep the existing release image, tag, multi-arch manifest, and strip pipeline unchanged With the default build, debug information remains self-contained in the installed ELF files. The existing release pipeline can continue publishing the unstripped build as `-debug` and stripping the same build for the regular image without copying sidecar debug files into production images. ## Release impact - regular stripped images should retain their current layout and strip behavior - debug images can grow because debug sections are embedded instead of being left behind in the build tree - Release builds still use the existing `-g1`; changing the debug level or publishing `.dwp` artifacts is intentionally out of scope - the first C++ build after this flag change may have lower cache reuse ## Validation - `bash -n scripts/core_build.sh` - parsed `DefineOptions.cmake` with CMake - verified `MILVUS_USE_SPLIT_DWARF` defaults to OFF and accepts explicit ON - `git diff --check` Supersedes #53188, which was recreated from the contributor fork to follow the repository contribution workflow. Fixes #53182 Signed-off-by: Zhikun Yao <[email protected]> |
||
|
|
5f7ddf23d2 |
enhance: add async storage v3 field data loading (#51246)
issue: #51245 - Add an async executor and Storage V3 field-data load pipeline for manifest column groups and JSON key stats. - Group requested cells into contiguous, byte-bounded row-group read windows and admit each window through the shared transient-memory budget. - Preserve load priority, requested result order, cancellation, and the first storage or finalization failure across coroutine boundaries. - Route mmap finalization to the optional local-file I/O executor while keeping the legacy synchronous path as the default. - Add the temporary disabled-by-default rollout switch `queryNode.segcore.storageV2.enableAsyncLoad`; `storageV2` is retained only as the existing internal configuration name. --------- Signed-off-by: Shawn Wang <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]> |
||
|
|
720983fe5d |
test: add Scalar Index CMEK positive matrix (#52816)
## Summary - Add the positive Scalar Index CMEK matrix for engines 2, 3, and 5 across V2/V3 artifact formats. - Cover 17 cells with repository-owned Go/C++ CipherPlugin fixtures, authoritative object locators, independent V2/V3 envelope inspectors, release/load checks, and type-specific query oracles. - Verify database EZ ID inheritance and configured root-key material propagation: the strict fixtures now fail when an EZ key was not delivered, and the C++ fixture derives encryption keys from the exact forwarded root key. - Keep vector-index setup in every collection with an explicit FLAT/L2 index. - Keep `integration-test` as the aggregate CI gate: it depends on the existing non-CMEK scope and the dedicated CMEK scope, while only the CMEK target builds its fixture plugins. - Group the campaign tests by suite in the V2, V3, and FMINDEX suite files. ## Review follow-up - Complete the ASF license headers in all new source and CMake files. - Remove the unused text-log inspector wrapper. - Link the independent V3 inspector to the format design and production reader/writer sources to make drift reviewable without coupling the oracle to production decoding. - Keep large V2 EZ ID parsing local to the inspector with json.Number; this PR does not modify production descriptor decoding. - Split the default integration gate into `integration-test-base` and `integration-test-cmek`, exclude only the top-level CMEK package from the base run, and append CMEK coverage to the same `it_coverage.txt` only when invoked through the aggregate target. ## Verification - Controlled full Milvus build — passed after merging current master. - `make integration-test-cmek` — 23 tests passed in 3m02s. - CMEK fixture build regression — passed. - Target graph dry-run — the aggregate runs base before CMEK with append enabled, while standalone CMEK resets the single coverage file. - Strict Go fixture unit test — passed after reproducing the fallback gap. - Scoped V2/V3 inspector tests — passed. - `make fmt` — passed. - Controlled static-check — 0 issues in core, pkg, client, and go_client. - All commits are signed off. issue: #52815 --------- Signed-off-by: yangxuan <[email protected]> |
||
|
|
e36fbfdc2d |
fix: migrate archived hamba/avro to maintained fork and suppress plan-parser pseudo-version (#52782)
## Summary Address the remaining master image CVEs left after #52685 (which only bumped x/net, x/text, grpc). | CVE | Package | Severity | Remediation | |-----|---------|----------|-------------| | CVE-2026-46385 | github.com/hamba/avro/v2 v2.29.0 | High | Migrate to maintained fork `github.com/iskorotkov/avro/v2` v2.33.1 (direct imports) | | CVE-2026-46384 | github.com/hamba/avro/v2 v2.29.0 | High | Same; plus `replace github.com/hamba/avro/v2 => github.com/iskorotkov/avro/v2 v2.33.0` for transitive (Pulsar) consumers | | CVE-2026-26190 | github.com/milvus-io/milvus self-reference in libmilvus-planparser.so | Critical (scanner finding) | Build plan-parser with `-buildvcs=false` so the local module stays `(devel)` instead of stamping a misleading affected pseudo-version | The archived `hamba/avro/v2` has no fixed release (project archived Jan 2026); the published mitigation is to migrate to the maintained `iskorotkov/avro/v2` fork. The actual endpoint-auth fix for CVE-2026-26190 is already in master (PR #47277); the scanner flags the stamped pseudo-version, so this change suppresses the false positive. ## Change scope - `internal/snapshotio/snapshot.go`, `snapshot_test.go`, `storage/snapshot_data_test.go`: import `github.com/iskorotkov/avro/v2` - `go.mod` / `go.sum`: replace hamba direct require with iskorotkov v2.33.1; keep hamba v2.29.0 as indirect; add `replace` directive - `pkg/go.mod` / `pkg/go.sum`: add iskorotkov indirect + `replace` directive - `scripts/build_plan_parser.sh`: add `-buildvcs=false` ## Runtime image coverage Go-dependency and build-metadata changes only. All six published runtime Dockerfiles copy the same root-module `bin/milvus` and `lib/` outputs, so one dependency-graph change covers every image: - `build/docker/milvus/ubuntu22.04` - `build/docker/milvus/ubuntu20.04` - `build/docker/milvus/amazonlinux2023` - `build/docker/milvus/rockylinux9` - `build/docker/milvus/gpu/ubuntu22.04` - `build/docker/milvus/gpu/ubuntu20.04` No image variant is skipped; no per-Dockerfile package-manager change is required. ## Validation - `go mod verify` passed in root and `pkg`. - `go mod tidy` clean in `tests/go_client`. - `go build -tags dynamic,test ./internal/snapshotio/...` resolves the new module graph (fails only at the `milvus_core` pkg-config stage, which this checkout does not provide; CI rebuilds native deps). Auto-generated CVE fix (autonomous run). issue: #50763 Signed-off-by: Li Liu <[email protected]> |
||
|
|
3dfae89e93 |
feat: route general LIKE through FMINDEX with candidate recheck (#52697)
General LIKE with interior `%` or `_` was declined by FMINDEX even though PrefixMatch, PostfixMatch, and InnerMatch already use it. This routes VARCHAR Match through `ShouldUseOp`: split the pattern on wildcards, take candidates from the rarest literal fragment, then recheck those rows on sealed VARCHAR with `LikePatternMatcher` via `ProcessDataByOffsets`. FMINDEX load no longer materializes ISA. Match phase 2 rechecks candidate rows on sealed VARCHAR via ProcessDataByOffsets. The Match guard is locate-only again, the same occ times sa_sample_rate bound as Prefix, Inner, and Postfix. Empty-fragment patterns still decline. RegexMatch, equality, IN, TEXT, JSON, ARRAY, and growing segments are unchanged. FMINDEX Match is never served as unrechecked PatternMatch candidates through the ScalarIndex path. Design: `docs/design-docs/design_docs/20260708-fm_index_scalar_index.md` issue: #52683 ## How to test `LOCAL_STORAGE_SIZE=10` is required on this host. Without the VARCHAR recheck (product from `47f5cf5791`, tests kept): 5 FAILED (`ShouldUseOp(Match)` still prices Extract, so `%RARE%` / `%ZEBRA%` stay declined). With `7a3e274a36`: ``` source scripts/setenv.sh export DYLD_LIBRARY_PATH="$PWD/cmake_build/src:$DYLD_LIBRARY_PATH" LOCAL_STORAGE_SIZE=10 cmake_build/unittest/all_tests --gtest_filter='FMIndex.*' [==========] 23 tests from 1 test suite ran. [ PASSED ] 23 tests. ``` Includes `FMIndex.ExecutorPathMatchRechecksVarchar` and `FMIndex.MatchOracleEqualsBruteForce`. Whole C++ module (three Darwin crashers excluded): ``` export LOCAL_STORAGE_SIZE=10 internal/core/output/unittest/all_tests --gtest_filter='-JsonIndexTest.LargeInt64LiteralDoesNotAliasInDoublePathIndex:JsonFlatIndexExprTest.PreservesLargeInt64LiteralPrecision:SortBufferTest.*' [==========] Running 8326 tests from 473 test suites. [ PASSED ] 8167 tests. ``` None of the 138 failures are `FMIndex.*`. Reverse deps: Ngram 10/10, scalar/hybrid/inverted 26/26, json_stats_test 79/79, LikeConjunctExpr 1/1. /cc @xiaofan-luan --------- Signed-off-by: David Dallakyan <[email protected]> Signed-off-by: xiaofanluan <[email protected]> Co-authored-by: xiaofanluan <[email protected]> |
||
|
|
5097a4246b |
feat: add query view state machines (#51887)
issue: #40451 - QueryView protocol: add lifecycle states, per-node view payloads, bidirectional sync messages, and generated Go bindings - state machines: add shared QueryView value objects and focused Coord, StreamingNode, and QueryNode lifecycle implementations with unit tests - documentation: describe state transitions, recovery of versioned Up views, StreamingNode query-lease ownership, and TODO integration boundaries --------- Signed-off-by: chyezh <[email protected]> |
||
|
|
d3793e4463 |
auto: bump Milvus version to v3.0.0 (#52024)
Update the default Milvus release image references on master from v3.0-beta to v3.0.0. This is the master counterpart of #52016. Changes: - bump CPU deployment and binary examples to v3.0.0 - bump GPU standalone deployment to v3.0.0-gpu - bump standalone embed shell and batch scripts to v3.0.0 Validation: - exactly six release files changed - no targeted v3.0-beta image references remain - bash -n scripts/standalone_embed.sh - docker compose config --quiet for CPU and GPU standalone files - git diff --check Signed-off-by: Zhikun Yao <[email protected]> |
||
|
|
70f144a91c |
enhance: add delete/shard by namespace (#50153)
Shard data by namespace. issue: #50154 --------- Signed-off-by: sunby <[email protected]> |
||
|
|
ef166a673a |
enhance: support building core on macOS (Apple Silicon) with clang 19 (#50616)
issue: #50615 ## What this PR does Makes the C++ core build cleanly on **macOS (Apple Silicon) with Homebrew LLVM/clang 19**. > [!IMPORTANT] > **Scope / impact is NOT macOS-only.** Although this PR is framed as macOS/clang-19 enablement, two of the changes are **top-level `requires(...)` in `internal/core/conanfile.py`, so they apply to every platform, including Linux production builds:** > - **`azure-sdk-for-cpp` `1.11.3@milvus/dev` → `1.16.0@milvus/dev`** (5 minor versions, `force=True`). This is the SDK Arrow uses for the **Azure Blob remote-storage path**, so this is effectively a major Azure SDK bump on the **production Azure object-storage path for Linux deployments** too. > - **`arrow` recipe `17.0.0@milvus/dev-2.6#c743ea7a…` → `17.0.0@milvus/dev#f411aa73…`** — same Arrow version, but **rebuilt against azure 1.16.0** with a patched `FindAzure.cmake`. The Arrow **`package_id` (recipe revision) DID change**; it is not the same binary as before. > - **`libbson/1.30.6@milvus/dev`** added (also global, but new — no pre-existing behavior to regress). > > **Testing blind spot:** CI green proves compile/link/UT/e2e pass, but the UT and integration suites **do not exercise real Azure Blob read/write**, so the Azure object-storage path is **not covered** by this PR's CI. A real Azure Blob remote-storage regression is recommended before merge (see Verification). ### Why the dependency bumps are required for clang 19 - **azure 1.16.0**: azure 1.11.3 bundles an older `nlohmann/json` that uses `std::char_traits<unsigned char>`, which was **removed in libc++ 19** → 1.11.3 fails to compile on clang 19. 1.16.0 fixes this. - **arrow rebuilt against azure 1.16.0**: when Arrow is built from source on clang 19 it must link the same azure 1.16.0; the recipe also patches `FindAzure.cmake` to the monolithic `Azure` config so `find_package(Azure)` resolves. Hence a new Arrow recipe revision. ### Toolchain / build enablement - **`scripts/setenv.sh`**: probe LLVM 19/20/21 first (libc++ 17/18 `chrono operator<<` clashes with Arrow's vendored `date`; libc++ 19 fixes it). - **`scripts/3rdparty_build.sh`**: arm64 `-march=armv8-a+crypto+crc` so folly's F14 (SimdAndCrc on Apple Silicon) matches core/knowhere — fixes `F14LinkCheck` undefined-symbol link errors. - **`InvertedIndexTantivy.cpp`**: drop spurious `->template` on non-template members (clang 19 `-Wmissing-template-arg-list-after-template-kw`). ### Drop bsoncxx / libmongoc → libbson only The BSON layer used the **bsoncxx** C++ driver, whose CMake unconditionally builds mongo-cxx-driver → **libmongoc** → bundled **utf8proc**, which fails to configure under newer CMake/clang on macOS. Milvus only needs BSON (de)serialization. - New Conan package **`libbson/1.30.6@milvus/dev`** (libbson-only, `ENABLE_MONGOC=OFF`; recipe published to milvus conanfiles & production). - New **`src/common/bson_shim.h`** — a thin `milvus::bson` C++ layer over libbson's C API. - Migrated `bson_view.h`, `bson_builder.{h,cpp}`, json_stats consumers and unit tests off bsoncxx. - CMake: `find_package(bson-1.0)` + link `mongo::bson_shared`; removed FetchContent `thirdparty/bsoncxx`. All three global Conan requires (arrow / libbson / azure) pin an explicit recipe `#revision` for reproducibility. ## Verification - Full clean rebuild on macOS arm64 / clang 19: `bin/milvus` builds; `libmilvus_core` links **only `libbson-1.0.dylib`** (no libmongoc/mongocxx/utf8proc). - libbson / arrow / azure resolve from production Conan at the pinned revisions. - All 21 BSON unit tests (BsonView / BsonBuilder / DomNode) pass. - Full ci-v2 suite green on Linux (build / build-ut-cov / ut-cpp / ut-go / integration / e2e / go-sdk). - **TODO before merge:** real Azure Blob remote-storage read/write regression to cover the azure-1.16.0 / arrow-rebuild blast radius (not exercised by UT/integration). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: xiaofanluan <[email protected]> Co-authored-by: xiaofanluan <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]> |
||
|
|
6492fa011b |
enhance: remove unused C++ dependencies (rapidjson, OpenDAL backend) (#50552)
## What this PR does Removes two unused C++ third-party dependencies from `internal/core` to reduce dependency count, comprehension cost, and link/build surface. ### rapidjson Linked into `milvus_core` but has **zero `#include` usage** in the C++ sources (only a stale comment in `common/Json.h`). knowhere v3.0.3 and milvus-storage do not depend on it. Removes the conan requirement, `find_package(RapidJSON)`, and the link target. ### OpenDAL backend Experimental `ChunkManager` backend gated behind `USE_OPENDAL` (**default OFF**) — released binaries never built it. Removes `OpenDALChunkManager`, the vendored OpenDAL Rust dependency, and all `USE_OPENDAL` build plumbing (Makefile / core_build.sh / 3rdparty_build.sh / CMake). The Go-side `"opendal"` storageType value remains a backward-compatible alias to the standard remote chunk manager. ### Kept `simde` is **not** removed — knowhere v3.0.3 requires it (`find_package(simde REQUIRED)`, used in `src/index/sparse/codec/varintdecode.c`). issue: #50551 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: xiaofanluan <[email protected]> Co-authored-by: xiaofanluan <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]> |
||
|
|
e2787d3981 |
enhance: standardize error handling on merr + Sys/Input classification (#50221)
issue: #47420 ## What this PR does Project-wide migration of raw `fmt.Errorf` / `errors.New` in function bodies onto the `merr` framework, plus the Sys-vs-Input error classification and the machinery it drives (retriability, fine-grained metrics, segcore unification), plus the convention docs and a linter that keeps it from regressing. Scope: storage, proxy, coordinators (root/data/query), query node, data node, `pkg/util` & `internal/util`, expression parser, message queue, streaming, and misc packages. Bare raw-error usages went from ~3000 to a ~340 allowlist (package-level sentinels / build-tag / test sites). --- ## How to review this PR It is large but the vast majority is mechanical. Changes fall into three tiers; spend review budget on Part 2 and Part 3. ### Part 1 — Mechanical standardization (low risk, verify by rule) Each converted call follows one of a small fixed set of rules. To review, check that each site obeys the matching rule rather than reading every line: | Pattern | Rule | |---|---| | `fmt.Errorf("...")` originating a new error | → `merr.WrapErrXxxMsg("...")` with a code matching the failure's meaning | | Adding context to an existing typed error | → `merr.Wrap(err, "...")` / `merr.Wrapf(...)` — **preserves** the inner code (never `WrapErr*Err`, which overwrites it) | | Errors inside the streaming subsystem | → `status.New*` factories (StreamingError), **not** merr — this is the component-internal dialect (see `docs/dev/error_handling_guide.md`) | | Low-level / control-flow signal caught by `errors.Is` | → kept as a package-level `errors.New` sentinel (lowercase, same-package) | Conventions are documented in `docs/dev/error_handling_guide.md` (how-to) and `docs/dev/error_sentinel_convention.md` (rules + audit). A `gocritic`/`ruleguard` rule (`rawmerrerror`, in `rules.go`) enforces "no raw `return errors.New/fmt.Errorf`" under `make verifiers`. ### Part 2 — Behavior changes (review these closely) These are the sites where the wire contract or runtime behavior changes, not just the source text. Listed by category; representative locations given, full set in the diff. **A. gRPC wire-code shifts: `UnexpectedError(1)/Code 65535` → typed code.** Where a handler previously returned a raw error (collapsed to `Code=65535` on the wire), it now returns a typed merr, so the client sees a real code. The most common shift is to `IllegalArgument(5)/Code 1100` (ParameterInvalid). Touch points include datanode task handlers (CreateTask/Query/Drop), proxy Upsert, querynode GetMetrics, datacoord CreateIndex, httpserver query-response builder, and typeutil schema validation. One code refinement: an index-param validation moved `1100` → `1101` (ParameterMissing). **Client/SDK assertions and any code that switched on `Code=65535` for these paths must be re-checked** (the go_client e2e assertions were already aligned in this PR). **B. Prometheus `status` label contract change (externally visible).** The proxy metric's coarse `fail` / `rejected` values are split into `fail_input` / `fail_system` and `rejected_user` / `rejected_system` (in `requestutil.ParseMetricLabel`; auth/privilege rejections count as `rejected_user`), so dashboards can attribute a failure to caller vs operator. **Dashboards/alerts querying `status="fail"` must migrate to `status=~"fail_.*"`, and `status="rejected"` to `status=~"rejected_.*"`.** The in-repo Grafana dashboard is already migrated; external dashboards built on the old values silently go empty after upgrade. This is the one change that requires an ops-side migration. **C. Retriability semantics.** - C1: `merr.Status(err)` now forces `Retriable=false` when the error is an `InputError` — a malformed request can never succeed on blind retry, so clients never get the self-contradictory "your input is wrong but you may retry". - C2: `retry.Do` short-circuits an `InputError` (non-retriable) — **but only when the caller did not pass a `RetryErr` predicate**. The check is an `if c.isRetryErr != nil { ... } else if InputError { ... }` *mutually exclusive* branch (`pkg/util/retry/retry.go`): an explicit `RetryErr` takes precedence and bypasses the InputError abort. `retry.Handle` deliberately does **not** apply the InputError abort (its callers signal abort via `shouldRetry=false`). Four flusher startup callsites that must retry through transient "not ready" errors were given explicit `RetryErr` escape hatches. **D. segcore (C++→Go) error classification.** A single shared Go-side table (`pkg/util/merr/segcore.go`) maps each segcore code to a merr sentinel + InputError/signal category, replacing scattered hand-written `if errorCode == ...` switches in the cgo wrappers. **Wire `Code` values change for every segcore pass-through error, not just the remapped ones.** Named sentinels remap (C++ `2003` → merr `2001`, `2033` → `2002`, Folly/Knowhere codes likewise); **all remaining pass-through codes (`2004`–`2043`, previously surfaced to clients as raw C++ enum values) now serialize as `2000`** (`ErrSegcore`), with the original C++ code preserved in the `Reason` text (`segcoreCode=...`); unknown/future codes collapse to `2000` as well (pinned by the `wire_code_projection` test). Transient segcore classes (object storage / file IO / OOM / mmap / FieldNotLoaded — 11 codes) now report `Retriable=true`. **Any client switching on raw segcore codes in the `2004`–`2043` range must be re-checked**; the in-Reason code remains available for diagnostics. Signal codes (PretendFinished / FollyCancel) are recognized centrally. `errors.Is`-based control flow on these (e.g. scheduler skip/retry) is preserved. **E. InputError classification (25 sentinels + dynamic marks).** 25 sentinels in `errors.go` carry `WithErrorType(InputError)` (the Collection / ResourceGroup / Database families, `ErrIndexDuplicate`, `ErrParameterInvalid`, `ErrPrivilegeNotAuthenticated`, `ErrImportFailed`, `ErrQueryPlan`, ...), plus dynamic marks for the 8 segcore input codes (ExprInvalid, DimNotMatch, MetricTypeInvalid, FieldIDInvalid, ...) and `WrapErrAsInputError`. The widest blast radius is `ErrParameterInvalid` (1100): ~2335 `WrapErrParameterInvalid*` callsites now classify as input / non-retriable. Because of C1/C2 this changes retriability for any path that returns these. **The audit to confirm no transient path was mis-marked is the single most important review item** (see Part 3). One reverse correction: storage field-stats parsing moved from `ErrParameterInvalid` (input) to `ErrDataIntegrity` — a corrupted stored stat is data corruption, not user input. ### Part 3 — Known risks & traps (called out proactively) 1. **`merr.Wrap` vs `WrapErr*Err` (code-masking).** `WrapErr*Err` builds a `wrappedMilvusError{sentinel: ErrServiceInternal}` whose `code()` returns the *outer* sentinel — it overwrites the inner typed code and hides the `errors.Is` chain. This is intentional (use it to *deliberately* downgrade), but it was a recurring conversion defect; the rule "add context with `merr.Wrap`, downgrade with `WrapErr*Err`" is enforced by convention and reviewed across the diff. 2. **InputError × `retry.Do` blast radius.** Marking a sentinel `InputError` makes any `retry.Do(...)` without a `RetryErr` predicate stop retrying it. Reviewers should sanity-check that no transient use of the 19 newly-marked sentinels (especially `ErrParameterInvalid`) sits inside a retry loop that needed to keep spinning. The known flusher cases were handled (see C2). 3. **The ~340 raw-error allowlist.** What remains as bare `errors.New` is, by design: package-level sentinels (caught by `errors.Is`), `//go:build test` sites, and out-of-band trees (`cmd/`, `tests/`, codegen, walimpls). The linter only bans the *direct-return* form; assignment-then-return escapes and the full no-exceptions ban are deferred to an AST-based linter (Tier 2, documented). 4. **segcore C++ second step deferred.** This PR unifies classification on the Go side; splitting the dual-semantic C++ codes at the source is a follow-up. --- ## Validation - `make verifiers`: Go side clean (gofmt + static-check across modules, including the new `rawmerrerror` rule with a 0-hit baseline repo-wide). - `make test-go`: passing; the one real regression introduced (a datanode `invalid_task_type` assertion shifting `1` → `5` from a ParameterInvalid conversion) was fixed in-tree. - go_client e2e CreateIndex assertions aligned to the new merr messages. --------- Signed-off-by: zhenshan.cao <[email protected]> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]> |
||
|
|
385caab437 |
fix: use C++20 for Conan build profile (#50294)
issue: https://github.com/milvus-io/milvus/issues/47425 Milvus already asks Conan to build the C++ third-party stack with C++20 for the host profile, but Conan keeps the build profile separate. That means packages used during the build can still fall back to the default C++ standard, which caused protobuf and abseil to be compiled as gnu17 in some environments and fail during the dependency build. This change passes C++20 to the Conan build profile as well, so both the host context and the build context use the same language level. It applies the setting to both Linux Conan install branches in the third-party build script, including the gcc4 ABI path and the normal libstdc++11 path. Signed-off-by: jiaqizho <[email protected]> Co-authored-by: EC2 Default User <[email protected]> |
||
|
|
965e4b1564 |
build(deps): Upgrade knowhere and manage milvus-common via conan (#49912)
issue: https://github.com/milvus-io/milvus/issues/47425 # Plan: upgrade Milvus to Knowhere with Conan `milvus-common` and Conan OpenBLAS ## Context Milvus currently fetches both `knowhere` and `milvus-common` from source with CMake `FetchContent`. The requested Knowhere commit `0e53e57cd1f67f74decbdf9af42e74d0e3850155` expects `milvus-common` and Linux OpenBLAS from Conan 2.x instead: - `milvus-common/1.0.0-9ca5ea6@milvus/dev#274d428d85f1d3d996e1092f0c9c7144` - `find_package(milvus-common REQUIRED)` and target `milvus-common::milvus-common` - Linux `openblas/0.3.30` with CMake target `OpenBLAS::OpenBLAS` - macOS Apple BLAS/LAPACK via `BLA_VENDOR Apple`, not Conan OpenBLAS Milvus also currently installs system OpenBLAS in builder Dockerfiles, runtime Dockerfiles, dependency scripts, and packaging scripts. The intended outcome is one build-time OpenBLAS source on Linux: Conan. Runtime packaging should use the Conan-built shared libraries instead of relying on distro `libopenblas-dev`/`openblas-devel` where possible. ## Implementation 1. **Update Conan dependency pins in `internal/core/conanfile.py`.** - Add direct requirement `milvus-common/1.0.0-9ca5ea6@milvus/dev#274d428d85f1d3d996e1092f0c9c7144`. - Align dependencies required by Knowhere `0e53e57c`: - `folly/2026.04.20.00@milvus/dev#06852bea5b6449f0c4eb0df002b5779c` - `fmt/11.2.0#eb98daa559c7c59d591f4720dde4cd5c` - `lz4/1.10.0#982d9b673900f665a1da109e09c17cab` - `fast_float/8.0.0@milvus/dev#c7802833c74c5a86ffed70e4af1a795e` - Linux-only `openblas/0.3.30` - Add `openblas/*:dynamic_arch = True` to default options to match Knowhere. 2. **Move Milvus core build settings to C++20.** - Change `internal/core/CMakeLists.txt` from `CMAKE_CXX_STANDARD 17` to `20`. - Keep `OPENTELEMETRY_STL_VERSION=2017` unchanged; it controls OpenTelemetry ABI mode, not the language standard. - Change all `compiler.cppstd=17` Conan install settings in `scripts/3rdparty_build.sh` to `compiler.cppstd=20`. - Review `internal/core/src/storage/gcp-native-storage/CMakeLists.txt`; if it inherits incompatible flags or includes C++20-dependent headers, change its local `CMAKE_CXX_STANDARD 17` to `20` too. 3. **Expose Conan packages to Milvus CMake.** - Add `find_package(milvus-common REQUIRED)` in `internal/core/CMakeLists.txt` near the existing Conan `find_package(...)` block. - Add Linux-only `find_package(OpenBLAS CONFIG REQUIRED)` in `internal/core/CMakeLists.txt` so missing Conan OpenBLAS fails before Knowhere configures. - Remove `-DOpenBLAS_SOURCE=AUTO` from `internal/core/build.sh`; the requested Knowhere commit no longer consumes that flag and directly calls `find_package(OpenBLAS CONFIG REQUIRED)` on non-Apple platforms. 4. **Stop executing source FetchContent for `milvus-common`.** - Remove `add_subdirectory(milvus-common)` from `internal/core/thirdparty/CMakeLists.txt`. - Keep `add_subdirectory(knowhere)`. - Do not keep a compatibility alias to the old source target; all consumers should use the Conan target. - Leave `internal/core/thirdparty/milvus-common/` files in place for the first pass unless cleanup is explicitly desired; they will no longer be active once the subdirectory is removed. 5. **Pin Knowhere to the requested commit.** - Update `internal/core/thirdparty/knowhere/CMakeLists.txt`: - `KNOWHERE_VERSION` -> `0e53e57cd1f67f74decbdf9af42e74d0e3850155`. - Use the full SHA for deterministic FetchContent checkout. 6. **Migrate CMake links/includes from source target to Conan target.** - In `internal/core/src/CMakeLists.txt`: - Remove `${MILVUS_COMMON_INCLUDE_DIR}` from include directories. - Add `milvus-common::milvus-common` to `CONAN_TARGETS` so `milvus_conan_deps` propagates include directories to object libraries. - Remove plain `milvus-common` from `LINK_TARGETS`. - In `internal/core/unittest/CMakeLists.txt`: - Remove `${MILVUS_COMMON_INCLUDE_DIR}` from include directories. - Remove plain `milvus-common` from `all_tests` and `test_json_uint64` link lists; both already link `milvus_conan_deps`, which will carry `milvus-common::milvus-common`. 7. **Adjust build-time system OpenBLAS installs.** - Remove Linux build-time OpenBLAS package installs that can shadow or duplicate Conan OpenBLAS: - `scripts/install_deps.sh`: remove Ubuntu `libopenblas-dev`; remove Rocky/Amazon/CentOS `openblas-devel` where only needed for C++ core build. - `build/docker/builder/cpu/ubuntu20.04/Dockerfile`, `ubuntu22.04/Dockerfile`, `ubuntu24.04/Dockerfile`: remove `libopenblas-dev`. - `build/docker/builder/gpu/ubuntu20.04/Dockerfile`, `gpu/ubuntu22.04/Dockerfile`: remove `libopenblas-dev`. - `build/docker/builder/cpu/amazonlinux2023/Dockerfile`, `rockylinux9/Dockerfile`: remove `openblas-devel` and any OpenBLAS header symlink workaround that only supported system OpenBLAS. - `build/deb/build_deb.sh`: remove build-time `libopenblas-dev` install if no longer needed after Conan generation. - Keep Fortran/toolchain packages needed to build Conan OpenBLAS from source when binary packages are missing. - Do not change `scripts/install_deps_embd.sh` or `scripts/install_deps_msys.sh` in the first pass unless the target build path uses them; they are separate embedded/MSYS dependency paths and may still require manual/system OpenBLAS. - On macOS, remove `openblas` from `.github/workflows/mac.yaml` only after confirming the new Knowhere path uses Apple BLAS/LAPACK and Milvus has no other macOS OpenBLAS consumer. 8. **Adjust runtime/package OpenBLAS handling carefully.** - The runtime should still include `libopenblas.so*` if the Milvus binary or Conan-built Knowhere/Faiss links it dynamically. - Prefer copying the Conan-provided OpenBLAS shared library from `cmake_build/lib` or the Conan package output instead of installing distro development packages in runtime images. - Update packaging sites that currently copy or depend on system OpenBLAS: - `build/deb/build_deb.sh`: change the copied source from `/usr/lib/x86_64-linux-gnu/libopenblas.so.0` to the Conan/build output path if present. - `build/rpm/milvus.spec`: stop assuming `/usr/lib/libopenblas-r0.3.9.so`; use the packaged Conan/build output library. - Runtime Dockerfiles under `build/docker/milvus/**`: remove `libopenblas-dev`/`openblas-devel` only after confirming the image gets the Conan OpenBLAS `.so` with Milvus libs. - `build/docker/milvus/gpu/ubuntu20.04/Dockerfile.base`: review the explicit `milvusdb/openblas` stage; replace it with the Conan-produced library if that image path is still active. - Keep runtime `libgomp1`/`libgomp` and `libaio` if required by OpenMP/libaio-linked dependencies. 9. **Clean stale build state before verification.** - Use a fresh `cmake_build` or remove the old FetchContent checkout/cache before rebuilding; stale `MILVUS_COMMON_INCLUDE_DIR`, old `knowhere-src`, or system OpenBLAS paths can hide integration errors. Signed-off-by: yhmo <[email protected]> |
||
|
|
0ca60c5b47 |
feat: add commit_timestamp to SegmentInfo for correct MVCC/TTL/GC on import/CDC segments (#48472)
## What this PR does
Adds `commit_timestamp` (uint64) to `SegmentInfo` and `SegmentLoadInfo`
so that import/CDC segments use their logical commit time — not raw row
timestamps — for all temporal decisions.
**Problem:** When bulk-insert imports rows, the row timestamps generated
during the import process may be slightly older than the actual commit
time. Every time-based check in the system (MVCC snapshot visibility, GC
eligibility, collection-level TTL compaction triggering, delete-buffer
anchoring) sees these outdated timestamps instead of the actual commit
time, producing correctness bugs.
**Solution:**
Two-layer approach:
1. **C++ segcore (load-time overwrite):** During `LoadFieldData`, the
in-memory timestamp column is overwritten to `commit_ts_` when
`commit_ts_ != 0`. This makes existing MVCC/delete logic work correctly
with zero hot-path changes.
2. **Compaction normalization:** During compaction, all compaction paths
(mix/sort/clustering) rewrite row timestamps to `commit_ts` in output
binlogs, then set `CommitTimestamp = 0` on the output segment. After
first compaction, the segment becomes a normal segment with no special
handling needed. `commit_ts` is a temporary state that only exists
between import and first compaction.
**Key design decisions:**
- **TTL field (per-row):** Not affected by commit_ts. TTL field values
represent user-specified expiration intent and are honored as-is.
- **Collection-level TTL:** Uses `max(row_ts, commit_ts)` as the
effective row age to prevent premature expiration.
- **Delete/Upsert before commit_ts:** A delete/upsert with `ts <
commit_ts` does NOT take effect, because the row did not exist at that
time. The original `search_pk(pk, delete_ts)` logic handles this
correctly since `row_ts` is overwritten to `commit_ts`.
- **CommitTimestamp assignment:** Currently TODO in `import_checker.go`,
pending companion PR for 2PC commit flow.
## Changes
- `pkg/proto/data_coord.proto`, `query_coord.proto`, `segcore.proto`:
add `commit_timestamp` field
- `internal/datacoord/segment_info.go`:
`segmentEffectiveTs`/`segmentEffectiveDmlTs`/`effectiveTimestamp`
helpers
- `internal/datacoord/meta.go`: compaction completion mutations set
`CommitTimestamp=0` and normalize position timestamps via
`normalizePositionTimestamp` helper
- `internal/datacoord/compaction_trigger.go`: use `effectiveTimestamp`
for TTL compaction trigger
- `internal/datacoord/handler.go`, `garbage_collector.go`,
`compaction_task_l0.go`: use effective timestamp helpers
- `internal/querycoordv2`: propagate `CommitTimestamp` in
`PackSegmentLoadInfo`
- `internal/querynodev2/delegator`: use `segmentEffectiveTs` for
delete-buffer pin/list anchoring
- `internal/core/src/segcore/ChunkedSegmentSealedImpl`: overwrite
timestamp column at load time when `commit_ts_ != 0`
- `internal/datanode/compactor/timestamp_overwrite.go`: Record/Reader
wrappers for compaction timestamp normalization
-
`internal/datanode/compactor/{mix,merge_sort,sort,clustering}_compactor.go`:
apply timestamp overwrite during compaction
## Tests
- Unit tests: DataCoord helpers, `UpdateCommitTimestamp` operator,
`GenSnapshot` filter, GC eligibility, TTL compaction trigger
- Unit tests: QueryNode `segmentEffectiveTs`, delete-buffer pin at
commit_ts
- Unit tests: `timestamp_overwrite.go` Record/Reader wrappers
- C++ tests: MVCC gate, TTL gate, pre-commit delete not applied, normal
segment unchanged
- Integration tests: MVCC visibility, delete/upsert on import segment,
delete/upsert before commit_ts (should not apply), compaction normalizes
commit_ts to 0
## issue
issue: #48471
design doc:
https://github.com/milvus-io/milvus-design-docs/blob/main/design_docs/20260324-commit-timestamp.md
---------
Signed-off-by: Yihao Dai <[email protected]>
Signed-off-by: bigsheeper <[email protected]>
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
|
||
|
|
73eec01a0c |
fix: disable SDK default checksum to fix non-AWS S3 uploads (#49978)
issue: #49977 ## Summary AWS SDK C++ 1.11.692 (bumped from 1.11.352 in #47810) changed two defaults that together break PutObject against non-AWS S3-compatible storage: 1. `PutObjectRequest::GetChecksumAlgorithmName()` returns `"crc64nvme"` by default 2. `ClientConfiguration::checksumConfig::requestChecksumCalculation` defaults to `WHEN_SUPPORTED` `ChecksumInterceptor` then attaches a request hash to every PutObject, and the V4 signer switches the request to `Transfer-Encoding: aws-chunked` + `x-amz-content-sha256: STREAMING-UNSIGNED-PAYLOAD-TRAILER`. Aliyun OSS, Tencent COS, Huawei OBS, and GCP all reject this streaming form. This makes any `MinioChunkManager::PutObjectBuffer` call fail in an infinite `JobStateRetry` loop — json_stats / bson_inverted shared_key_index builds and any non-DiskANN-style index upload (IVF_*, HNSW, FLAT) are affected. ## Fix Restrict `requestChecksumCalculation` to `WHEN_REQUIRED` on non-AWS providers so the SDK only adds checksums when the operation model demands them (PutObject does not). Same approach as milvus-io/milvus-storage#500. Patched in both client construction paths: - `MinioChunkManager::MinioChunkManager` (storage_type=minio, address-based dispatch) — gated on `storageType != S3` - `ChunkManager.cpp` subclasses (storage_type=remote, cloud_provider-based dispatch) — applies in `GcpChunkManager`, `AliyunChunkManager`, `TencentCloudChunkManager`, `HuaweiCloudChunkManager`. `AwsChunkManager` keeps the default `WHEN_SUPPORTED`. CARDINAL_TIERED / DiskANN indexes already work because they upload via Arrow's `S3FileSystem` provided by milvus-storage, which was fixed in #500. ## Test plan - [x] Added `TEST(MinioChecksumConfig, OverridesAreWhenRequired)` in `test_storage.cpp` — asserts the override flips both directions from `WHEN_SUPPORTED` to `WHEN_REQUIRED` - [ ] Build / CI green - [ ] Manual smoke test on Aliyun OSS endpoint — index build (IVF_SQ8) and json_stats no longer fail with `x-oss-ec=0017-00000804`. CI cannot regression-detect this since MinIO doesn't reject `aws-chunked`; a real Aliyun OSS endpoint is required. ## Workaround (no code change) Setting `AWS_REQUEST_CHECKSUM_CALCULATION=when_required` and `AWS_RESPONSE_CHECKSUM_VALIDATION=when_required` on milvus pods also fixes this — the AWS SDK reads them at `ClientConfiguration` default-construct time, so it works across all bundled SDK copies without rebuilding. Useful for hotfix on running clusters until this PR ships. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: cai.zhang <[email protected]> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]> |
||
|
|
66fa592752 |
enhance: revert index_store_path full-path plumbing to montage assembly (#49805)
## Summary PR #49325 introduced collection-rooted index storage and also added a precomputed `index_store_path` string flowing through the build path. This PR scopes that back down: the collection-rooted layout stays, but the precomputed `index_store_path` string is removed from the write/build path. Build/write path: - DataCoord sends `IndexStorePathVersion` with the build job. - DataNode forwards the version to C++ indexbuilder. - C++ `FileManager` assembles the index object prefix locally from `(path_version, collID, partID, segID, buildID, indexVersion)`. Read/load path: - Go keeps passing full `IndexFilePaths` through DataCoord -> QueryCoord -> QueryNode -> cgo/segcore. - Load-side protos stay on full paths; no `index_file_keys` / `index_store_path_version` split is added there. - C++ load keeps PR #49325's direct full-path open behavior for `index_files/...` and `index_v1/...` paths. The v1 root is intentionally named `index_v1` before release. v0 remains `index_files`. issue: #49086 ## Compatibility note This PR is wire-incompatible with the short-lived #49325-era internal schema that carried `index_store_path`. That is intentional and acceptable because no release has shipped between the merge of #49325 and this rework. In other words, there are no released binaries or released persisted wire data that rely on the #49325-era `index_store_path` field semantics. This PR treats the proto changes as a pre-release schema correction rather than a compatibility migration. Because of that: - `BuildIndexInfo.index_store_path = 18` is replaced by `index_store_path_version = 18`. - `CreateJobRequest.index_store_path = 21` is removed. - `CreateJobRequest.index_store_path_version = 36` is kept. - We do not reserve the removed field numbers/names in this PR; if this schema had crossed a release boundary, we would reserve them and use fresh field numbers instead. ## What changes **Protos** - `worker.proto`: drop `CreateJobRequest.index_store_path`; keep `CreateJobRequest.index_store_path_version`. - `index_cgo_msg.proto`: replace `BuildIndexInfo.index_store_path` with `BuildIndexInfo.index_store_path_version`. - Read/load-side protos keep their full-path shape: no `IndexFilePaths -> IndexFileKeys` rename and no load-side `index_store_path_version` propagation. **C++** - `storage::IndexMeta`: replace `std::string index_store_path` with `IndexStorePathVersion index_store_path_version`. - `FileManager::GetRemoteIndexObjectPrefix()`: assemble v0/v1 prefixes from path version and IDs. - `FileManager::OpenInputStream()`: keep direct full-path open support for read/load paths. - `indexbuilder/index_c.cpp`: pass `index_store_path_version` into `IndexMeta`. - `DiskFileManagerTest`: cover v0 and v1 prefix assembly. **Go** - DataCoord `task_index.go`: stop building/sending `IndexStorePath`; continue sending `IndexStorePathVersion`. - DataNode `index/task_index.go`: forward `IndexStorePathVersion` to C++ build info. - DataNode `index_services.go`: drop logs for the removed `index_store_path` field. - DataCoord FinishTask validation and `SegmentIndex.IndexStorePathVersion` metadata remain unchanged. - GC/copy/import/snapshot/read path keep full-path behavior; only expected v1 root strings are updated from `index_files_v1` to `index_v1`. ## Notes for reviewers - The read/load path intentionally remains full-path based. QueryNode should not convert full paths to basenames or parse path version for load. - `IndexFilePathInfo.IndexStorePathVersion` remains as DataCoord metadata, but QueryCoord does not forward it for loading. - `metautil.IndexPathBuilder` remains needed for Go-side object storage operations such as GC, snapshot, copy-segment, and DataCoord `GetIndexInfos` path construction. - Mixed-version concerns are limited to unreleased #49325-era binaries, which is why this PR can remove/retype `index_store_path` without compatibility scaffolding. ## Test plan - [x] C++ build: `ninja milvus_core` clean. - [x] `DiskAnnFileManagerTest.GetRemoteIndexObjectPrefix_{V0BuildRooted,V1CollectionRooted}` covers v0/v1 prefix assembly. - [x] Updated Go/C++ tests for the `index_v1` root rename. - [ ] CI on this PR: code-check, UT, E2E. Signed-off-by: bigsheeper <[email protected]> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]> |
||
|
|
b664969c3b |
[automated] Bump milvus version to v3.0-beta (#49681)
Bump milvus version to v3.0-beta Signed-off-by: sre-ci-robot [email protected] Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
99097abea8 |
feat: support Sort/Bitmap/Hybrid index types for JSON Path Index (#48953)
this PR allows to create Sort/Bitmap/Hybrid index for json path index, and also removed the `JsonInvertedIndex` class, to use `InvertedIndexTantivy` directly for Inverted index type. C++ changes: - Add ConvertJsonToTypedFieldData<T>() to extract typed values from JSON field data with separate tracking of non_exist_offsets for EXISTS semantics - Add JsonScalarIndexWrapper<T, BaseIndex> template for Sort/Bitmap with dual file-manager pattern (original JSON schema for reading, cast-type schema for base index dispatching) - Add JsonHybridScalarIndex<T> with validity-aware cardinality counting - Add IndexBase::Exists() virtual method; override in Sort/Bitmap/Hybrid wrappers using non_exist_offsets (serialized via WriteEntries/LoadEntries) - Simplify ExistsExpr to use index->Exists() uniformly - Extend IndexFactory::CreateJsonIndex() to route STL_SORT/BITMAP/HYBRID Go changes: - Update STL_SORT/Bitmap/Hybrid checkers to accept JSON with cast_type and json_path validation - Change AUTOINDEX default for JSON from INVERTED to HYBRID - Bump ScalarIndexEngineVersion to 4 - Add version gate in DataCoord CreateIndex and snapshot RestoreIndexes - Update test fixtures to cover new (index_type, cast_type) combinations <img width="2380" height="708" alt="image" src="https://github.com/user-attachments/assets/8b3923a0-2cb3-4af7-b73a-b76d1d1ec2d0" /> issue: https://github.com/milvus-io/milvus/issues/48954 design-doc: https://github.com/milvus-io/milvus-design-docs/blob/main/design_docs/20260410-json_path_index_multi_type.md --------- Signed-off-by: Buqian Zheng <[email protected]> |
||
|
|
34c9f57ad5 |
enhance: support Conan installation on PEP 668 systems (Ubuntu 24.04+) (#48146)
Related issue: #48145 scripts/install_deps.sh fails to install Conan on Ubuntu 24.04 in two scenarios: 1. System Python (PEP 668): `pip install --user conan` fails with `error: externally-managed-environment` 2. Active virtual environment: `pip install --user conan` fails with `ERROR: Can not perform a '--user' install. User site-packages are not visible in this virtualenv.` Fall back to an isolated venv (~/.venv/conan) with a ~/.local/bin/conan symlink when --user install is unavailable. Behavior on Ubuntu 20.04/22.04, macOS, and Rocky Linux is unchanged. Signed-off-by: Vikhlyantsev Konstantin <[email protected]> Co-authored-by: Claude Sonnet 4.6 <[email protected]> |
||
|
|
7311d450a0 |
enhance: bump Go dependencies to v3 modules (#49485)
Related to #49398 Bump Go module references from pkg/v2 and milvus-proto/go-api/v2 to pkg/v3 and milvus-proto/go-api/v3 so the client tracks the Milvus 3.x release line. This prepares the repository for the upcoming 3.x.y release by aligning imports, module dependencies, and proto API references with the new major-version module paths. --------- Signed-off-by: Congqi Xia <[email protected]> |
||
|
|
10a6c5abba |
doc: add scripts/milvus-debug.sh for coredump analysis with debug image (#49084)
## Summary Add `scripts/milvus-debug.sh` to automate GDB coredump analysis using the `-debug` image that accompanies each Milvus release starting from v2.6.14. ## Background Starting with v2.6.14, each Milvus release publishes two image variants: | Tag | Content | Size | Use | |-----|---------|------|-----| | `milvusdb/milvus:<tag>` | **stripped** (production) | ~1/3 | Production deployment | | `milvusdb/milvus:<tag>-debug` | unstripped (full symbols) | full | GDB coredump analysis | The stripped production image is **byte-identical** to the debug image in its code sections (`strip --strip-debug` removes only `.debug_*` sections and symbol tables). So GDB can use the debug image's symbols to resolve addresses in a coredump produced by the stripped image. ## What the script does 1. Pulls the debug image 2. Mounts the coredump file read-only into a container 3. Installs `gdb` on demand (not present in the runtime image by default) 4. Launches GDB with `solib-search-path=/milvus/lib` so symbols from all shared libraries (`libknowhere.so`, `libtantivy-binding.so`, etc.) resolve correctly 5. Auto-prints the initial backtrace ## Typical usage after a production crash ```bash # 1. Copy the coredump out of the crashed pod kubectl cp <ns>/<pod>:/tmp/cores/core.<pid> ./core.<pid> # 2. Run this script (GDB starts automatically with backtrace) ./scripts/milvus-debug.sh ./core.<pid> \ milvusdb/milvus:v2.6.14 milvusdb/milvus:v2.6.14-debug ``` ## Test plan - [x] `bash -n scripts/milvus-debug.sh` (syntax check passes) - [x] Mirrors the documented procedure in the strip-image-coredump-debug-guide Feishu doc - [ ] Manual validation on a real coredump (waiting for v2.6.14 production crash; can be exercised with any coredump for now) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Zhikun Yao <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]> |
||
|
|
9fe5cddd02 |
enhance: preserve unchanged proto output timestamps (#49407)
## Summary - Preserve generated proto output mtimes when regenerated content is unchanged. - Back up generated files under `cmake_build/.proto-backup.*` during `generate_proto.sh`. - Avoid unnecessary C++ incremental rebuilds caused by unchanged `.pb.h` / `.pb.cc` timestamp churn. issue: #49406 Closes #49406 ## Test plan - [x] `bash -n scripts/generate_proto.sh` - [x] `git diff --check master...HEAD` - [ ] `make milvus-gpu` twice and confirm unchanged proto outputs no longer trigger proto-dependent C++ rebuilds 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: marcelo-cjl <[email protected]> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]> |
||
|
|
2a09964041 |
fix: use configured parallel jobs for ninja install (#49405)
#48783 Signed-off-by: luzhang <[email protected]> Co-authored-by: luzhang <[email protected]> |
||
|
|
7fc234d1fe |
build(deps): bump rust to 1.92 in builder images and install scripts (#49362)
issue: [#45691](https://github.com/milvus-io/milvus/issues/45691) ## Summary Bump rust toolchain `1.89 → 1.92` only in installation paths (Dockerfiles + install scripts). ## Why milvus-storage HEAD upgrades `iceberg` crate `0.8 → 0.9`, which declares `edition = "2024"` and `rust-version = "1.92"`. The new MSRV requires the builder image to ship rust 1.92 before milvus can take that milvus-storage commit. This PR is the **first step**: 1. Bump rust toolchain in installation scripts and Dockerfiles. 2. Once merged, builder image is republished with rust 1.92. 3. Follow-up PR will bump `.env` `DATE_VERSION` to the new tag, switch `cargo +1.89` → `cargo +1.92` in `internal/core/thirdparty/{tantivy,opendal}/CMakeLists.txt`, and bump milvus-storage to the iceberg-0.9 commit. This split avoids the chicken-egg problem: changing the cargo pin or milvus-storage version in this PR would fail CI, since the currently pinned builder image only ships rust 1.89. ## Files changed | File | Change | |---|---| | `scripts/install_deps.sh` | `RUST_VERSION="1.89"` → `1.92` | | `scripts/3rdparty_build.sh` | rust toolchain `1.89` → `1.92` (mac + linux paths) | | `build/docker/builder/{cpu,gpu}/*/Dockerfile` (7 files) | rustup `--default-toolchain=1.89` → `1.92` | | `DEVELOPMENT.md` | doc table rust version | ## Test plan - [ ] CI passes on existing builder image (no behaviour change for current build path) - [ ] After merge, builder image is republished with rust 1.92 - [ ] Follow-up PR can then bump `.env` and milvus-storage Signed-off-by: Wei Liu <[email protected]> |
||
|
|
5409a81f40 |
feat: support TEXT column with LOB storage for large text fields (#47567)
issue: #48783 design doc: https://github.com/milvus-io/milvus-design-docs/blob/main/design_docs/20260407-text_lob_storage.md Signed-off-by: luzhang <[email protected]> Co-authored-by: luzhang <[email protected]> |
||
|
|
d77009d654 |
enhance: support CONAN_CMD override in 3rdparty_build.sh (#49107)
Fixes #49106. Follow-up to #48165. Adds an opt-in `CONAN_CMD` environment variable so developers working on both master (Conan 2.x) and release-2.5/2.6 (Conan 1.x) on the same machine can select a Conan binary per-build without switching their default `conan`. See commit message for details. ## Test plan - [x] `make` with default conan (2.x) — unchanged behavior - [x] `CONAN_CMD=conan-1 make` — fails with clear version mismatch error - [x] `CONAN_CMD=/nonexistent make` — fails with clear error Signed-off-by: zhenshan.cao <[email protected]> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]> |
||
|
|
499619033f |
enhance: Migrate to Conan 2.x (#48165)
new JFrog artifactory for conan 2.x: https://milvus01.jfrog.io/ui/repos/tree/General/default-conan-local2 issue: https://github.com/milvus-io/milvus/issues/47425 conanfiles pr: https://github.com/milvus-io/conanfiles/pull/92 milvus-common: https://github.com/zilliztech/milvus-common/pull/69 milvus-storage: https://github.com/milvus-io/milvus-storage/pull/445 knowhere: https://github.com/zilliztech/knowhere/pull/1495 Signed-off-by: yhmo <[email protected]> |
||
|
|
98245e12a4 |
enhance: Introduce the support of Intel SVS (#48799)
related PRs: * https://github.com/zilliztech/VectorDBBench/pull/749 for vectordbbench * https://github.com/zilliztech/knowhere/pull/1537 for knowhere * https://github.com/milvus-io/milvus/pull/48798 for Milvus 3.0 Signed-off-by: Alexandr Guzhva <[email protected]> |
||
|
|
0449ea35a1 |
test: fix C++ UT portability on macOS (#48741)
## Summary - Skip `AzureChunkManagerTest` via TCP probe when Azurite emulator is not running locally - Remove Linux-specific `read()` single-call size limit assertion from `UtilIndex.ReadFromFD` - Fix `IterativeFilter.SealedIndex` platform-dependent RNG: explicitly construct int16 column with guaranteed coverage then shuffle - Skip faiss mmap tests on macOS with `#ifdef __APPLE__` — `MmappedFileMappingOwner` is not implemented in faiss upstream for Apple platforms (`mapped_io.cpp` only covers Linux/FreeBSD and Windows) After these fixes: **6745 passed, 25 skipped (all with documented reasons), 0 failed** on macOS ARM64. issue: #48740 ## Test plan - [ ] Run `internal/core/output/unittest/all_tests` on macOS ARM64 — expect 0 FAILED - [ ] Run `internal/core/output/unittest/all_tests` on Linux — expect no regressions (Azure/mmap skips are guarded by `__APPLE__` or runtime checks) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: james <[email protected]> Co-authored-by: james <[email protected]> Co-authored-by: Claude Sonnet 4.6 <[email protected]> |
||
|
|
6da09b8b02 |
[automated] Bump milvus version to v2.6.14 (#48744)
Bump milvus version to v2.6.14 Signed-off-by: sre-ci-robot [email protected] Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
79672130af |
enhance: optimize C++ build speed by ~25% (#48696)
## Summary - Optimize C++ compilation speed with minimal code changes and zero runtime impact (except tantivy codegen-units) - Measured **25% faster** on full clean build (j8, cold ccache): 17m39s → 13m13s ## Changes ### Compiler & Linker (`internal/core/CMakeLists.txt`) - `-g1` instead of `-g` for Release/MinSizeRel (smaller debug info) - `-pipe` for faster compiler inter-stage I/O - `-gsplit-dwarf` on Linux (smaller .o files, faster linking) - Auto-detect faster linker: mold > lld > gold > bfd ### Precompiled Headers (`src/CMakeLists.txt` + `cmake/milvus_pch.hxx`) - Apply PCH (STL + glog + fmt) to 15 OBJECT targets - Controllable via `USE_PCH=ON/OFF` (default ON) ### Tantivy (`Cargo.toml`) - `codegen-units=4` (was 1) — ~1-2% runtime cost for text search only ### Conan (`conanfile.py`) - Disable 8 unused Boost compiled modules ### Build Scripts - Pass PCH/Unity options through `core_build.sh` - `CONAN_CPU_COUNT` for parallel downloads ## Benchmark (j8, cold ccache, full clean build) | Metric | Before | After | Improvement | |--------|--------|-------|-------------| | **Total** | 17m 39s | 13m 13s | **-25%** | | Milvus src | 11m 36s | 8m 42s | -25% | | Thirdparty | 6m 03s | 4m 31s | -25% | ## Runtime Impact - `codegen-units=4` (Tantivy): ~1-2% slower for full-text search tokenization - All other changes: **zero runtime impact** ## Test plan - [x] Full clean build passes (`libmilvus_core.so` generated) - [x] Cross-platform: Linux flags guarded, macOS paths preserved - [ ] CI build verification - [ ] Run full test suite to verify no regressions issue: #48695 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: xiaofanluan <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]> |
||
|
|
c48aadd289 |
enhance: optimize LIKE pattern matching with SmartPatternMatcher replacing regex (#47310)
issue: #47307 Signed-off-by: xiaofanluan <[email protected]> Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]> |
||
|
|
b0ec4a2dd8 |
fix: upgrade Go to 1.25.8 for CVE-2025-68121, CVE-2026-27142, CVE-2026-25679 (#48286)
issue: #48574 ## Summary - Upgrade Go from 1.24.12 to 1.25.8 across all go.mod files and Dockerfiles - Fixes CVE-2025-68121 (CRITICAL), CVE-2026-27142 (HIGH), CVE-2026-25679 (HIGH) in Go stdlib - All three CVEs affect the Go standard library and are resolved by upgrading to Go 1.25.8 ## Changes - Updated `go` directive in go.mod files (root, pkg/, client/, tests/go_client/, examples/) - Updated Go download URLs in Dockerfiles (build/docker/builder/) - Updated `toolchain` directives where present issue: https://github.com/milvus-io/milvus/issues/TBD ## Test plan - [x] `make milvus` builds successfully with Go 1.25.8 - [ ] CI passes 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Li Liu <[email protected]> Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]> |
||
|
|
c54b34a880 |
enhance: enable OpenSSL FIPS mode for Milvus (#48331)
Layer 2 (OpenSSL FIPS) changes: - Add programmatic FIPS activation via OSSL_LIB_CTX_load_config in boring_enabled.go (gated by //go:build boringcrypto) - Add openssl-fips.cnf with fips + default providers and default_properties = fips=yes - Use absolute .include path for fipsmodule.cnf — OpenSSL resolves relative .include from the process working directory, not the config file's directory, causing silent FIPS provider load failure - Add RAND_bytes probe after config load to verify the FIPS provider is truly functional (EVP_default_properties_is_fips_enabled only checks the property string, not whether the provider loaded) - Dockerfiles: add openssl fipsinstall + OPENSSL_MODULES env var - Log OpenSSL FIPS status from C++ via EVP_default_properties_is_fips_enabled Layer 1 (Go BoringCrypto) changes: - Add GOEXPERIMENT=boringcrypto build flag (conditional on MILVUS_FIPS_ENABLED=ON) - Add boringEnabled() build-tagged functions for startup logging s2n-tls upgrade: - Override s2n 1.4.1 (from aws-c-io) to 1.6.0 in conanfile.py. s2n 1.4.1 only detects FIPS via the legacy OPENSSL_FIPS define (not set by OpenSSL 3.x). s2n 1.6.0 adds EVP_default_properties_is_fips_enabled() detection so s2n enters FIPS mode and uses RAND_bytes() through the FIPS provider. See also: #48202, #48301 Signed-off-by: yangxuan <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]> |
||
|
|
4c5ea64714 |
[automated] Bump milvus version to v2.6.13 (#48431)
Bump milvus version to v2.6.13 Signed-off-by: sre-ci-robot [email protected] Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
7dbe7e89d1 |
enhance: use RelWithDebInfo build type for CI to reduce peak compiler memory (#48154)
## Summary Switch CI pipelines from Release (`-O3`) to RelWithDebInfo (`-O2 -g -DNDEBUG`), reducing peak compiler memory by ~15%. RelWithDebInfo is a standard CMake build type that uses `-O2` natively and includes debug symbols for better crash diagnostics in CI. Production image builds remain at Release (`-O3`). ## Changes - Update Jenkins (PR, PR-Arm, PR-for-go-sdk, UT-CPP) to use `mode=RelWithDebInfo` - Update GitHub Actions (`main.yaml`) to use `mode=RelWithDebInfo` - Allow all standard CMake build types in `3rdparty_build.sh` validation - Add gcc>=13 implicit include workaround in `CMakeLists.txt` ## Test plan - [ ] CI builds with `mode=RelWithDebInfo` use `-O2` instead of `-O3` - [ ] Default builds still use Release with `-O3` - [ ] ASAN CI jobs pass with reduced memory usage issue: #48400 Signed-off-by: xiaofan-luan <[email protected]> Signed-off-by: xiaofanluan <[email protected]> Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]> |
||
|
|
8900b46f45 |
fix: split macOS RPATH into separate -r flags for linker compatibility (#48241)
## Summary
- macOS `ld` treats each `-r` flag as a single directory path, unlike
Linux `ld` which accepts colon-separated paths
- Since
|