Skip to content

Commit

Permalink
Merge #1554
Browse files Browse the repository at this point in the history
1554: Add request timeout r=bidoubiwa a=amit-ksh

# Pull Request

## Related issue
Fixes #716 

## What does this PR do?
- Added the timeout property to the config.
- Added a test to search.test.ts which cancels the timeout after 1 millisecond.

## PR checklist
Please check if your PR fulfills the following requirements:
- [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
- [x] Have you read the contributing guidelines?
- [x] Have you made sure that the title is accurate and descriptive of the changes?

Thank you so much for contributing to Meilisearch!


Co-authored-by: amit-ksh <ksamit1110@gmail.com>
Co-authored-by: Amit Kumar Sharma <ksamit1110@gmail.com>
  • Loading branch information
meili-bors[bot] and amit-ksh authored Sep 27, 2023
2 parents 646d728 + 8a4995f commit 4af90a9
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 8 deletions.
54 changes: 46 additions & 8 deletions src/http-requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,13 @@ class HttpRequests {
url: URL
requestConfig?: Config['requestConfig']
httpClient?: Required<Config>['httpClient']
requestTimeout?: number

constructor(config: Config) {
this.headers = createHeaders(config)
this.requestConfig = config.requestConfig
this.httpClient = config.httpClient
this.requestTimeout = config.timeout

try {
const host = constructHostURL(config.host)
Expand Down Expand Up @@ -140,14 +142,17 @@ class HttpRequests {
const headers = { ...this.headers, ...config.headers }

try {
const fetchFn = this.httpClient ? this.httpClient : fetch
const result = fetchFn(constructURL.toString(), {
...config,
...this.requestConfig,
method,
body,
headers,
})
const result = this.fetchWithTimeout(
constructURL.toString(),
{
...config,
...this.requestConfig,
method,
body,
headers,
},
this.requestTimeout
)

// When using a custom HTTP client, the response is returned to allow the user to parse/handle it as they see fit
if (this.httpClient) {
Expand All @@ -166,6 +171,39 @@ class HttpRequests {
}
}

async fetchWithTimeout(
url: string,
options: Record<string, any> | RequestInit | undefined,
timeout: HttpRequests['requestTimeout']
): Promise<Response> {
return new Promise((resolve, reject) => {
const fetchFn = this.httpClient ? this.httpClient : fetch

const fetchPromise = fetchFn(url, options)

const promises: Array<Promise<any>> = [fetchPromise]

// TimeoutPromise will not run if undefined or zero
let timeoutId: ReturnType<typeof setTimeout>
if (timeout) {
const timeoutPromise = new Promise((_, reject) => {
timeoutId = setTimeout(() => {
reject(new Error('Error: Request Timed Out'))
}, timeout)
})

promises.push(timeoutPromise)
}

Promise.race(promises)
.then(resolve)
.catch(reject)
.finally(() => {
clearTimeout(timeoutId)
})
})
}

async get(
url: string,
params?: { [key: string]: any },
Expand Down
1 change: 1 addition & 0 deletions src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type Config = {
clientAgents?: string[]
requestConfig?: Partial<Omit<RequestInit, 'body' | 'method'>>
httpClient?: (input: string, init?: RequestInit) => Promise<any>
timeout?: number
}

///
Expand Down
15 changes: 15 additions & 0 deletions tests/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,21 @@ describe.each([
expect(error).toHaveProperty('message', 'The user aborted a request.')
})
})

test(`${permission} key: search should be aborted when reaching timeout`, async () => {
const key = await getKey(permission)
const client = new MeiliSearch({
...config,
apiKey: key,
timeout: 1,
})
try {
await client.health()
} catch (e: any) {
expect(e.message).toEqual('Error: Request Timed Out')
expect(e.name).toEqual('MeiliSearchCommunicationError')
}
})
})

describe.each([
Expand Down

0 comments on commit 4af90a9

Please sign in to comment.