-
Notifications
You must be signed in to change notification settings - Fork 99
Dynamic Indexing #693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic Indexing #693
Conversation
Implements Phase 1 of the Dynamic Indexing Feature Design, enabling Spring Expression Language
(SpEL) support in @IndexingOptions for runtime-evaluated index names and key prefixes.
Key features:
- Support for SpEL expressions in indexName and keyPrefix attributes
- Template expression syntax with #{...} markers
- Access to environment properties, beans, and system properties
- Automatic fallback to default naming when SpEL evaluation fails
- Full backward compatibility maintained
Use cases enabled:
- Multi-tenant indexing with tenant-specific names and prefixes
- Version-based index naming for blue-green deployments
- Environment-aware index configuration
- Dynamic index naming based on runtime context
Breaking changes: None - existing code continues to work unchanged
Testing: Comprehensive test suite with 100% coverage including:
- Environment property resolution
- Bean reference resolution
- Method invocations in SpEL
- Fallback behavior on evaluation failure
- Multi-tenant scenarios
- System properties access
- Add RedisIndexContext for thread-local tenant and environment context - Add IndexResolver interface for custom index name/prefix resolution strategies - Add DefaultIndexResolver with full SpEL evaluation support for context variables - Extend RediSearchIndexer with context-aware index operations - Support dynamic index naming and key prefixes based on runtime context - Enable multi-tenant Redis deployments with isolated indexes per tenant
…ime configuration - Add SpEL expression support for dynamic index naming and key prefixes - Implement RedisIndexContext for thread-local multi-tenant isolation - Create IndexResolver interface for customizable index resolution strategies - Add IndexMigrationService supporting Blue-Green, Dual-Write, and In-Place migration strategies - Implement ConfigurableIndexDefinitionProvider for runtime index configuration - Support context-aware index creation with tenant-specific indices - Add comprehensive validation, export/import, and statistics functionality - Maintain 100% backward compatibility with existing applications Components added: - RedisIndexContext: ThreadLocal context storage for tenant/environment data - DefaultIndexResolver: SpEL-aware resolver with application context integration - IndexMigrationService: Production-ready index migration with versioning - ConfigurableIndexDefinitionProvider: Runtime index management and Spring Data Redis bridge - Supporting classes: MigrationResult, ReindexResult, MigrationStrategy, ValidationResult Test coverage: 50+ tests including comprehensive integration tests demonstrating real Redis functionality with multi-tenant data isolation and dynamic configuration.
- Enhance README with dynamic indexing and multi-tenant support highlights - Add extensive dynamic indexing section to index-creation.adoc covering: - SpEL expressions for dynamic index naming - Environment-based and bean reference configurations - Multi-tenant index context and custom resolvers - Error handling, migration services, and best practices - Create dedicated multi-tenant-support.adoc page with: - RedisIndexContext and thread-local isolation - Custom index resolvers and tenant management service - Request-scoped tenant context and data access patterns - Monitoring, observability, and troubleshooting guides - Update navigation to include multi-tenant support documentation This documentation covers all aspects of the new dynamic indexing features including SpEL evaluation, multi-tenant isolation, index migration, and enterprise-ready patterns for production deployments.
…gement - Add real Redis alias operations to RediSearchIndexer (createAlias, removeAlias, updateAlias) - Integrate with existing SearchOperations interface methods - Support FT.ALIASADD, FT.ALIASUPDATE, FT.ALIASDEL Redis commands - Update IndexMigrationService to use real Redis aliasing for blue-green deployments - switchAlias() now creates actual Redis aliases instead of stub implementation - Enable zero-downtime index migrations with atomic alias switching - Add EphemeralIndexService for temporary indexes with TTL support - Automatic deletion after specified time-to-live expires - Support for extending TTL of existing ephemeral indexes - Proper cleanup on service shutdown via DisposableBean - Useful for batch processing and temporary data analysis - Add comprehensive integration tests using TestContainers - IndexMigrationServiceIntegrationTest: Validates blue-green migration with real aliasing - EphemeralIndexServiceIntegrationTest: Tests TTL expiration and extension - CustomIndexResolverIntegrationTest: Validates custom index resolver functionality All tests passing (1611 tests, 100% success rate)
Add missing Javadoc comments to fix build warnings in the indexing
module. This includes documentation for constructors, builder classes,
and all public methods in ConfigurableIndexDefinitionProvider,
EphemeralIndexService, IndexMigrationService, MigrationResult,
ReindexResult, and RediSearchIndexer.
Also wrap SpEL expressions in {@code} blocks in RediSearchIndexer
to prevent them from being parsed as Javadoc tags.
Add roms-multitenant demo showcasing dynamic index naming with SpEL
expressions for multi-tenant scenarios. The demo includes:
- Product and Order entities with tenant-aware index names
- TenantService for thread-local tenant context management
- REST controllers for tenant switching and product management
- Admin endpoints for index creation and verification
- Interactive HTML UI for demonstrating tenant isolation
- Integration tests verifying dynamic index creation
The demo demonstrates how to use @IndexingOptions with SpEL
expressions like "products_#{@tenantService.getCurrentTenant()}_idx"
to create tenant-specific search indexes at runtime.
Add new documentation pages for dynamic indexing features: - ephemeral-indexes.adoc: Covers EphemeralIndexService for creating temporary indexes with TTL, including use cases for testing, analytics, and temporary data processing - index-migration.adoc: Covers IndexMigrationService with Blue-Green, Dual-Write, and In-Place migration strategies for zero-downtime index updates Also update multi-tenant-support.adoc to clarify that keyPrefix in @IndexingOptions affects only index configuration, not actual key storage by Spring Data Redis. Add navigation entries and update outline.md.
Add new test entity fixtures: - ComplexSpelEntity: Entity with complex SpEL expressions for testing - SystemPropertyEntity: Entity using system property SpEL expressions Add BulkIndexOperationsIntegrationTest for testing batch index operations and update DynamicIndexingSpelTest and MultiTenantIndexIsolationIntegrationTest with improved test cases for dynamic index resolution.
… isolation The keyPrefix attribute in @IndexingOptions now controls both the index configuration AND the actual key storage location for documents. This provides complete multi-tenant data isolation where each tenant's data is stored with different key prefixes. Changes: - Add resolveDynamicKeyspace() to RedisJSONKeyValueAdapter for @document entities - Add resolveDynamicKeyspace() to RedisEnhancedKeyValueAdapter for @RedisHash entities - Update put(), get(), delete() methods to use dynamic keyspace resolution - Update Product entity to use dynamic keyPrefix with SpEL expressions - Add comprehensive testTenantSearchIsolation() test for end-to-end verification - Update multi-tenant documentation to reflect complete isolation support Example usage: @IndexingOptions( indexName = "products_#{@tenantService.getCurrentTenant()}_idx", keyPrefix = "#{@tenantService.getCurrentTenant()}:products:" ) For tenant "acme": - Index: products_acme_idx - Keys stored as: acme:products:<id>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR introduces a comprehensive Dynamic Indexing feature for Redis OM Spring, enabling runtime index configuration through SpEL expressions, multi-tenant support, ephemeral indexes, and index migration strategies. The implementation spans across:
- SpEL-Based Dynamic Index Names: Support for Spring Expression Language in
@IndexingOptionsannotation for runtime evaluation - Multi-Tenant Index Support:
RedisIndexContextfor thread-local tenant context management with customIndexResolverinterface - Ephemeral Indexes:
EphemeralIndexServicefor creating temporary indexes with automatic TTL-based cleanup - Index Migration:
IndexMigrationServicesupporting Blue-Green, Dual-Write, and In-Place migration strategies - Configurable Index Definitions:
ConfigurableIndexDefinitionProviderfor runtime index configuration management
Reviewed changes
Copilot reviewed 65 out of 65 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| redis-om-spring/src/main/java/com/redis/om/spring/indexing/RediSearchIndexer.java | Adds SpEL expression evaluation for dynamic index names and key prefixes, context-aware indexing methods, and bulk operations |
| redis-om-spring/src/main/java/com/redis/om/spring/indexing/RedisIndexContext.java | Thread-local context for tenant/environment information with builder pattern and execution utilities |
| redis-om-spring/src/main/java/com/redis/om/spring/indexing/IndexResolver.java | Strategy interface for custom index name/prefix resolution |
| redis-om-spring/src/main/java/com/redis/om/spring/indexing/DefaultIndexResolver.java | Default implementation supporting SpEL and context-based resolution |
| redis-om-spring/src/main/java/com/redis/om/spring/indexing/IndexMigrationService.java | Service for zero-downtime index migrations with multiple strategies |
| redis-om-spring/src/main/java/com/redis/om/spring/indexing/EphemeralIndexService.java | Service for TTL-based temporary indexes with automatic cleanup |
| redis-om-spring/src/main/java/com/redis/om/spring/indexing/ConfigurableIndexDefinitionProvider.java | Runtime index configuration management with validation and export/import |
| redis-om-spring/src/main/java/com/redis/om/spring/annotations/IndexingOptions.java | Enhanced annotation with keyPrefix and comprehensive SpEL documentation |
| redis-om-spring/src/main/java/com/redis/om/spring/RedisJSONKeyValueAdapter.java | Dynamic keyspace resolution integration |
| redis-om-spring/src/main/java/com/redis/om/spring/RedisEnhancedKeyValueAdapter.java | Dynamic keyspace resolution integration |
| tests/src/test/java/com/redis/om/spring/indexing/* | Comprehensive test suite covering all dynamic indexing features |
| tests/src/test/java/com/redis/om/spring/fixtures/document/model/* | Test entities demonstrating SpEL usage patterns |
| docs/content/modules/ROOT/pages/index-migration.adoc | Complete documentation for index migration strategies |
| demos/roms-multitenant/* | Demo application showcasing multi-tenant support |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
redis-om-spring/src/main/java/com/redis/om/spring/indexing/IndexMigrationService.java
Outdated
Show resolved
Hide resolved
| * @return the next version string | ||
| */ | ||
| public String getNextVersion(String incrementType) { | ||
| int major = Integer.parseInt(getMajorVersion()); |
Copilot
AI
Nov 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential uncaught 'java.lang.NumberFormatException'.
tests/src/test/java/com/redis/om/spring/services/VersionService.java
Outdated
Show resolved
Hide resolved
tests/src/test/java/com/redis/om/spring/services/VersionService.java
Outdated
Show resolved
Hide resolved
Add try-catch blocks to handle potential NumberFormatException when parsing version numbers from index names and version strings. - IndexMigrationService.getCurrentIndexVersion(): wrap Integer.parseInt with try-catch and log warning on failure, returning 0 as default - VersionService.getNextVersion(): wrap all three Integer.parseInt calls with try-catch blocks, using sensible defaults (1.0.0)
Summary
This PR introduces a comprehensive Dynamic Indexing feature for Redis OM Spring, enabling runtime index configuration through SpEL expressions, multi-tenant support, ephemeral indexes, and index
migration strategies. This provides flexibility for applications requiring dynamic index management based on runtime context.
Key Features
@IndexingOptionsannotationindexName = "products_#{@tenantService.getCurrentTenant()}_idx"RedisIndexContextfor thread-local tenant context managementTenantServicepattern for managing current tenant stateIndexResolverinterface for advanced resolution logicEphemeralIndexService)IndexMigrationService)ConfigurableIndexDefinitionProvider)New Components
@IndexingOptionsRedisIndexContextIndexResolverDefaultIndexResolverEphemeralIndexServiceIndexMigrationServiceConfigurableIndexDefinitionProviderMigrationStrategyDemo Application
New roms-multitenant demo showcasing:
Documentation
Important Notes
Note on keyPrefix: The keyPrefix attribute in @IndexingOptions affects the index configuration (what key prefix the index searches), not the actual key storage by Spring Data Redis. Documents are
stored using Spring Data Redis's static keyspace. For true data isolation, implement a custom KeyspaceResolver or tenant-aware ID strategy.