Skip to content

v2026.2.0

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 28 Jul 06:40
b732543

What's Changed

☢️ Breaking changes

  • ClassSchemaAnalyzer ignores annotation flags reverting to default (one-way ratchet) (#1199)

    Schema analysis from annotated model classes is now symmetric: reverting a boolean-style annotation flag (e.g. nullable, unique, filterable) to its default now clears the corresponding schema setting on the next re-analysis, instead of silently leaving the previous value in place. Classes that relied on a manually-set flag surviving re-analysis after the annotation stopped declaring it must now declare that flag explicitly.
  • Histograms: add range source-attribute support and multi-histogram schema (#1161)

    Reference histograms can now be built from range-typed attributes (e.g. price bands, capacity intervals) in addition to scalar numeric ones, and a single reference can define multiple histograms instead of just one. Existing single-histogram configurations using @Reference(bucketed = @Histogram(...)) must be rewritten to the array form @Reference(bucketed = {@Histogram(...)}).
  • REST referenceSummary schema rejects requirements as object and omits entityGroupFetch (#1160)

    The REST referenceSummary (and per-reference variants like referenceBrandSummary) requirements field is now an array of single-key containers — {"entityFetch": {...}}, {"entityGroupFetch": {...}} — instead of a single object combining both keys, and entityGroupFetch is now accepted at all. Existing REST requests that sent requirements as one object with entityFetch/entityGroupFetch side by side must switch to the array form.
  • Price histogram for LOWEST_PRICE entities ignores inner-record granularity (#1159)

    The priceHistogram extra result now reflects one data point per inner-record price (selected by price-list priority) for entities using LOWEST_PRICE handling, instead of collapsing each entity to a single representative price. Bucket counts and thresholds for LOWEST_PRICE catalogs will shift after upgrade — storefronts with hard-coded bucket expectations should re-baseline.
  • Introduce HostSystemEvent on system CDC stream — fix external APIs missing catalog availability after auto-upgrade (#1151)

    Fixes a bug where a catalog auto-upgraded during boot stayed invisible to GraphQL, REST, and the Lab UI until the server was restarted. Introduces a new, opt-in HostSystemEvent category on the system CDC stream for host-local signals; existing subscribers that don't explicitly opt in see no change in behavior.
  • Enforce WAL-first discipline for engine state to prevent version/WAL drift (#1137)

    Closes several internal paths where the engine's state version could advance without a matching WAL entry, which could permanently wedge the engine and require manual repair. Startup now validates the WAL/state invariant, recovers a single in-flight step automatically via forward replay, and fails loudly instead of continuing on unrecoverable drift.
  • More optimized data structures in indexes & more granular storage parts (#760)

    Reworks core index storage (attribute, filter, sort, price and reference indexes) onto transactional B+ trees and moves to leaf/page-granular persistence, so a transaction persists only the part of an index that actually changed instead of rewriting it whole — reducing write costs on high-cardinality entities and storage-layer vacuuming pressure.
  • Compute "dynamic" set of attribute histogram for references (#8)

    GraphQL's Histogram type becomes an interface implemented by BaseHistogram (a direct replacement); the REST OpenAPI Histogram schema is likewise replaced by BaseHistogram, which extends it; and the GraphQL attributeHistograms extra-result field is removed, its functionality replaced by histogram statistics available directly on reference summaries.

🚀 Features

  • Fork RoaringBitmap into a persistent, transactional data structure

    evitaDB now maintains its own fork of RoaringBitmap (vendored as evita_roaring_bitmap), reworked so bitmaps are a persistent, copy-on-write data structure instead of requiring a full clone on every write. This lets bitmap-backed indexes participate in the same transactional, snapshot-isolated model as the rest of the storage layer. Landed under the broader index-rework effort in #760, but significant enough to call out on its own.
  • Granular transaction conflict resolution (#503)

    Introduces a schema-declared, hierarchically inherited conflict-resolution model that can be tuned from entity-level down to a single attribute, price, or reference, instead of a single engine-wide entity-level policy — reducing false rollbacks on concurrent updates that touch the same entity but different, semantically independent data.
  • Cheap savepoint snapshots: eliminate the O(N²) per-entity rollback cliff (#1252)

    Removes an O(N²) cost cliff in per-entity transaction rollback: savepoint snapshots of shared diff layers (unique-attribute, faceted-reference and price indexes) no longer grow with the number of entities already touched in the same transaction, so large batch transactions with per-entity rollback stay cheap regardless of batch size.
  • perf: reduce OffsetIndex compaction memory churn and page-cache impact (#1157)

    Reduces the allocation churn generated by OffsetIndex compaction on large entity collections, cutting the G1 old-generation pauses (previously up to ~2s on large files) that could otherwise surface as request timeouts on concurrently running queries.
  • New groupHaving filtering constraint (#1088)

    Adds a groupHaving filtering constraint that lets a query filter entities by a reference whose group entity satisfies a given filter — previously there was no way to express this.
  • Support for getting full price range for variants of a single master product (#1086)

    Adds a getPriceRangeForSale* family of methods to PricesContract that returns the lowest and highest price alongside the selling price in a single call, covering all three inner-record-handling strategies (NONE, LOWEST_PRICE, SUM) — useful for rendering a price range across a master product's variants.
  • Add aggregated crc32 checksum to WAL log (#1062)

    Adds a rolling CRC32 checksum after every WAL record covering all preceding records, so WAL corruption can be detected at the byte level; existing WAL files are automatically upgraded to the new format.
  • Coalesce GraphQL / REST schema refresh on catalog schema changes (#1153)

    GraphQL and REST no longer rebuild their per-catalog schema on every individual engine mutation or transaction commit; the rebuild now fires only when the catalog schema version actually changes, removing redundant rebuild work during bulk schema definition and on every data-only commit.
  • Traffic recording: on-demand export of the disk ring buffer contents, plus bug-hunt & JMH performance hardening (#1282)

    Adds an on-demand export of the traffic-recording disk ring buffer as a downloadable zip, triggered over the gRPC traffic-recording service, so recorded traffic can be pulled off a running instance and replayed or analyzed elsewhere without waiting for the buffer to roll over.
  • Performance: reuse memoised filter formula tree for hierarchy statistics instead of re-planning (#1141)

    Speeds up hierarchy statistics computation by deriving each per-statistics-base filter from the already-planned main query formula tree instead of re-planning it from the constraint tree, reducing planning overhead on queries with several hierarchy statistics variants.
  • Add support for filtering greater / lesser / between for primaryKeys (#1085)

    Adds greater-than / less-than / between filtering constraints for primary keys, alongside the existing equality-based ones.
  • Support also distance 0 for specific queries (#499)

    stopAt(distance(...)) now accepts 0, letting hierarchy traversal (children, parents, siblings, fromRoot, fromNode) stop right at the pivot node without expanding into its descendants — useful for rendering a breadcrumb or menu header alongside statistics(...) counts for the full subtree.
  • Introduce GroupConstraint and align single-variant Child handling between schema builder and resolver (#1147)

    Fixes groupHaving's inner filter constraints so they correctly target the referenced group entity instead of being accidentally routed to the referenced entity itself, and resolves a case where the groupHaving selector inside histogram statistics could be silently dropped from GraphQL/REST requests.
  • expose engine settings and capabilities via GetEngineSettings management RPC

    Adds a GetEngineSettings management RPC that reports the engine-wide default conflict resolution plus which capabilities (time travel, change data capture, traffic recording, query cache) are enabled — unlike getConfiguration, it carries no sensitive values and stays readable even when the engine runs in read-only mode.
  • Expose evitadb_build_info metric (version, commit, java_version) (#1146)

    Exposes an evitadb_build_info{version, commit, java_version} Prometheus gauge so the running evitaDB version and build commit can be read directly off a metrics scrape, without querying the management endpoint or checking logs.
  • dedicated traffic-recorder metrics; opt MemoryNotAvailableException out of error monitoring

    Adds a dedicated set of traffic-recorder Prometheus metrics (off-heap block usage, active sessions, disk-buffer occupancy, throughput counters) and stops counting the internal MemoryNotAvailableException control-flow signal as an engine error, so genuine engine faults are no longer diluted by benign traffic-sampling skips in io_evitadb_errors_total.
  • export configurable query labels as Prometheus dimensions

    Query label() values can now be opted in as Prometheus dimensions on query metrics via a new exportedQueryLabels observability option; with nothing configured (the default) no dimension is added, so existing metric cardinality is unchanged.
  • Traffic recorder: attribute post-discard trailing records/close to the discard reason, not SAMPLING (#1314)

    Fixes traffic-recorder telemetry so activity that arrives after a session was discarded for genuine resource pressure (MEMORY_SHORTAGE / SERIALIZATION_ERROR) is attributed to that reason instead of being folded into the benign SAMPLING counter, giving operators an accurate signal for capacity-related discards.
  • Introduce grouped configuration sub-records for EvitaClientConfiguration (#1094)

    Groups EvitaClientConfiguration's connection, TLS, and timeout settings into dedicated ClientConnectionOptions, ClientTlsOptions, and ClientTimeoutOptions sub-records with their own builders. The previous flat TLS and timeout accessors/setters are deprecated for removal in 2026.3, while host(), port(), systemApiPort(), and clientId() remain available at the top level.
  • Replace release-drafter with Claude-generated enriched release notes (#1131)
  • add a debug mode that denies the optional prefetch

🐛 Bug Fixes

  • Release pipeline: transient Claude CLI install failure aborts release and skips Docker publish (#1291)
  • gRPC MakeCatalogAlive / MakeCatalogAliveWithProgress fail with UNAUTHENTICATED — missing from session interceptor whitelist (#1283)
  • filterGroupBy ignored by reference histogramStatistics path (wrong group returned) (#1246)
  • Range-typed bucketed reference histogram rendered with point semantics (inflated overallCount, range not spanning buckets) (#1245)
  • BigDecimalNumberRange value not normalized to schema indexedDecimalPlaces on index write (attributeBetween/histogram returns zero matches) (#1238)
  • indexedDecimalPlaces annotation silently dropped for BigDecimalNumberRange attributes in ClassSchemaAnalyzer (#1236)
  • MoreThanSingleResultException in ReevaluateExpressionExecutor when filter has multiple GroupHaving siblings (#1233)
  • Null-coalesce (??) precedence trap + unhelpful error in FilterBy @Expression (#1232)
  • Memory leak: old Catalog snapshots retained (124 instances / ~6.6 GB) — #557 regression + CDC/static anchors (#1220)
  • Scheduler: multiple bugs in thread/queue handling (purge sizing, swallowed exceptions, type/counter inconsistencies) (#1206)
  • Request request pool rejects under load: ForkJoinPool parallelism clamped to CPU count, maxThreadCount ignored (#1204)
  • WAL-rotation purge reads an already-deleted .catalog file → FileNotFoundException under heavy compaction (#1203)
  • CDC ring-buffer cleanup throws NoSuchElementException on empty subscriber map (#1201)
  • Long-running tests: OffsetIndex torn-read race returns spurious null + TransactionalReference test seeding bug (#1189)
  • OffsetIndex.count(historicalVersion) undercounts when the queried version was never recorded as a PastMemory (#1162)
  • Some REST examples stopped working due to ReferenceSummary changes (#1156)
  • Incorrect behavior of the query with NOT container (#1025)
  • Issues applying partial rollback in atomic entity mutation (#569)
  • address PR #1290 review - Markdown JavaDoc and cache placeholder for absent index
  • address PR review — lazy span names, tail-slot guard, cast removal
  • attribute post-discard traffic to the real discard reason
  • break the JFR registration deadlock between event class init and the metadata lock
  • B+ tree dirty-scope validation registers probe keys, not node objects
  • bump logback 1.5.32 -> 1.5.34
  • bump netty-codec-* to 4.2.16.Final
  • cannot make catalog alive using specific gRPC service call without session
  • carve out granular conflict items from the coarse entity conflict scope
  • correct B+ tree internal-node block-size confusion across all transactional trees
  • correct Deprecated since= values to reflect actual deprecation release
  • de-flake gRPC traffic-export test and harden recorder activation
  • detect conflict-resolution changes in schema differsFrom comparison
  • enforce the documented keep-alive ping/idle configuration contract
  • exclude evita_long_running_tests from PGP/duplicate-class CI checks
  • exempt session-less gRPC endpoints via service wildcard
  • expose conflict-resolution schema mutations in GraphQL/REST mutation unions
  • expose GROUP-typed constraints in REST/GraphQL reference filter schema
  • guarantee stage-order listener firing in CommitProgressRecord
  • guard gRPC SET_FROM_NOW re-arm against a disabled request timeout
  • harden configurable query-label export per review
  • harden the gRPC session cancellation cascade and CDC ordering
  • harden traffic ring-buffer drain, span-lock fairness, and export bounds
  • honor InputStream skip contract and pin UTF-8 for traffic export metadata
  • isolate traffic-metrics JFR capture by unique catalog name
  • keep the two index views in step and stop orphaning facet layers
  • maintain reflected references correctly across LIVE/ARCHIVED scopes
  • make a reduced price index prove it holds nothing live before it is discarded
  • make reused-catalog query benchmarks actually run and report
  • make RingBufferInputStream mark/reset explicitly unsupported
  • make the AI PR review actually produce a review
  • name TransactionalStateProducer in assertion messages that check it
  • port RoaringBitmap #837 and fix two inherited reverse/clone defects
  • prevent and diagnose overlapping-leaf-page corruption in warm-up paged index flushes
  • prime locale-id sequence in GlobalUniqueIndex shell copy
  • publish the offset index descriptor before expiring the read Kryo pool
  • read the lazily initialized logger through its accessor in EvitaServer
  • reclaim the on-disk footprint of dropped and emptied indexes
  • remove sleep-based race in CheckpointCoordinatorTest
  • repair four defects in the PGP key verification script
  • repair reference removal and duplicate bookkeeping in reference builders
  • replace CAS-based completionSequencer with a synchronized append
  • replace dropped NOT branch with EmptyFormula in FormulaOptimizer
  • report zero size for absent directory instead of failing
  • resolve aged-out conflict recompute against the effective catalog schema
  • resolve OPENAI_API_KEY from the environment in translation plugin config
  • restore Lombok processor path and mock index generic arity
  • restrict session concurrency guard to read-write sessions
  • serialize JShell source parsing with evaluation in documentation tests
  • skip vendored RoaringBitmap suite in doc CI workflow
  • soft-fail the release-notes path so a transient blip can't skip release assets
  • treat flushFrequencyInMillis as milliseconds in trunk incorporation
  • wait for catalog init before parallel backup/restore load test

⛓ Dependencies upgrades

  • armeria ... 1.36.0 → 1.40.0
  • bouncyCastle ... 1.83 → 1.85
  • grpc ... 1.78.0 → 1.83.0
  • jackson ... 2.21.1 → 2.22.1
  • jackson.annotations ... 2.21 → 2.22
  • junit.jupiter ... 6.0.3 → 6.1.2
  • logback ... 1.5.32 → 1.6.0
  • lombok ... 1.18.42 → 1.18.46
  • maven.toolchains ... 3.2.0 → 3.3.0
  • micrometer ... 1.16.3 → 1.17.0
  • mockito.junit ... 5.22.0 → 5.23.0
  • okhttp ... 5.3.2 → 5.4.0
  • opentelemetry ... 1.59.0 → 1.64.0
  • opentelemetry.semconv ... 1.40.0 → 1.43.0
  • prometheus ... 1.5.0 → 1.8.0
  • roaringbitmap ... 1.6.12 → 1.6.18
  • slf4j ... 2.0.17 → 2.0.18
  • swagger ... 2.2.43 → 2.2.52

Full Changelog: v2026.1.20...v2026.2.0