-
Notifications
You must be signed in to change notification settings - Fork 923
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(book/queue): add recent counter questions and solution
- Loading branch information
1 parent
9a88766
commit 77d4596
Showing
4 changed files
with
133 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
const { Queue } = require('../../src/index'); | ||
|
||
// tag::description[] | ||
/** | ||
* Counts the most recent requests within a time window. | ||
* Each request has its timestamp. | ||
* If the time window is 2 seconds, | ||
* any requests that happened more than 2 seconds before the most recent request | ||
* should not count. | ||
* | ||
* @example - The time window is 10 ms. | ||
* const counter = new RecentCounter(10); | ||
* counter.request(1000); // 1 (first request, it counts) | ||
* counter.request(3000); // 1 (last requests was 2000 ms ago, > 10ms, so doesn't count) | ||
* counter.request(3100); // 1 (last requests was 100 ms ago, > 10ms, so doesn't count) | ||
* counter.request(3105); // 2 (last requests was 5 ms ago, <= 10ms, so it counts) | ||
* | ||
* @example - The time window is 3 sec. (3000 ms) | ||
* const counter = new RecentCounter(3000); | ||
* counter.request(100); // 1 | ||
* counter.request(1000); // 2 | ||
* counter.request(3000); // 3 | ||
* counter.request(3100); // 4 | ||
* counter.request(3101); // 4 (request at time 100 is out of the 3000 window). | ||
* | ||
*/ | ||
class RecentCounter { | ||
// end::description[] | ||
// tag::solution[] | ||
queue = new Queue(); | ||
// end::solution[] | ||
// tag::description[] | ||
/** | ||
* @param {number} maxWindow - Max. time window (in ms) for counting requests | ||
* Defaults to 1 second (1000 ms) | ||
*/ | ||
constructor(maxWindow = 1000) { | ||
// end::description[] | ||
// tag::solution[] | ||
this.window = maxWindow; | ||
// end::solution[] | ||
// tag::description[] | ||
} | ||
|
||
/** | ||
* Add new request and calculate the current count within the window. | ||
* @param {number} timestamp - The current timestamp (increasing order) | ||
* @return {number} - The number of requests within the time window. | ||
*/ | ||
request(timestamp) { | ||
// end::description[] | ||
// tag::solution[] | ||
this.queue.enqueue(timestamp); | ||
while (timestamp - this.queue.peek() > this.window) | ||
this.queue.dequeue(); | ||
|
||
return this.queue.size; | ||
// end::solution[] | ||
// tag::description[] | ||
} | ||
} | ||
// end::description[] | ||
|
||
module.exports = { RecentCounter }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
const { RecentCounter } = require('./recent-counter'); | ||
|
||
describe('Queue: Recent Counter', () => { | ||
it('should count requests within the window', () => { | ||
const counter = new RecentCounter(3000); | ||
expect(counter.request(100)).toEqual(1); // 1 | ||
expect(counter.request(1000)).toEqual(2); // 2 | ||
expect(counter.request(3000)).toEqual(3); // 3 | ||
expect(counter.request(3100)).toEqual(4); // 4 | ||
expect(counter.request(3101)).toEqual(4); // 4 (request at time 100 is out of the 3000 window). | ||
}); | ||
|
||
it('should NOT count requests out of the window', () => { | ||
const counter = new RecentCounter(10); | ||
expect(counter.request(100)).toEqual(1); | ||
expect(counter.request(1000)).toEqual(1); | ||
expect(counter.request(3000)).toEqual(1); | ||
expect(counter.request(3100)).toEqual(1); | ||
expect(counter.request(3101)).toEqual(2); | ||
}); | ||
}); |