Commit a33e1d0
fix: Resilient Redis cache reads for rate limiting (#3455)
## Summary
- **Exclude actuator endpoints from rate limit filters** — health probes
(`/actuator/health`) no longer go through
`GlobalIpRateLimitFilter`/`GlobalUserRateLimitFilter`, preventing crash
loops when Redis cache entries are corrupted
- **Add `ResilientCacheAccessor` component** — catches `RedisException`
on direct `cache.get()` calls (not covered by `TolgeeCacheErrorHandler`
which only handles `@Cacheable`), evicts bad entries, returns `null`
(cache miss)
- **Integrate into `RateLimitService`** — corrupted Bucket entries are
treated as cache misses instead of 500 errors
### Root cause (v3.154.0 crash loop)
`Bucket` class gained `strikeCount`/`lastStrikeAt` fields → old
Kryo-serialized entries in Redis couldn't deserialize →
`KryoBufferUnderflowException` → health checks hit rate limit filter →
HTTP 500 → K8s restarts pod → crash loop.
### Defense in depth
| Layer | What it does | Protects against |
|-------|-------------|-----------------|
| Actuator bypass | Skips rate limiting for `/actuator/**` | Health
probe failures from any cache issue |
| ResilientCacheAccessor | Catches `RedisException`, evicts, returns
null | 500 errors on API requests from corrupted cache |
## Test plan
- [x] `ResilientCacheAccessorTest` — 5 tests (normal get, null return,
RedisException caught + eviction, non-Redis propagation)
- [x] `RateLimitServiceTest` — 15 tests including new `corrupted cache
entry is treated as cache miss`
- [ ] Full backend test suite (`server-app:runStandardTests`)
- [ ] Manual: start with Redis, corrupt a `rateLimits` entry, verify
graceful handling
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Improved cache resilience: corrupted cache entries are evicted and
treated as misses to prevent runtime errors.
* Rate limiting now skips actuator endpoints so health and metrics
remain accessible (including when an application context path is set).
* **Tests**
* Added tests validating cache resilience, eviction on corruption,
null-handling, and exception propagation.
* Expanded rate limiting tests to verify actuator endpoint exemptions
and context-path handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Gabriel Shanahan <gabe@tolgee.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>1 parent 320d87a commit a33e1d0
17 files changed
Lines changed: 274 additions & 511 deletions
File tree
- backend
- data/src
- main/kotlin/io/tolgee
- component
- cache
- security/ratelimit
- test/kotlin/io/tolgee
- security/ratelimit
- unit
- cache
- security/src
- main/kotlin/io/tolgee/security/ratelimit
- test/kotlin/io/tolgee/security/ratelimit
Lines changed: 0 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
8 | 7 | | |
9 | 8 | | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | 9 | | |
18 | 10 | | |
19 | 11 | | |
20 | 12 | | |
21 | 13 | | |
22 | 14 | | |
23 | 15 | | |
24 | | - | |
25 | 16 | | |
26 | 17 | | |
27 | 18 | | |
| |||
Lines changed: 58 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
Lines changed: 0 additions & 124 deletions
This file was deleted.
Lines changed: 0 additions & 84 deletions
This file was deleted.
Lines changed: 0 additions & 59 deletions
This file was deleted.
0 commit comments