Add ES DSL schema_versions implementation
What does this MR do and why?
Introduces Search::Elastic::Dsl::SchemaVersions
, a new DSL module for declaring and resolving Elasticsearch schema versions inside DSL-based models.
This provides a declarative API to define version history directly within model definitions, replacing hard-coded constants or manual version checks.
It supports:
- Static schema versions
- Conditional versions (gated by feature flags or migration state)
- Automatic resolution of the active version at runtime
Part of the Elasticsearch DSL powering Search::Elastic::Dsl::Models::<Model>
.
Usage example
class Vulnerability
include Search::Elastic::Dsl::SchemaVersions
schema_versions do
# Base version
version 2525
# Conditional version – only active when a migration or FF is ready
version 2526, if: -> { migration_has_finished?(:vulnerability_index_upgrade) }
# Feature-flag controlled version
version 2527, if: -> { Feature.enabled?(:use_vulnerability_dsl_reference) }
end
end
Vulnerability.current_version
# => returns the highest active version (2526 or 2527 if conditions true)
Each version(...)
entry stores a version number and an optional condition proc.
current_version
automatically evaluates which versions are active and returns the latest one.
Implementation details
-
New file:
ee/lib/search/elastic/dsl/schema_versions.rb
- Adds the
schema_versions
andversion
DSL methods - Evaluates conditional versions dynamically at runtime
- Tracks errors via
Gitlab::ErrorTracking
- Provides convenience alias
schema_version
→current_version
- Adds the
-
Specs:
ee/spec/lib/search/elastic/dsl/schema_versions_spec.rb
- Covers unconditional and conditional version declarations
- Tests fallback logic when no version is active
- Verifies exception handling and error reporting
Architectural context
flowchart TD
%% === BUILDERS LAYER ===
subgraph BUILDERS["Search::Elastic::Dsl::Builders::*"]
JB["JsonBuilder<br/>–––––––––––––––––––––––––––––––<br/>Builds Elasticsearch JSON documents for indexing.<br/>Applies field definitions, compute rules, and version filters."]
MB["MappingBuilder<br/>–––––––––––––––––––––––––––––––<br/>Generates Elasticsearch mappings.<br/>Includes only fields active for the current schema version."]
PB["ProxyBuilder<br/>–––––––––––––––––––––––––––––––<br/>Creates enriched runtime proxies combining raw records<br/>and preloaded enrichment data for indexing."]
SB["SettingsBuilder<br/>–––––––––––––––––––––––––––––––<br/>Builds index settings including analyzers,<br/>tokenizers, and normalization filters."]
end
%% === CORE DSL LAYER ===
subgraph CORE["Search::Elastic::Dsl::* (Core Modules)"]
F["Field DSL<br/>–––––––––––––––––––––––––––––––<br/>Central definition of all fields:<br/>type, compute, preload, default, and conditions."]
SV["SchemaVersions<br/>–––––––––––––––––––––––––––––––<br/>Defines available schema versions and<br/>resolves which one is currently active."]
ST["Settings<br/>–––––––––––––––––––––––––––––––<br/>Defines reusable analyzer, filter,<br/>and tokenizer configuration for indices."]
end
%% === RELATIONSHIPS ===
JB --> F
JB --> SV
MB --> F
MB --> SV
PB --> F
SB --> ST
%% === STYLING ===
classDef builder fill:#e8f1ff,stroke:#3366cc,stroke-width:1px,color:#000;
classDef core fill:#f2faff,stroke:#66b3ff,stroke-width:1px,color:#000;
classDef title fill:none,stroke:none,font-weight:bold;
class BUILDERS,JB,MB,PB,SB builder;
class CORE,F,SV,ST core;
SchemaVersions
integrates with:
-
MappingBuilder
, which uses it to resolve the correct schema version for mapping definitions. - Other DSL modules (
Field
,Settings
) that build version-aware index definitions.
References
- Issue: #577399
- Design: ES DSL Design (#577962)
-
Search::Elastic::Dsl::Field
MR: Add ES DSL field implementation (!209522)
Screenshots or screen recordings
Before | After |
---|---|
How to set up and validate locally
-
Include the DSL module in a temporary class:
class TestModel include Search::Elastic::Dsl::SchemaVersions schema_versions do version 1 version 2, if: -> { Feature.enabled?(:test_feature) } end end
-
In Rails console, toggle the feature flag and check:
TestModel.current_version # => 1 or 2 depending on the FF state
-
Verify expected version resolution in
MappingBuilder
output.