-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests(api): dynamically set delay in eventually() assertion helper (#…
…10929) This updates the logic of `eventually()` to start with a very small initial delay of 100ms. On each failure, the delay is increased by 25% (clamped to the remaining time) + 1-10ms of jitter. ### other changes 1. Time spent within the assertion function passed to `eventually()` will now count towards the timeout. It's possible these behavioral changes could break due to assumptions of some callers, but this doesn't seem _too_ likely. 2. There were several functions with their own implementation of this pattern. They've all been refactored to wrap `eventually()` and should reap the same benefits: `retryRequest()`, `waitForCacheInvalidation()`, and `waitForTargetStatus()` ### rationale This _should_ translate to faster test runs. Here are some example timings from the `Execute Gateway API Tests` step in various jobs: * `API Test Packages - ubuntu-24.04 / Package API Tests - using ubuntu-24.04 artifact, hybrid mode` * [this branch](https://github.com/Kong/kong-ee/actions/runs/12168109558/job/33938264421?pr=10929#logs) => 1m43s * [master](https://github.com/Kong/kong-ee/actions/runs/12130570459/job/33821902232#logs) => 5m8s * `API Test Packages - ubuntu-24.04-arm64 / Package API Tests - using ubuntu-24.04-arm64 artifact, classic mode` * [this branch](https://github.com/Kong/kong-ee/actions/runs/12168109558/job/33938263450#logs) => 1m59s * [master](https://github.com/Kong/kong-ee/actions/runs/12130570459/job/33821899862#logs) => 3m58s * `E2E Tests - ubuntu / non-smoke API test - classic mode on ubuntu-latest-kong for kong/kong-gateway-dev:<tag>` * [this branch](https://github.com/Kong/kong-ee/actions/runs/12168109558/job/33938557043?pr=10929#logs) => 15m30s * [master](https://github.com/Kong/kong-ee/actions/runs/12130570459/job/33822233896#logs) => 31m36s + 1m48s in `Retry Failed E2E API Tests` ### links KAG-5953
- Loading branch information
Showing
9 changed files
with
148 additions
and
214 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,28 @@ | ||
import { AxiosResponse } from 'axios'; | ||
import { logResponse } from './logging'; | ||
import { isCI } from '@support'; | ||
import { eventually } from '@support'; | ||
|
||
/** | ||
* Retry the given Axios request to match the status code using a timeout and interval | ||
* @param {Promise<AxiosResponse>} axiosRequest request to perform | ||
* @param {(response: AxiosResponse) => void} assertions assertions to match | ||
* @param {number} timeout timeout of retry loop | ||
* @param {number} interval interval between tries | ||
* @param axiosRequest - request to perform | ||
* @param assertions - assertions to match | ||
* @param timeout - max amount of time before raising an assertion error | ||
* @param delay - initial delay between request retries | ||
* @returns {Promise<AxiosResponse>} axios response object | ||
*/ | ||
export const retryRequest = async ( | ||
axiosRequest: () => Promise<AxiosResponse>, | ||
assertions: (response: AxiosResponse) => void, | ||
timeout = 30000, | ||
interval = 3000, | ||
delay = 100, | ||
verbose = false, | ||
): Promise<AxiosResponse> => { | ||
// enable verbose logs in GH Actions for debugability | ||
verbose = isCI() ? true : verbose | ||
let response: AxiosResponse = {} as any; | ||
let errorMsg = ''; | ||
while (timeout >= 0) { | ||
response = await axiosRequest(); | ||
const wrapper: () => Promise<AxiosResponse> = async () => { | ||
const response = await axiosRequest(); | ||
logResponse(response); | ||
try { | ||
assertions(response); | ||
return response; | ||
} catch (error: any) { | ||
if (verbose) { | ||
errorMsg = error.message; | ||
console.log(errorMsg); | ||
console.log( | ||
`** Assertion(s) Failed -- Retrying in ${interval / 1000} seconds **` | ||
); | ||
} | ||
await new Promise((resolve) => setTimeout(resolve, interval)); | ||
timeout -= interval; | ||
} | ||
} | ||
|
||
/* | ||
* The last try. | ||
* | ||
* If we get here, we've timed out, | ||
* but we might miss a try in some cases, | ||
* For example, if the timeout is 10 seconds, | ||
* and the interval is 3 seconds, | ||
* we'll try 3 times, the last try will be at 9 seconds. | ||
* But the condition might be true at 10 seconds, | ||
* and the timeout not is less than 0, | ||
* so we'll exit the above loop, | ||
* and we'll miss the last try. | ||
*/ | ||
try { | ||
assertions(response); | ||
return response; | ||
} catch (error: any) { | ||
errorMsg = error.message; | ||
console.log(errorMsg); | ||
console.log( | ||
`** Assertion(s) Failed -- Retrying in ${interval / 1000} seconds **` | ||
); | ||
} | ||
}; | ||
|
||
throw new Error(errorMsg); | ||
return await eventually(wrapper, timeout, delay, verbose); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.