Merged
Conversation
…tency Add Redis 7 (Alpine) as a distributed cache layer across the platform, using Spring Boot auto-configured StringRedisTemplate throughout. Session caching (auth-service): - TokenBlocklistService: Redis-backed token revocation with TTL matching token lifetime, fail-open on Redis unavailability - UserSessionCacheService: cache /auth/me responses (15min TTL), evicted on logout, status change, and profile update via Kafka events - Integrate blocklist check into AuthService.logout() and session caching into AuthController.getCurrentUser() Rate limiting (api-gateway): - RateLimitFilter: Redis-backed sliding-window rate limiter using Lua script (sorted set) for atomic increment + check - Tiered limits: auth (20/min), admin (200/min), default (100/min) - Configurable via RateLimitProperties, fail-open when Redis is down - Client key derived from X-User-Id header or client IP Idempotency deduplication (finpay-outbox-starter): - RedisIdempotentConsumerService: Redis-accelerated duplicate check with automatic DB fallback (sub-ms fast path, DB slow path) - Write-through pattern: DB first (source of truth), then Redis with TTL - Smart backfill: cache-warm Redis on DB hit for future lookups - Auto-configured via @ConditionalOnBean(StringRedisTemplate), falls back to DB-only IdempotentConsumerService without Redis Analytics caching (wallet-service): - WalletCacheService: cache wallet read responses (10s TTL), evicted on every write operation (deposit, withdraw, freeze, etc.) - WalletAnalyticsCacheService: cache admin dashboard metrics (30s TTL), evicted on wallet mutations Infrastructure: - Redis 7 Alpine in docker-compose.yml (maxmemory 256mb, allkeys-lru) - spring-boot-starter-data-redis added to all service POMs - testcontainers-redis (com.redis:testcontainers-redis:2.2.4) for integration tests with @Serviceconnection - Redis testcontainer added to all 5 TestcontainersConfig files - All Redis operations wrapped in try-catch with graceful degradation Tests: - TokenBlocklistServiceTest (6 tests) - UserSessionCacheServiceTest (4 tests) - RateLimitFilterTest (6 tests) - RedisIdempotentConsumerServiceTest (8 tests) - All use @InjectMocks/@SPY (no new keyword anti-pattern) - Fixed existing tests: added missing @mock for new dependencies, cache eviction in @beforeeach for test isolation
- Remove raw token column from RefreshToken entity (security best practice) - Add tokenHash column (64-char SHA-256 hex, unique indexed) - Extract sha256() from entity to TokenHashUtil utility class - Update AuthService and OAuth2SuccessHandler to hash before persisting - Update RefreshTokenRepository to findByTokenHash - Update all tests (unit, integration, repository)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's New
1. Session Caching (auth-service)
/auth/meresponses in Redis for 15 minutes viaUserSessionCacheService2. Token Blocklist (auth-service)
TokenBlocklistServiceblocks revoked access tokens in Redis with TTL matching token remaining lifetimeAuthController.getCurrentUser()before serving/auth/me3. Rate Limiting (api-gateway)
RateLimitFilteruses a Redis Lua script for atomic sliding-window rate limitingRateLimitPropertiesin application.yaml4. Idempotency Deduplication (finpay-outbox-starter)
RedisIdempotentConsumerServiceaccelerates duplicate event detection using Redis before DB lookup@ConditionalOnBean(StringRedisTemplate); falls back to DB-only without Redis5. Wallet & Analytics Caching (wallet-service)
WalletCacheService: caches wallet reads for 10 seconds, evicted on any wallet mutation (deposit, withdraw, transfer, freeze, unfreeze)WalletAnalyticsCacheService: caches admin dashboard metrics for 30 seconds6. Secure Refresh Token Storage (auth-service)
tokencolumn fromrefresh_tokenstabletokenHash, 64-char hex) is persisted - raw token is never storedfindByTokenHash()after hashing the incoming tokensha256()toTokenHashUtilutility class (clean entity, no crypto in JPA model)Resilience
Infrastructure
docker-compose.yml(256MB, allkeys-lru eviction)spring-boot-starter-data-redisadded to parent POMStringRedisTemplateused everywhere (auto-configured by Spring Boot, no customRedisConfig)Testing
redis:7-alpine) added to all 5 service TestcontainersConfig filesTokenBlocklistServiceTest,UserSessionCacheServiceTest,RateLimitFilterTest,RedisIdempotentConsumerServiceTesttokenHashchangesCommits:
704b600feat: add Redis infrastructure for caching, rate limiting, and idempotency84282dfrefactor: store only SHA-256 hash of refresh tokens