Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1026,9 +1026,9 @@ export class OpenAI {
}
}

// If the API asks us to wait a certain amount of time, just do what it
// says, but otherwise calculate a default
if (timeoutMillis === undefined) {
// If the API asks us to wait a certain amount of time (capped at 60 seconds),
// just do what it says, but otherwise calculate a default
if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis <= 60 * 1000)) {
const maxRetries = options.maxRetries ?? this.maxRetries;
timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
}
Expand Down
41 changes: 41 additions & 0 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,47 @@ describe('retries', () => {
expect(count).toEqual(3);
});

test.each([
['Retry-After', '60'],
['Retry-After-Ms', '60000'],
])('retry on 429 honors %s at the 60-second cap', async (headerName, headerValue) => {
jest.useFakeTimers();
try {
let count = 0;
const testFetch = async (
url: string | URL | Request,
{ signal }: RequestInit = {},
): Promise<Response> => {
if (count++ === 0) {
return new Response(undefined, {
status: 429,
headers: {
[headerName]: headerValue,
},
});
}
return new Response(JSON.stringify({ a: 1 }), {
headers: { 'Content-Type': 'application/json' },
});
};

const client = new OpenAI({
apiKey: 'My API Key',
adminAPIKey: 'My Admin API Key',
fetch: testFetch,
});

const request = client.request({ path: '/foo', method: 'get' });
await Promise.resolve();
await jest.advanceTimersByTimeAsync(60 * 1000);

await expect(request).resolves.toEqual({ a: 1 });
expect(count).toEqual(2);
} finally {
jest.useRealTimers();
}
});

describe('auth', () => {
test('apiKey', async () => {
const client = new OpenAI({
Expand Down