test(NODE-7534): add prose tests for retry behavior with mixed overload/non-overload errors#4921
Conversation
…-overload errors - Add 4 new prose tests per spec commit 7039e69 - Test 4 (reads/writes): Verify MAX_RETRIES applies to all errors after overload - Test 5 (reads/writes): Verify backoff only applies to overload errors - Uses mocking pattern consistent with existing prose tests
There was a problem hiding this comment.
Pull request overview
Adds new prose integration tests to validate the driver’s retry behavior when encountering an initial SystemOverloadedError followed by subsequent non-overload retryable errors, per the referenced spec guidance.
Changes:
- Add new retryable-writes prose cases to verify
MAX_RETRIESis honored across mixed overload/non-overload retryable write errors. - Add new retryable-reads prose cases to verify
MAX_RETRIESis honored across mixed overload/non-overload retryable read errors. - Add timing-based assertions (via
measureDuration) to ensure backoff is only applied to overload-labeled errors.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| test/integration/retryable-writes/retryable_writes.spec.prose.test.ts | Adds Case 4/5 prose tests for mixed overload/non-overload retry behavior and backoff timing for retryable writes. |
| test/integration/retryable-reads/retryable_reads.spec.prose.test.ts | Adds new prose suites to validate max-retry behavior and backoff timing for retryable reads under mixed error-label sequences. |
| TEST_METADATA, | ||
| async function () { | ||
| // Configure the random number generator used for jitter to always return a number as close as possible to `1`. | ||
| const randomStub = sinon.stub(Math, 'random'); |
There was a problem hiding this comment.
We're doing this so we can have a predictable wait. The spec requires this:
Assert that backoff was applied only once for the initial overload error and not for the subsequent
non-overload retryable errors.
Should the spec be updated with instructions to use this approach? Or is it largely up to each team to determine how this gets verified?
There was a problem hiding this comment.
Pull request overview
Adds new prose tests to validate retry/backoff behavior when an initial SystemOverloadedError is followed by retryable non-overload errors, aligning with the retryable reads/writes prose spec scenarios.
Changes:
- Add “Case 4” tests asserting
MAX_RETRIES + 1attempts occur even when later retryable errors are not overload errors (reads + writes). - Add “Case 5” tests intended to assert backoff is applied only for overload errors (reads + writes).
- Introduce
measureDurationusage to time retry sequences for the backoff assertions.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
test/integration/retryable-writes/retryable_writes.spec.prose.test.ts |
Adds two new prose cases (max retries after overload; backoff only for overload) using Server.prototype.command stubbing + timing. |
test/integration/retryable-reads/retryable_reads.spec.prose.test.ts |
Adds two new prose describes for the same behaviors for reads, including new imports and per-describe client lifecycle hooks. |
| // If the driver incorrectly applied backoff to all retries, total would be 0.99*(100+200) = ~297ms. | ||
| const expectedMinBackoff = 90; // First backoff | ||
| const expectedMaxBackoff = expectedMinBackoff + 1000; // Allow 1 second margin for test overhead |
There was a problem hiding this comment.
Comment seems reasonable. @nbbeeken , can we use Math.random=0 to test the very shortest time it should take to run all the operations?
There was a problem hiding this comment.
Yes seems reasonable
| const expectedMinBackoff = 90; // First backoff | ||
| const expectedMaxBackoff = expectedMinBackoff + 1000; // Allow 1 second margin for test overhead |
| let client: MongoClient; | ||
|
|
||
| beforeEach(async function () { | ||
| // 1. Create a client. | ||
| client = this.configuration.newClient({ | ||
| monitorCommands: true, | ||
| retryReads: true | ||
| }); | ||
| await client.connect(); | ||
| }); | ||
|
|
||
| afterEach(async function () { | ||
| sinon.restore(); | ||
| await client?.close(); | ||
| }); |
nbbeeken
left a comment
There was a problem hiding this comment.
LGTM on the changes
Description
Summary of Changes
Notes for Reviewers
WIP
What is the motivation for this change?
Coverage reccomended by spec
Double check the following
npm run check:lint)type(NODE-xxxx)[!]: descriptionfeat(NODE-1234)!: rewriting everything in coffeescript