Skip to content

Feat add exp 429 retry - #46

Merged
sonic16x merged 4 commits into
masterfrom
add-exp-429-retry
Aug 14, 2026
Merged

Feat add exp 429 retry#46
sonic16x merged 4 commits into
masterfrom
add-exp-429-retry

Conversation

@sonic16x

@sonic16x sonic16x commented Aug 10, 2026

Copy link
Copy Markdown

When a WebDriver grid responds with 429 (Too Many Requests) during, retries now use exponential backoff instead of hammering the server immediately.

Retry delays follow the formula 5000 × 2^attempt + jitter(0..1000ms), giving approximately 5s → 10s → 20s between attempts.
The number of retries is controlled by the existing connectionRetryCount option.

The backoff applies only to all requests which get 429.

Screenshot 2026-08-12 at 17 24 23

@pkg-pr-new

pkg-pr-new Bot commented Aug 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

@testplane/devtools

npm i https://pkg.pr.new/gemini-testing/webdriverio/@testplane/devtools@46

eslint-plugin-wdio

npm i https://pkg.pr.new/gemini-testing/webdriverio/eslint-plugin-wdio@46

@wdio/allure-reporter

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/allure-reporter@46

@wdio/appium-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/appium-service@46

@wdio/browser-runner

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/browser-runner@46

@wdio/browserstack-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/browserstack-service@46

@wdio/cli

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/cli@46

@wdio/concise-reporter

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/concise-reporter@46

@testplane/wdio-config

npm i https://pkg.pr.new/gemini-testing/webdriverio/@testplane/wdio-config@46

@wdio/cucumber-framework

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/cucumber-framework@46

@wdio/dot-reporter

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/dot-reporter@46

@wdio/firefox-profile-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/firefox-profile-service@46

@wdio/globals

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/globals@46

@wdio/jasmine-framework

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/jasmine-framework@46

@wdio/json-reporter

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/json-reporter@46

@wdio/junit-reporter

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/junit-reporter@46

@wdio/lighthouse-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/lighthouse-service@46

@wdio/local-runner

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/local-runner@46

@testplane/wdio-logger

npm i https://pkg.pr.new/gemini-testing/webdriverio/@testplane/wdio-logger@46

@wdio/mocha-framework

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/mocha-framework@46

@testplane/wdio-protocols

npm i https://pkg.pr.new/gemini-testing/webdriverio/@testplane/wdio-protocols@46

@testplane/wdio-repl

npm i https://pkg.pr.new/gemini-testing/webdriverio/@testplane/wdio-repl@46

@wdio/reporter

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/reporter@46

@wdio/runner

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/runner@46

@wdio/sauce-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/sauce-service@46

@wdio/shared-store-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/shared-store-service@46

@wdio/smoke-test-cjs-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/smoke-test-cjs-service@46

@wdio/smoke-test-reporter

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/smoke-test-reporter@46

@wdio/smoke-test-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/smoke-test-service@46

@wdio/spec-reporter

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/spec-reporter@46

@wdio/static-server-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/static-server-service@46

@wdio/sumologic-reporter

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/sumologic-reporter@46

@wdio/testingbot-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/testingbot-service@46

@testplane/wdio-types

npm i https://pkg.pr.new/gemini-testing/webdriverio/@testplane/wdio-types@46

@testplane/wdio-utils

npm i https://pkg.pr.new/gemini-testing/webdriverio/@testplane/wdio-utils@46

@wdio/webdriver-mock-service

npm i https://pkg.pr.new/gemini-testing/webdriverio/@wdio/webdriver-mock-service@46

@testplane/webdriver

npm i https://pkg.pr.new/gemini-testing/webdriverio/@testplane/webdriver@46

@testplane/webdriverio

npm i https://pkg.pr.new/gemini-testing/webdriverio/@testplane/webdriverio@46

commit: a16b25f

Comment thread packages/wdio-types/src/Options.ts Outdated
* Base delay in ms for exponential backoff on 429 responses during session creation.
* If set, retries use exponential backoff instead of immediate retry.
*/
exp429RetryBaseDelay?: number

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest removing the option and leaving only the constant value. In my opinion, there is no reason for a new option.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Comment thread packages/webdriver/src/request/index.ts Outdated
log.warn(msg)
log.info(`Retrying ${retryCount}/${totalRetryCount}`)

const exp429RetryBaseDelay = fullRequestOptions.exp429RetryBaseDelay

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest changing the name of this variable it's too complicated

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Comment thread packages/webdriver/src/request/index.ts Outdated
log.info(`Retrying ${retryCount}/${totalRetryCount}`)

const exp429RetryBaseDelay = fullRequestOptions.exp429RetryBaseDelay
if (exp429RetryBaseDelay && !(response instanceof Error) && response.statusCode === 429) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we here retraying absolutely all requests, not just for creating a session?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now all 429

Comment thread packages/webdriver/src/request/index.ts Outdated
const exp429RetryBaseDelay = fullRequestOptions.exp429RetryBaseDelay
if (exp429RetryBaseDelay && !(response instanceof Error) && response.statusCode === 429) {
const delay = Math.round(exp429RetryBaseDelay * 2 ** (retryCount - 1) + Math.random() * 100)
log.warn(`Session creation failed with 429, retrying in ${delay}ms`)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure we need a warning here, not a debug log?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to debug

Comment thread packages/webdriver/src/request/index.ts Outdated

const exp429RetryBaseDelay = fullRequestOptions.exp429RetryBaseDelay
if (exp429RetryBaseDelay && !(response instanceof Error) && response.statusCode === 429) {
const delay = Math.round(exp429RetryBaseDelay * 2 ** (retryCount - 1) + Math.random() * 100)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is the jitter so low? Only 100ms

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to 1000

Comment thread packages/webdriver/src/request/index.ts Outdated
const delay = Math.round(exp429RetryBaseDelay * 2 ** (retryCount - 1) + Math.random() * 100)
log.warn(`Session creation failed with 429, retrying in ${delay}ms`)
return new Promise(resolve => setTimeout(resolve, delay)).then(
() => this._request(fullRequestOptions, transformResponse, customWdRequestAgent, totalRetryCount, retryCount)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just delete this call and use the call of this._request below?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used here timeout and it was more easy to implement

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used here timeout and it was more easy to implement

I don't understand why is code duplication easier to implement?
In my opinion, it is more correct to call the method once, especially if it has 4 parameters.

return new Promise(resolve => setTimeout(resolve, delay)).then(
() => this._request(fullRequestOptions, transformResponse, customWdRequestAgent, totalRetryCount, retryCount)
)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if tomorrow we let the user manage connectionRetryCount option? And he set value 10. How much we should wait? I'm saying that we need some kind of maximum limit.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We set this on testplane side, and maybe we have to set max limit there and do it when we provide it to config for users?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usually, when implementing retires logic, jitter and the maximum limit are always used

@sonic16x
sonic16x merged commit 9ea8c59 into master Aug 14, 2026
14 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants