Skip to content

Commit af4b23e

Browse files
committed
chore: more throtteling tests
1 parent b014b84 commit af4b23e

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

src/rate-limit-throttle.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,16 @@ type ThrottleType = 'auto' | string
77

88
const PERCENTAGE_REGEX = /(?<value>\d+)(%)/
99

10-
function calculateLimit(type: ThrottleType, max = 7) {
10+
const HEADERS = {
11+
// @desc The maximum amount of requests which can be made in a second.
12+
RATE_LIMIT: 'x-contentful-ratelimit-second-limit',
13+
// @desc The number of seconds until the next request can be made.
14+
RATE_LIMIT_RESET: 'x-contentful-ratelimit-second-reset',
15+
// @desc The remaining amount of requests which can be made until the next secondly reset.
16+
RATE_LIMIT_REMAINING: 'x-contentful-ratelimit-second-remaining',
17+
} as const
18+
19+
export function calculateLimit(type: ThrottleType, max = 7) {
1120
let limit = max
1221

1322
if (PERCENTAGE_REGEX.test(type)) {
@@ -46,14 +55,15 @@ export default (axiosInstance: AxiosInstance, type: ThrottleType | number = 'aut
4655

4756
const responseInterceptorId = axiosInstance.interceptors.response.use(
4857
(response) => {
58+
// If we haven't yet calculated the limit based on the headers, do so now
4959
if (
5060
!isCalculated &&
5161
isString(type) &&
5262
(type === 'auto' || PERCENTAGE_REGEX.test(type)) &&
5363
response.headers &&
54-
response.headers['x-contentful-ratelimit-second-limit']
64+
response.headers[HEADERS.RATE_LIMIT]
5565
) {
56-
const rawLimit = parseInt(response.headers['x-contentful-ratelimit-second-limit'])
66+
const rawLimit = parseInt(response.headers[HEADERS.RATE_LIMIT])
5767
const nextLimit = calculateLimit(type, rawLimit)
5868

5969
if (nextLimit !== limit) {

src/rate-limit.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export default function rateLimit(instance: AxiosInstance, maxRetry = 5): void {
5858
} else if (response.status === 429) {
5959
// 429 errors are exceeded rate limit exceptions
6060
retryErrorType = 'Rate limit'
61-
// all headers are lowercased by axios https://github.com/mzabriskie/axios/issues/413
61+
// all headers are lower-cased by axios https://github.com/mzabriskie/axios/issues/413
6262
if (response.headers && error.response.headers['x-contentful-ratelimit-reset']) {
6363
wait = response.headers['x-contentful-ratelimit-reset']
6464
}

test/unit/rate-limit-throttle.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import axios from 'axios'
44
import MockAdapter from 'axios-mock-adapter'
55
import { AxiosInstance } from '../../src'
66
import createHttpClient from '../../src/create-http-client'
7+
import { calculateLimit } from '../../src/rate-limit-throttle'
78

89
const logHandlerStub = jest.fn()
910

@@ -141,3 +142,19 @@ describe('throttle to rate limit axios interceptor', () => {
141142
}
142143
)
143144
})
145+
146+
describe('a calculate limit function', () => {
147+
describe('with type "auto"', () => {
148+
it('always returns the given max limit', () => {
149+
expect(calculateLimit('auto', 10)).toEqual(10)
150+
expect(calculateLimit('auto', 1)).toEqual(1)
151+
})
152+
})
153+
describe('with %', () => {
154+
it('always returns % of max limit', () => {
155+
expect(calculateLimit('0%', 10)).toEqual(1)
156+
expect(calculateLimit('50%', 10)).toEqual(5)
157+
expect(calculateLimit('100%', 10)).toEqual(10)
158+
})
159+
})
160+
})

0 commit comments

Comments
 (0)