Skip to content

Commit

Permalink
refactor: allow duration to be optional during set method
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Feb 7, 2024
1 parent 8418a83 commit 115ed7b
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 11 deletions.
6 changes: 5 additions & 1 deletion src/limiter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,11 @@ export class Limiter implements LimiterStoreContract {
*
* The duration must be a value in seconds or a string expression.
*/
set(key: string | number, requests: number, duration: string | number): Promise<LimiterResponse> {
set(
key: string | number,
requests: number,
duration?: string | number
): Promise<LimiterResponse> {
return this.#store.set(key, requests, duration)
}

Expand Down
8 changes: 6 additions & 2 deletions src/stores/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,13 @@ export default abstract class RateLimiterBridge implements LimiterStoreContract
async set(
key: string | number,
requests: number,
duration: string | number
duration?: string | number
): Promise<LimiterResponse> {
const response = await this.rateLimiter.set(key, requests, string.seconds.parse(duration))
const response = await this.rateLimiter.set(
key,
requests,
duration ? string.seconds.parse(duration) : this.duration
)
debug('updated key %s with requests: %s, duration: %s', key, requests, duration)

/**
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export interface LimiterStoreContract {
*
* The duration must be a value in seconds or a string expression.
*/
set(key: string | number, requests: number, duration: string | number): Promise<LimiterResponse>
set(key: string | number, requests: number, duration?: string | number): Promise<LimiterResponse>

/**
* Delete a given key
Expand Down
29 changes: 22 additions & 7 deletions tests/limiter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { test } from '@japa/runner'
import { createRedis } from './helpers.js'
import { Limiter } from '../src/limiter.js'
import LimiterRedisStore from '../src/stores/redis.js'
import { ThrottleException } from '../src/errors.js'

test.group('Limiter', () => {
test('proxy store methods', async ({ assert }) => {
Expand Down Expand Up @@ -237,7 +238,6 @@ test.group('Limiter', () => {
throw new Error('Something went wrong')
})
}, 'Something went wrong')

assert.equal(await limiter.remaining('ip_localhost'), 1)

assert.isTrue(
Expand All @@ -249,7 +249,10 @@ test.group('Limiter', () => {
assert.isNull(await limiter.get('ip_localhost'))
})

test('throw error via penalize when all requests has been exhausted', async ({ assert }) => {
test('return error via penalize when all requests has been exhausted', async ({
assert,
expectTypeOf,
}) => {
const redis = createRedis(['rlflx:ip_localhost']).connection()
const store = new LimiterRedisStore(redis, {
duration: '1 minute',
Expand All @@ -263,17 +266,29 @@ test.group('Limiter', () => {
throw new Error('Something went wrong')
})
}, 'Something went wrong')

await assert.rejects(async () => {
await limiter.penalize('ip_localhost', () => {
throw new Error('Something went wrong')
})
}, 'Something went wrong')
await assert.rejects(async () => {
await limiter.penalize('ip_localhost', () => {
throw new Error('Something went wrong')
})
}, 'Too many requests')

const [error, user] = await limiter.penalize('ip_localhost', () => {
return {
id: 1,
}
})

if (error) {
expectTypeOf(error).toEqualTypeOf<ThrottleException>()
expectTypeOf(user).toEqualTypeOf<null>()
} else {
expectTypeOf(user).toEqualTypeOf<{ id: number }>()
expectTypeOf(error).toEqualTypeOf<null>()
}

assert.instanceOf(error, ThrottleException)
assert.equal(error?.response.remaining, 0)
assert.equal(await limiter.remaining('ip_localhost'), 0)
})
})

0 comments on commit 115ed7b

Please sign in to comment.