PYTHON-4919 Resync tests for retryable writes (#2006)

This commit is contained in:
Shane Harvey 2024-11-18 10:26:22 -08:00 committed by GitHub
parent c9d9d7c2dc
commit 1dd42173e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 705 additions and 100 deletions

View File

@ -1,4 +1,4 @@
# Copyright 2017 MongoDB, Inc.
# Copyright 2017-present MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -43,7 +43,6 @@ from bson.codec_options import DEFAULT_CODEC_OPTIONS
from bson.int64 import Int64
from bson.raw_bson import RawBSONDocument
from bson.son import SON
from pymongo.asynchronous.mongo_client import AsyncMongoClient
from pymongo.errors import (
AutoReconnect,
ConnectionFailure,
@ -226,47 +225,6 @@ class TestRetryableWrites(IgnoreDeprecationsTest):
f"{msg} sent txnNumber with {event.command_name}",
)
@async_client_context.require_no_standalone
async def test_supported_single_statement_supported_cluster(self):
for method, args, kwargs in retryable_single_statement_ops(self.db.retryable_write_test):
msg = f"{method.__name__}(*{args!r}, **{kwargs!r})"
self.listener.reset()
await method(*args, **kwargs)
commands_started = self.listener.started_events
self.assertEqual(len(self.listener.succeeded_events), 1, msg)
first_attempt = commands_started[0]
self.assertIn(
"lsid",
first_attempt.command,
f"{msg} sent no lsid with {first_attempt.command_name}",
)
initial_session_id = first_attempt.command["lsid"]
self.assertIn(
"txnNumber",
first_attempt.command,
f"{msg} sent no txnNumber with {first_attempt.command_name}",
)
# There should be no retry when the failpoint is not active.
if async_client_context.is_mongos or not async_client_context.test_commands_enabled:
self.assertEqual(len(commands_started), 1)
continue
initial_transaction_id = first_attempt.command["txnNumber"]
retry_attempt = commands_started[1]
self.assertIn(
"lsid",
retry_attempt.command,
f"{msg} sent no lsid with {first_attempt.command_name}",
)
self.assertEqual(retry_attempt.command["lsid"], initial_session_id, msg)
self.assertIn(
"txnNumber",
retry_attempt.command,
f"{msg} sent no txnNumber with {first_attempt.command_name}",
)
self.assertEqual(retry_attempt.command["txnNumber"], initial_transaction_id, msg)
async def test_supported_single_statement_unsupported_cluster(self):
if async_client_context.is_rs or async_client_context.is_mongos:
raise SkipTest("This cluster supports retryable writes")

View File

@ -0,0 +1,144 @@
{
"description": "aggregate with $out/$merge does not set txnNumber",
"schemaVersion": "1.3",
"runOnRequirements": [
{
"minServerVersion": "3.6",
"topologies": [
"replicaset",
"sharded",
"load-balanced"
]
}
],
"createEntities": [
{
"client": {
"id": "client0",
"observeEvents": [
"commandStartedEvent"
]
}
},
{
"database": {
"id": "database0",
"client": "client0",
"databaseName": "retryable-writes-tests"
}
},
{
"collection": {
"id": "collection0",
"database": "database0",
"collectionName": "coll0"
}
}
],
"initialData": [
{
"collectionName": "mergeCollection",
"databaseName": "retryable-writes-tests",
"documents": []
}
],
"tests": [
{
"description": "aggregate with $out does not set txnNumber",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$sort": {
"x": 1
}
},
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$out": "outCollection"
}
]
}
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "aggregate",
"command": {
"txnNumber": {
"$$exists": false
}
}
}
}
]
}
]
},
{
"description": "aggregate with $merge does not set txnNumber",
"runOnRequirements": [
{
"minServerVersion": "4.1.11"
}
],
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$sort": {
"x": 1
}
},
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$merge": {
"into": "mergeCollection"
}
}
]
}
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "aggregate",
"command": {
"txnNumber": {
"$$exists": false
}
}
}
}
]
}
]
}
]
}

View File

@ -13,7 +13,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": false
"useMultipleMongoses": false,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -121,6 +124,53 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "update",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "delete",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{
@ -510,6 +560,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{
@ -926,6 +1003,81 @@
]
}
]
},
{
"description": "collection bulkWrite with updateMany does not set txnNumber",
"operations": [
{
"object": "collection0",
"name": "bulkWrite",
"arguments": {
"requests": [
{
"updateMany": {
"filter": {},
"update": {
"$set": {
"x": 1
}
}
}
}
]
}
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "update",
"command": {
"txnNumber": {
"$$exists": false
}
}
}
}
]
}
]
},
{
"description": "collection bulkWrite with deleteMany does not set txnNumber",
"operations": [
{
"object": "collection0",
"name": "bulkWrite",
"arguments": {
"requests": [
{
"deleteMany": {
"filter": {}
}
}
]
}
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "delete",
"command": {
"txnNumber": {
"$$exists": false
}
}
}
}
]
}
]
}
]
}

View File

@ -428,7 +428,10 @@
{
"ns": "retryable-writes-tests.coll0"
}
]
],
"txnNumber": {
"$$exists": false
}
}
}
}
@ -779,7 +782,10 @@
{
"ns": "retryable-writes-tests.coll0"
}
]
],
"txnNumber": {
"$$exists": false
}
}
}
}
@ -861,7 +867,10 @@
{
"ns": "retryable-writes-tests.coll0"
}
]
],
"txnNumber": {
"$$exists": false
}
}
}
}

View File

@ -15,7 +15,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": true
"useMultipleMongoses": true,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -70,6 +73,23 @@
"databaseName": "retryable-writes-tests",
"documents": []
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "delete",
"command": {
"txnNumber": {
"$$exists": false
}
}
}
}
]
}
]
}
]

View File

@ -13,7 +13,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": false
"useMultipleMongoses": false,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -88,6 +91,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "delete",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "delete",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{

View File

@ -13,7 +13,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": false
"useMultipleMongoses": false,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -94,6 +97,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "findAndModify",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "findAndModify",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{

View File

@ -13,7 +13,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": false
"useMultipleMongoses": false,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -98,6 +101,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "findAndModify",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "findAndModify",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{

View File

@ -13,7 +13,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": false
"useMultipleMongoses": false,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -99,6 +102,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "findAndModify",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "findAndModify",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{

View File

@ -13,7 +13,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": false
"useMultipleMongoses": false,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -107,6 +110,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{
@ -172,6 +202,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{

View File

@ -13,7 +13,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": false
"useMultipleMongoses": false,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -101,6 +104,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{

View File

@ -13,7 +13,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": false
"useMultipleMongoses": false,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -98,6 +101,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "update",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "update",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{

View File

@ -0,0 +1,77 @@
{
"description": "unacknowledged write does not set txnNumber",
"schemaVersion": "1.3",
"runOnRequirements": [
{
"minServerVersion": "3.6",
"topologies": [
"replicaset",
"sharded",
"load-balanced"
]
}
],
"createEntities": [
{
"client": {
"id": "client0",
"observeEvents": [
"commandStartedEvent"
]
}
},
{
"database": {
"id": "database0",
"client": "client0",
"databaseName": "retryable-writes-tests"
}
},
{
"collection": {
"id": "collection0",
"database": "database0",
"collectionName": "coll0",
"collectionOptions": {
"writeConcern": {
"w": 0
}
}
}
}
],
"tests": [
{
"description": "unacknowledged write does not set txnNumber",
"operations": [
{
"object": "collection0",
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"x": 11
}
}
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "insert",
"command": {
"txnNumber": {
"$$exists": false
}
}
}
}
]
}
]
}
]
}

View File

@ -15,7 +15,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": true
"useMultipleMongoses": true,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -86,6 +89,23 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "update",
"command": {
"txnNumber": {
"$$exists": false
}
}
}
}
]
}
]
}
]

View File

@ -13,7 +13,10 @@
{
"client": {
"id": "client0",
"useMultipleMongoses": false
"useMultipleMongoses": false,
"observeEvents": [
"commandStartedEvent"
]
}
},
{
@ -99,6 +102,33 @@
}
]
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"commandName": "update",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
},
{
"commandStartedEvent": {
"commandName": "update",
"command": {
"txnNumber": {
"$$exists": true
}
}
}
}
]
}
]
},
{

View File

@ -1,4 +1,4 @@
# Copyright 2017 MongoDB, Inc.
# Copyright 2017-present MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -65,7 +65,6 @@ from pymongo.operations import (
UpdateMany,
UpdateOne,
)
from pymongo.synchronous.mongo_client import MongoClient
from pymongo.write_concern import WriteConcern
_IS_SYNC = True
@ -226,47 +225,6 @@ class TestRetryableWrites(IgnoreDeprecationsTest):
f"{msg} sent txnNumber with {event.command_name}",
)
@client_context.require_no_standalone
def test_supported_single_statement_supported_cluster(self):
for method, args, kwargs in retryable_single_statement_ops(self.db.retryable_write_test):
msg = f"{method.__name__}(*{args!r}, **{kwargs!r})"
self.listener.reset()
method(*args, **kwargs)
commands_started = self.listener.started_events
self.assertEqual(len(self.listener.succeeded_events), 1, msg)
first_attempt = commands_started[0]
self.assertIn(
"lsid",
first_attempt.command,
f"{msg} sent no lsid with {first_attempt.command_name}",
)
initial_session_id = first_attempt.command["lsid"]
self.assertIn(
"txnNumber",
first_attempt.command,
f"{msg} sent no txnNumber with {first_attempt.command_name}",
)
# There should be no retry when the failpoint is not active.
if client_context.is_mongos or not client_context.test_commands_enabled:
self.assertEqual(len(commands_started), 1)
continue
initial_transaction_id = first_attempt.command["txnNumber"]
retry_attempt = commands_started[1]
self.assertIn(
"lsid",
retry_attempt.command,
f"{msg} sent no lsid with {first_attempt.command_name}",
)
self.assertEqual(retry_attempt.command["lsid"], initial_session_id, msg)
self.assertIn(
"txnNumber",
retry_attempt.command,
f"{msg} sent no txnNumber with {first_attempt.command_name}",
)
self.assertEqual(retry_attempt.command["txnNumber"], initial_transaction_id, msg)
def test_supported_single_statement_unsupported_cluster(self):
if client_context.is_rs or client_context.is_mongos:
raise SkipTest("This cluster supports retryable writes")