mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 15:56:57 +00:00
63 lines
2.1 KiB
Markdown
63 lines
2.1 KiB
Markdown
|
|
# Redis Read Access Functions
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Multiple functions in `RateLimitingUtil.scala` read counter data from Redis independently. This creates potential inconsistency and code duplication.
|
||
|
|
|
||
|
|
## Current Functions Reading Redis Counters
|
||
|
|
|
||
|
|
### 1. `underConsumerLimits` (line ~152-159)
|
||
|
|
- **Uses**: `EXISTS` + `GET`
|
||
|
|
- **Returns**: Boolean (are we under limit?)
|
||
|
|
- **Handles missing key**: Returns `true` (under limit)
|
||
|
|
- **Purpose**: Enforcement - check if request should be allowed
|
||
|
|
|
||
|
|
### 2. `incrementConsumerCounters` (line ~185-195)
|
||
|
|
- **Uses**: `TTL` + (`SET` or `INCR`)
|
||
|
|
- **Returns**: (ttl, count) as tuple
|
||
|
|
- **Handles missing key (TTL=-2)**: Creates new key with value 1
|
||
|
|
- **Purpose**: Tracking - increment counter after allowed request
|
||
|
|
|
||
|
|
### 3. `ttl` (line ~208-217)
|
||
|
|
- **Uses**: `TTL` only
|
||
|
|
- **Returns**: Long (normalized TTL)
|
||
|
|
- **Handles missing key (TTL=-2)**: Returns 0
|
||
|
|
- **Purpose**: Helper - get remaining time for a period
|
||
|
|
|
||
|
|
### 4. `getCallCounterForPeriod` (line ~223-250)
|
||
|
|
- **Uses**: `TTL` + `GET`
|
||
|
|
- **Returns**: ((Option[Long], Option[Long]), period)
|
||
|
|
- **Handles missing key (TTL=-2)**: Returns (Some(0), Some(0))
|
||
|
|
- **Purpose**: Reporting - display current usage to API consumers
|
||
|
|
|
||
|
|
## Redis TTL Semantics
|
||
|
|
|
||
|
|
- `-2`: Key does not exist
|
||
|
|
- `-1`: Key exists with no expiry (shouldn't happen in our rate limiting)
|
||
|
|
- `>0`: Seconds until key expires
|
||
|
|
|
||
|
|
## Issues
|
||
|
|
|
||
|
|
1. **Code duplication**: Redis interaction logic repeated across functions
|
||
|
|
2. **Inconsistency risk**: Each function interprets Redis state independently
|
||
|
|
3. **Multiple sources of truth**: No single canonical way to read counter state
|
||
|
|
|
||
|
|
## Recommendation
|
||
|
|
|
||
|
|
Refactor to have ONE canonical function that reads and normalizes counter state from Redis:
|
||
|
|
|
||
|
|
```scala
|
||
|
|
private def getCounterState(consumerKey: String, period: LimitCallPeriod): (Long, Long) = {
|
||
|
|
// Single place to read and normalize Redis counter data
|
||
|
|
// Returns (calls, ttl) with -2 handled as 0
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
All other functions should use this single source of truth.
|
||
|
|
|
||
|
|
## Status
|
||
|
|
|
||
|
|
- Enforcement functions work correctly
|
||
|
|
- Reporting improved (returns 0 instead of None for missing keys)
|
||
|
|
- Refactoring to single read function: **Not yet implemented**
|