Skip to content

Commit abec0f1

Browse files
committed
chore: more throtteling tests
1 parent c638f1d commit abec0f1

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
@@ -8,7 +8,16 @@ type ThrottleType = 'auto' | string
88

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

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

1423
if (PERCENTAGE_REGEX.test(type)) {
@@ -47,14 +56,15 @@ export default (axiosInstance: AxiosInstance, type: ThrottleType | number = 'aut
4756

4857
const responseInterceptorId = axiosInstance.interceptors.response.use(
4958
(response) => {
59+
// If we haven't yet calculated the limit based on the headers, do so now
5060
if (
5161
!isCalculated &&
5262
isString(type) &&
5363
(type === 'auto' || PERCENTAGE_REGEX.test(type)) &&
5464
response.headers &&
55-
response.headers['x-contentful-ratelimit-second-limit']
65+
response.headers[HEADERS.RATE_LIMIT]
5666
) {
57-
const rawLimit = parseInt(response.headers['x-contentful-ratelimit-second-limit'])
67+
const rawLimit = parseInt(response.headers[HEADERS.RATE_LIMIT])
5868
const nextLimit = calculateLimit(type, rawLimit)
5969

6070
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 = vi.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)