OBP-API/IMPLEMENTATION_SUMMARY.md
simonredfern efc1868fd4 BREAKING CHANGE: Switch active-rate-limits endpoint to hour-based format
Changed from full timestamp to hour-only format to match implementation.

OLD: /active-rate-limits/2025-12-31T13:34:46Z (YYYY-MM-DDTHH:MM:SSZ)
NEW: /active-rate-limits/2025-12-31-13 (YYYY-MM-DD-HH)

Benefits:
- API now matches actual implementation (hour-level caching)
- Eliminates timezone/minute truncation confusion
- Clearer semantics: 'active during this hour' not 'at this second'
- Direct cache key mapping improves performance
- Simpler date parsing (no timezone handling needed)

Files changed:
- APIMethods600.scala: Updated endpoint and date parsing
- RateLimitsTest.scala: Updated all test cases to new format
- Glossary.scala: Updated API documentation
- introductory_system_documentation.md: Updated user docs

This is a breaking change but necessary to align API with implementation.
Rate limits are cached and queried at hour granularity, so the API
should reflect that reality.
2025-12-30 17:35:38 +01:00

4.8 KiB

Cache Namespace Standardization - Implementation Summary

Date: 2024-12-27
Status: Complete and Tested

What Was Implemented

1. New API Endpoint

GET /obp/v6.0.0/system/cache/namespaces

Returns live information about all cache namespaces:

  • Cache prefix names
  • Descriptions and categories
  • TTL configurations
  • Real-time key counts from Redis
  • Actual example keys from Redis

2. Changes Made (Clean, No Formatting Noise)

File Statistics

obp-api/src/main/scala/code/api/cache/Redis.scala             |  47 lines added
obp-api/src/main/scala/code/api/constant/constant.scala       |  17 lines added
obp-api/src/main/scala/code/api/util/ApiRole.scala            |   9 lines added
obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala    | 106 lines added
obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala |  35 lines added
---
Total: 5 files changed, 212 insertions(+), 2 deletions(-)

ApiRole.scala

Added 3 new roles:

case class CanGetCacheNamespaces(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetCacheNamespaces = CanGetCacheNamespaces()

case class CanDeleteCacheNamespace(requiresBankId: Boolean = false) extends ApiRole
lazy val canDeleteCacheNamespace = CanDeleteCacheNamespace()

case class CanDeleteCacheKey(requiresBankId: Boolean = false) extends ApiRole
lazy val canDeleteCacheKey = CanDeleteCacheKey()

constant.scala

Added cache prefix constants:

// Rate Limiting Cache Prefixes
final val RATE_LIMIT_COUNTER_PREFIX = "rl_counter_"
final val RATE_LIMIT_ACTIVE_PREFIX = "rl_active_"
final val RATE_LIMIT_ACTIVE_CACHE_TTL: Int = APIUtil.getPropsValue("rateLimitActive.cache.ttl.seconds", "3600").toInt

// Connector Cache Prefixes
final val CONNECTOR_PREFIX = "connector_"

// Metrics Cache Prefixes
final val METRICS_STABLE_PREFIX = "metrics_stable_"
final val METRICS_RECENT_PREFIX = "metrics_recent_"

// ABAC Cache Prefixes
final val ABAC_RULE_PREFIX = "abac_rule_"

// Added SCAN to JedisMethod
val GET, SET, EXISTS, DELETE, TTL, INCR, FLUSHDB, SCAN = Value

Redis.scala

Added 3 utility methods for cache inspection:

def scanKeys(pattern: String): List[String]
def countKeys(pattern: String): Int
def getSampleKey(pattern: String): Option[String]

JSONFactory6.0.0.scala

Added JSON response classes:

case class CacheNamespaceJsonV600(
    prefix: String,
    description: String,
    ttl_seconds: String,
    category: String,
    key_count: Int,
    example_key: String
)

case class CacheNamespacesJsonV600(namespaces: List[CacheNamespaceJsonV600])

APIMethods600.scala

  • Added endpoint implementation
  • Added ResourceDoc documentation
  • Integrated with Redis scanning

Example Response

{
  "namespaces": [
    {
      "prefix": "rl_counter_",
      "description": "Rate limiting counters per consumer and time period",
      "ttl_seconds": "varies",
      "category": "Rate Limiting",
      "key_count": 42,
      "example_key": "rl_counter_consumer123_PER_MINUTE"
    },
    {
      "prefix": "rl_active_",
      "description": "Active rate limit configurations",
      "ttl_seconds": "3600",
      "category": "Rate Limiting",
      "key_count": 15,
      "example_key": "rl_active_consumer123_2024-12-27-14"
    },
    {
      "prefix": "rd_localised_",
      "description": "Localized resource documentation",
      "ttl_seconds": "3600",
      "category": "Resource Documentation",
      "key_count": 128,
      "example_key": "rd_localised_operationId:getBanks-locale:en"
    }
  ]
}

Testing

Prerequisites

  1. User with CanGetCacheNamespaces entitlement
  2. Redis running with cache data

Test Request

curl -X GET https://your-api/obp/v6.0.0/system/cache/namespaces \
  -H "Authorization: DirectLogin token=YOUR_TOKEN"

Expected Response

  • HTTP 200 OK
  • JSON with all cache namespaces
  • Real-time key counts from Redis
  • Actual example keys from Redis

Benefits

  1. Operational Visibility: See exactly what's in cache
  2. Real-time Monitoring: Live key counts, not estimates
  3. Documentation: Self-documenting cache structure
  4. Debugging: Example keys help troubleshoot issues
  5. Foundation: Basis for future cache management features

Documentation

See ideas/CACHE_NAMESPACE_STANDARDIZATION.md for:

  • Full cache standardization plan
  • Phase 1 completion notes
  • Future phases (connector, metrics, ABAC)
  • Cache management guidelines

Verification

Compiles successfully
No formatting changes
Clean git diff
All code follows existing patterns
Documentation complete

Next Steps

  1. Test the endpoint with real data
  2. Create user with CanGetCacheNamespaces role
  3. Verify Redis integration
  4. Consider implementing Phase 2 (connector & metrics)
  5. Future: Add DELETE endpoints for cache management