JAVA-6055 Implement prose backpressure retryable writes tests#1929
JAVA-6055 Implement prose backpressure retryable writes tests#1929stIncMale wants to merge 2 commits intomongodb:backpressurefrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds/updates prose tests to cover the retryable writes “backpressure retryable writes” scenarios from the spec updates, including refactoring test infrastructure to configure fail points in reaction to command events.
Changes:
- Introduce
ConfigureFailPointCommandListenerto enable a failpoint once upon matching aCommandEvent, and automatically disable it via try-with-resources. - Refactor existing retryable reads/writes prose tests to use the new helper and updated spec link references.
- Add new “error propagation after encountering multiple errors” retryable writes prose test cases (with Case 1 temporarily disabled behind TODO-BACKPRESSURE).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| driver-sync/src/test/functional/com/mongodb/internal/event/ConfigureFailPointCommandListener.java | New test utility to configure/cleanup failpoints triggered by command events. |
| driver-sync/src/test/functional/com/mongodb/client/RetryableWritesProseTest.java | Refactor existing prose tests; add new multi-error propagation cases. |
| driver-sync/src/test/functional/com/mongodb/client/RetryableReadsProseTest.java | Update prose-test references and align helper usage/signatures. |
| driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableWritesProseTest.java | Mirror sync prose test updates via sync-adapter delegation; add new cases. |
| driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableReadsProseTest.java | Update prose-test references and align helper usage/signatures. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
driver-sync/src/test/functional/com/mongodb/client/RetryableWritesProseTest.java
Show resolved
Hide resolved
...-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableReadsProseTest.java
Outdated
Show resolved
Hide resolved
53e526f to
44c8119
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
44c8119 to
973ee55
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...r-sync/src/test/functional/com/mongodb/internal/event/ConfigureFailPointCommandListener.java
Outdated
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/RetryableWritesProseTest.java
Outdated
Show resolved
Hide resolved
973ee55 to
758b89e
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
driver-sync/src/test/functional/com/mongodb/client/RetryableWritesProseTest.java
Outdated
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/RetryableWritesProseTest.java
Outdated
Show resolved
Hide resolved
758b89e to
d270460
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableReadsProseTest.java
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/RetryableWritesProseTest.java
Outdated
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/RetryableWritesProseTest.java
Outdated
Show resolved
Hide resolved
The relevant spec changes: - https://github.com/mongodb/specifications/blame/ba14b6bdc1dc695aa9cc20ccf9378592da1b2329/source/retryable-writes/tests/README.md#L265-L418 - See also https://jira.mongodb.org/browse/DRIVERS-3432 for the required fixes for "Test 3 Case 3" JAVA-6055
d270460 to
72d70e4
Compare
nhachicha
left a comment
There was a problem hiding this comment.
Good idea extracting ConfigureFailPointCommandListener as a reusable utility 👍
some minor comments from me & Claude review
| fail("The listener was closed before (in the happens-before order) it attempted to configure the fail point"); | ||
| } else { | ||
| assertTrue(failPointFuture.isDone()); | ||
| assertNotNull(failPointFuture.get()).close(); |
There was a problem hiding this comment.
[minor]
If failPointFuture is completed exceptionally (via completeExceptionally), then failPointFuture.get() in close() will throw, so the normal FailPoint.close() is skipped and the fail point may remain enabled.
This is, however, low-risk since there may be nothing to clean up if FailPoint.enable() fails ...
| @Override | ||
| public void close() throws InterruptedException, ExecutionException { | ||
| synchronized (lock) { | ||
| if (failPointFuture.cancel(true)) { |
There was a problem hiding this comment.
[TIL]
mayInterruptIfRunning is no-op
mayInterruptIfRunning - this value has no effect in this implementation because interrupts are not used to control processing.
| + " data: {\n" | ||
| + " failCommands: [\"" + operationName + "\"],\n" | ||
| + " failCommands: [\"" + expectedCommandName + "\"],\n" | ||
| + " errorCode: 6,\n" |
There was a problem hiding this comment.
[claude-review]
Trailing comma in generated JSON when write=false.
The old code avoided this by placing errorCode last
The same pattern appears in retriesOnSameMongosWhenAnotherNotAvailable
| Predicate<CommandEvent> configureFailPointEventMatcher = event -> { | ||
| if (event instanceof CommandFailedEvent) { | ||
| CommandFailedEvent commandFailedEvent = (CommandFailedEvent) event; | ||
| MongoException cause = assertInstanceOf(MongoException.class, commandFailedEvent.getThrowable()); |
There was a problem hiding this comment.
[claude-review]
The predicates use assertInstanceOf(MongoException.class, ...) which throws AssertionFailedError if the type doesn't match. A Predicate.test() should return false, not throw. The exception is caught by onEvent() and routed to completeExceptionally, so it works, but the semantics are surprising. Consider using a plain instanceof check instead.
| Predicate<CommandEvent> configureFailPointEventMatcher = event -> { | ||
| if (event instanceof CommandFailedEvent) { | ||
| CommandFailedEvent commandFailedEvent = (CommandFailedEvent) event; | ||
| MongoException cause = assertInstanceOf(MongoException.class, commandFailedEvent.getThrowable()); |
There was a problem hiding this comment.
| import static com.mongodb.assertions.Assertions.assertTrue; | ||
| import static com.mongodb.assertions.Assertions.fail; | ||
|
|
||
| public final class ConfigureFailPointCommandListener implements CommandListener, AutoCloseable { |
There was a problem hiding this comment.
Worth annotating with @ThreadSafe ?
| + " failCommands: ['" + commandName + "'],\n" | ||
| + " errorCode: 91,\n" | ||
| + " blockConnection: true,\n" | ||
| + " blockTimeMS: 1000,\n" |
There was a problem hiding this comment.
Trailing comma issue when write == false. I wonder if we should keep the append approach of building the BsonDocument
similar to https://github.com/mongodb/mongo-java-driver/pull/1929/changes#r3005045523
| + " data: {\n" | ||
| + " failCommands: [\"" + operationName + "\"],\n" | ||
| + " failCommands: [\"" + expectedCommandName + "\"],\n" | ||
| + " errorCode: 6,\n" |
There was a problem hiding this comment.
| + "', '" + NO_WRITES_PERFORMED_ERROR_LABEL + "']\n" | ||
| + " }\n" | ||
| + "}\n"); | ||
| Predicate<CommandEvent> configureFailPointEventMatcher = event -> event instanceof CommandFailedEvent; |
There was a problem hiding this comment.
[minor]
Both the initial and the listener fail points use error code 91, for consistency and defensiveness, checking code == 91 wouldn't hurt — if something unexpected fails first (e.g., a different command), the test would configure the second fail point at the wrong time and produce a confusing failure.
The relevant spec changes:
I recommend reviewing the first two commits one by one to simplify reviewing: the first commit does the refactoring, including the necessary refactoring (the introduction of
ConfigureFailPointCommandListener), the second commit adds the new tests.I used the
TODO-BACKPRESSURE Valentincomments as described in #1918.JAVA-6055