Skip to content

Conversation

andreatanky
Copy link
Contributor

@andreatanky andreatanky commented Sep 8, 2025

pull request

Closes #3007

Add Practice Exercise: Rate Limiter

  • Adds a new practice exercise, “rate-limiter”, implementing a deterministic fixed-window rate limiter with an injected monotonic clock
  • To implement a single method (FixedWindowRateLimiter.allow); the API, clock, and constructor are provided
  • Includes tests, reference solution, Gradle config, and brief instructions

Reviewer Resources:

Track Policies

@andreatanky andreatanky marked this pull request as ready for review September 12, 2025 14:39
@andreatanky andreatanky changed the title [Draft] Add rate limiter exercise Add rate limiter exercise Sep 12, 2025
Copy link
Member

@kahgoh kahgoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for contributing this exercise! As a concept for a practice exercise, I think this looks good! Some comments below:

@andreatanky andreatanky requested a review from kahgoh September 14, 2025 14:13
Comment on lines 19 to 21
public void advanceNanos(long nanos) {
this.now = this.now.plusNanos(nanos);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you might have forgotten to update the tests to use the advance(Duration d) method.

@andreatanky andreatanky requested a review from kahgoh September 20, 2025 04:21
Comment on lines 177 to 193
final class ClientId {
final String id;

ClientId(String id) {
this.id = id;
}

@Override
public boolean equals(Object o) {
return (o instanceof ClientId) && ((ClientId) o).id.equals(this.id);
}

@Override
public int hashCode() {
return id.hashCode();
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, I'm not a fan of having to rely on the correct implementation of the equals and hashCode in the test and I think having the UUID, Integer, Long and String variants is more than enough to test the generics side - perhaps we could remove this test case?

Copy link
Contributor Author

@andreatanky andreatanky Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback — could you share a bit more on what feels uncomfortable about the custom‑object test?
Is it that it couples outcomes to equals/hashCode correctness and can cause confusing failures unrelated to the rate‑limiter logic?

I have removed this custom object test case to reduce possible confusion

Copy link
Member

@kahgoh kahgoh Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is that we'd be relying on the equals and hashCode being implemented correctly for this test to work properly. If this had been for an actual project, I'd be wondering if we need tests to prove that they have been implemented correctly and honor the equals and hashCode contract too. I think an alternative would be to use records which would take care of this for you, but I also felt it was already sufficient to use UUID objects.

config.json Outdated
"uuid": "b4b0c60e-4ce1-488e-948f-bcb6821c773c",
"practices": [],
"prerequisites": [],
"difficulty": 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the difficulty, would you say it is similar in difficulty as Luhn? If so, we could say it is a 4 (a 4 is one of the lower medium difficulty, 3 is easy). I think 1 is too low.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think low‑medium (4) is reasonable! it only requires per‑key state and fixed‑window boundary handling with java.time, but avoids concurrency and advanced algorithms like sliding windows or token buckets.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! The exercises are sorted by difficulty and then name though. Could you please move this entry to between proverb and rotational-cipher in the exercises list?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shifted! Thanks!

@andreatanky andreatanky requested a review from kahgoh September 22, 2025 11:41
Copy link
Member

@kahgoh kahgoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its almost there! I have noticed the CI is failing with some errors (see the results at the bottom). I think one of the errors may be because there are some Gradle files missing. To fix this:

  • Have a look at resources/exercise-template.
  • There are some Gradle files and directories that should be copied to your rate-limiter exercise, namely:
    • the gradle directory
    • gradlew
    • gradlew.bat

Comment on lines 11 to 12
@Test
void allowsUpToLimit() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've started putting @DisplayName tags in the tests in the other PRs (example in suggestion). Could you please do the same?

Suggested change
@Test
void allowsUpToLimit() {
@Test
@DisplayName("Allows up to window limit")
void allowsUpToLimit() {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with the tests with @DisplayName

@andreatanky andreatanky requested a review from kahgoh September 23, 2025 01:20
Copy link
Member

@kahgoh kahgoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, there's still a couple of errors from the CI.

Copy link
Member

@kahgoh kahgoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, it is passing the CI now! I noticed some more really minor things while doing a last pass over the changes.

@andreatanky
Copy link
Contributor Author

Appreciate the thorough review!

@andreatanky andreatanky requested a review from kahgoh September 24, 2025 02:36
Co-authored-by: Kah Goh <[email protected]>
@andreatanky andreatanky requested a review from kahgoh September 24, 2025 09:46
@kahgoh
Copy link
Member

kahgoh commented Sep 24, 2025

Thanks for sticking with this one! Looks good now!

@kahgoh kahgoh merged commit 85eaced into exercism:main Sep 24, 2025
6 checks passed
bibekparajuli123 pushed a commit to bibekparajuli123/java that referenced this pull request Oct 4, 2025
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.

Add rate limiter exercise

2 participants