Skip to content

Conversation

@alfardil
Copy link
Collaborator

@alfardil alfardil commented Jan 15, 2026

612

Description of changes

  • Created SimpleRedis, SimpleRedisSlot, and SimpleRedisProvider.
  • SimpleRedisSlot is essentially our "enum" for the databases we support for in memory storage.
  • SimpleRedisProvider is our class to handle methods pertaining to CRUD operations on the database and/or specified key value.
  • SimpleRedis is an extension of ConcurrentHashMap that may return a typed value of Clazz instantiated from SimpleRedisSlot.

Checklist before review

  • I have done a thorough self-review of the PR
  • Copilot has reviewed my latest changes, and all comments have been fixed and/or closed.
  • If I have made database changes, I have made sure I followed all the db repo rules listed in the wiki here. (check if no db changes)
  • All tests have passed
  • I have successfully deployed this PR to staging
  • I have done manual QA in both dev (and staging if possible) and attached screenshots below.

Screenshots

Dev

Screenshot 2026-01-15 at 11 29 03 AM

Staging

@github-actions
Copy link
Contributor

Overall Project 75.63% -0.25% 🍏
Files changed 72.3%

File Coverage
SimpleRedis.java 100% 🍏
SimpleRedisSlot.java 100% 🍏
RateLimitingFilter.java 97.46% 🍏
SubmissionController.java 83.23% -2.9%
SimpleRedisProvider.java 59.22% -40.78%
AuthController.java 33% -1.97%

@tahminator
Copy link
Owner

/ai

@tahminator
Copy link
Owner

/review

@tahminator
Copy link
Owner

/describe

@tahminator
Copy link
Owner

/improve

@github-actions
Copy link
Contributor

Title

612: Simple Redis Improvements


PR Type

Enhancement, Tests


Description

  • Introduce typed in-memory Redis provider

  • Replace raw indices with typed slots

  • Update controllers to use provider API

  • Add rate limiter to typed storage


Diagram Walkthrough

flowchart LR
  Slots["SimpleRedisSlot<T> (typed slots)"]
  Redis["SimpleRedis<T> (typed map)"]
  Provider["SimpleRedisProvider (DB registry)"]
  Controllers["Auth/Submission Controllers"]
  Filter["RateLimitingFilter"]
  Tests["SubmissionControllerTest"]

  Slots -- "define indices + types" --> Provider
  Provider -- "register/select" --> Redis
  Controllers -- "use slots (Long)" --> Provider
  Filter -- "use slot (Bucket)" --> Provider
  Tests -- "mock provider + slots" --> Provider
Loading

File Walkthrough

Relevant files
Enhancement
6 files
AuthController.java
Use typed Redis provider and verification slot                     
+8/-6     
SubmissionController.java
Migrate rate limit to typed submission slot                           
+8/-6     
SimpleRedis.java
Simplify to typed map with safe get cast                                 
+7/-57   
SimpleRedisProvider.java
Add typed Redis provider and registry                                       
+89/-0   
SimpleRedisSlot.java
Define typed slots for Redis databases                                     
+16/-0   
RateLimitingFilter.java
Move bucket storage to typed global slot                                 
+8/-6     
Tests
1 files
SubmissionControllerTest.java
Update mocks to SimpleRedisProvider and slot                         
+5/-3     

@github-actions
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Raw Cast

The generic get method casts from Object without type checks; consider leveraging the slot's clazz for safer typing or documenting the unchecked cast and suppressing warnings to avoid confusion.

public class SimpleRedis<T> extends ConcurrentHashMap<String, T> {
    public T get(String key) {
        Object value = super.get(key);

        if (value == null) {
            return null;
        }
        return (T) value;
    }
Slot Registration

Slots are pre-registered in init; ensure future slots are added here or provide a single source of truth to prevent IllegalArgumentException when selecting an unregistered slot.

/** Initialize the Redis store with indices of all the databases we support. */
@PostConstruct
public void init() {
    register(SimpleRedisSlot.GLOBAL_RATE_LIMIT);
    register(SimpleRedisSlot.SUBMISSION_REFRESH);
    register(SimpleRedisSlot.VERIFICATION_EMAIL_SENDING);
}

private <T> void register(final SimpleRedisSlot<T> slot) {
    store.put(slot.getIndex(), new SimpleRedis<T>());
}

/** Selects database slot. Throws exception if slot doesn't exist. */
public <T> SimpleRedis<T> select(final SimpleRedisSlot<T> slot) {
    SimpleRedis<?> redis = store.get(slot.getIndex());
    if (redis == null) {
        throw new IllegalArgumentException("This database is not initialized: " + slot.getIndex());
    }
    return (SimpleRedis<T>) redis;
}
Synchronization Scope

Synchronization on this may bottleneck under load; consider a computeIfAbsent per-key initialization to reduce contention when creating buckets.

Bucket bucket;
var slot = SimpleRedisSlot.GLOBAL_RATE_LIMIT;
synchronized (this) {
    bucket = (Bucket) redis.get(slot, bucketKey);
    if (bucket == null) {
        redis.put(slot, bucketKey, createNewBucket(rateLimitCapacity, refillInterval));
        bucket = (Bucket) redis.get(slot, bucketKey);
    }
}

@codecov
Copy link

codecov bot commented Jan 16, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants