Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

rateLimit.test.ts 3.7 KB

You have to be logged in to leave a comment. Sign In
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  1. import { fetchWithRetries } from '../src/fetch';
  2. const mockedFetch = jest.spyOn(global, 'fetch');
  3. const mockedFetchResponse = (ok: boolean, response: object, headers: object = {}) => {
  4. const responseText = JSON.stringify(response);
  5. return {
  6. ok,
  7. status: ok ? 200 : 429,
  8. statusText: ok ? 'OK' : 'Too Many Requests',
  9. text: () => Promise.resolve(responseText),
  10. json: () => Promise.resolve(response),
  11. headers: new Headers({
  12. 'content-type': 'application/json',
  13. ...headers,
  14. }),
  15. } as Response;
  16. };
  17. const mockedSetTimeout = (reqTimeout: number) =>
  18. jest.spyOn(global, 'setTimeout').mockImplementation((cb: () => void, ms?: number) => {
  19. if (ms !== reqTimeout) {
  20. cb();
  21. }
  22. return 0 as any;
  23. });
  24. describe('fetchWithRetries', () => {
  25. beforeEach(() => {
  26. jest.useFakeTimers();
  27. });
  28. afterEach(() => {
  29. mockedFetch.mockReset();
  30. jest.useRealTimers();
  31. });
  32. afterAll(() => {
  33. jest.clearAllMocks();
  34. });
  35. it('should fetch data', async () => {
  36. const url = 'https://api.example.com/data';
  37. const response = { data: 'test data' };
  38. mockedFetch.mockResolvedValueOnce(mockedFetchResponse(true, response));
  39. const result = await fetchWithRetries(url, {}, 1000);
  40. expect(mockedFetch).toHaveBeenCalledTimes(1);
  41. await expect(result.json()).resolves.toEqual(response);
  42. });
  43. it('should retry after given time if rate limited, using X-Limit headers', async () => {
  44. const url = 'https://api.example.com/data';
  45. const response = { data: 'test data' };
  46. const rateLimitReset = 47_000;
  47. const timeout = 1234;
  48. const now = Date.now();
  49. const setTimeoutMock = mockedSetTimeout(timeout);
  50. mockedFetch
  51. .mockResolvedValueOnce(
  52. mockedFetchResponse(false, response, {
  53. 'X-RateLimit-Remaining': '0',
  54. 'X-RateLimit-Reset': `${(now + rateLimitReset) / 1000}`,
  55. }),
  56. )
  57. .mockResolvedValueOnce(mockedFetchResponse(true, response));
  58. const result = await fetchWithRetries(url, {}, timeout);
  59. const waitTime = setTimeoutMock.mock.calls[1][1];
  60. expect(mockedFetch).toHaveBeenCalledTimes(2);
  61. expect(waitTime).toBeGreaterThan(rateLimitReset);
  62. expect(waitTime).toBeLessThanOrEqual(rateLimitReset + 1000);
  63. await expect(result.json()).resolves.toEqual(response);
  64. });
  65. it('should retry after given time if rate limited, using status and Retry-After', async () => {
  66. const url = 'https://api.example.com/data';
  67. const response = { data: 'test data' };
  68. const retryAfter = 15;
  69. const timeout = 1234;
  70. const setTimeoutMock = mockedSetTimeout(timeout);
  71. mockedFetch
  72. .mockResolvedValueOnce(
  73. mockedFetchResponse(false, response, { 'Retry-After': String(retryAfter) }),
  74. )
  75. .mockResolvedValueOnce(mockedFetchResponse(true, response));
  76. const result = await fetchWithRetries(url, {}, timeout);
  77. const waitTime = setTimeoutMock.mock.calls[1][1];
  78. expect(mockedFetch).toHaveBeenCalledTimes(2);
  79. expect(waitTime).toBe(retryAfter * 1000);
  80. await expect(result.json()).resolves.toEqual(response);
  81. });
  82. it('should retry after default wait time if rate limited and wait time not found', async () => {
  83. const url = 'https://api.example.com/data';
  84. const response = { data: 'test data' };
  85. const timeout = 1234;
  86. const setTimeoutMock = mockedSetTimeout(timeout);
  87. mockedFetch
  88. .mockResolvedValueOnce(mockedFetchResponse(false, response))
  89. .mockResolvedValueOnce(mockedFetchResponse(true, response));
  90. const result = await fetchWithRetries(url, {}, timeout);
  91. const waitTime = setTimeoutMock.mock.calls[1][1];
  92. expect(mockedFetch).toHaveBeenCalledTimes(2);
  93. expect(waitTime).toBe(60_000);
  94. await expect(result.json()).resolves.toEqual(response);
  95. });
  96. });
Tip!

Press p or to see the previous file or, n or to see the next file

Comments

Loading...