From 5b9077c974c7e1ca78c7d1795761817cc60e6bdb Mon Sep 17 00:00:00 2001 From: Antonio Fuschetto Date: Thu, 12 May 2022 10:52:56 +0000 Subject: SERVER-66312 Tests on batched operations do not involve orphaned documents --- jstests/sharding/change_stream_no_orphans.js | 306 +++++++++++---------------- 1 file changed, 128 insertions(+), 178 deletions(-) diff --git a/jstests/sharding/change_stream_no_orphans.js b/jstests/sharding/change_stream_no_orphans.js index 98d5fd1bcd6..ce4d35c847c 100644 --- a/jstests/sharding/change_stream_no_orphans.js +++ b/jstests/sharding/change_stream_no_orphans.js @@ -1,13 +1,12 @@ /** * Verify that write operations on orphaned documents (1) do not show up unexpected events in change - * streams and (2) have no effect on the persisted data. + * streams and (2) have a certain behavior on the persisted data. * * The behavior is tested in the following scenarios: - * - Direct operations to shard on orphaned documents - * - Broadcasted operations (from router) on orphaned documents - * - Transaction from router updating both orphaned and non-orphaned documents - * - Transaction to shard updating both orphaned and non-orphaned documents - * - Batched deletes from router and to shard + * - Test case 1: Direct operations to shard on orphaned documents + * - Test case 2: Broadcasted operations (from router) on orphaned documents + * - Test case 3: Transaction from router updating both orphaned and owned documents + * - Test case 4: Transaction to shard updating both orphaned and owned documents * * @tags: [ * requires_fcv_53, @@ -19,6 +18,19 @@ load('jstests/libs/fail_point_util.js'); // For configureFailPoint +// Asserts that there is no event. +function assertNoChanges(csCursor) { + function advanceAndGetToken() { + assert(!csCursor.hasNext(), () => csCursor.next()); + return csCursor.getResumeToken(); + } + const startToken = advanceAndGetToken(); + assert.soon(() => { + const currentToken = advanceAndGetToken(); + return bsonWoCompare(currentToken, startToken) > 0; + }); +} + const dbName = 'test'; const collName = 'foo'; const collNS = dbName + '.' + collName; @@ -29,7 +41,7 @@ const st = new ShardingTest({ mongos: 1, config: 1, shards: 2, - rs: {nodes: 1, setParameter: {writePeriodicNoops: true}}, + rs: {nodes: 1, setParameter: {writePeriodicNoops: true, periodicNoopIntervalSecs: 1}}, other: {enableBalancer: false} }); @@ -42,14 +54,15 @@ assert.commandWorked( st.s.adminCommand({enableSharding: dbName, primaryShard: st.shard0.shardName})); assert.commandWorked(st.s.adminCommand({shardCollection: collNS, key: {_id: 1}})); const coll = st.s.getCollection(collNS); -assert.commandWorked(coll.insert({_id: -2, name: 'emma', age: 20})); -assert.commandWorked(coll.insert({_id: -1, name: 'olivia', age: 25})); -assert.commandWorked(coll.insert({_id: 0, name: 'matt', age: 30})); -assert.commandWorked(coll.insert({_id: 1, name: 'john', age: 35})); -assert.commandWorked(coll.insert({_id: 2, name: 'robert', age: 40})); -assert.commandWorked(coll.insert({_id: 3, name: 'robert', age: 45})); -assert.commandWorked(coll.insert({_id: 4, name: 'james', age: 50})); -assert.commandWorked(coll.insert({_id: 5, name: 'liam', age: 55})); +assert.commandWorked(coll.insert({_id: -2, name: 'emma', age: 20})); // Test case 4 +assert.commandWorked(coll.insert({_id: -1, name: 'olivia', age: 25})); // Test case 3 +assert.commandWorked(coll.insert({_id: 0, name: 'matt', age: 30})); // Test case 1 +assert.commandWorked(coll.insert({_id: 1, name: 'matt', age: 35})); // Test case 1 +assert.commandWorked(coll.insert({_id: 2, name: 'john', age: 40})); // Test case 2 +assert.commandWorked(coll.insert({_id: 3, name: 'robert', age: 45})); // Test case 2 +assert.commandWorked(coll.insert({_id: 4, name: 'robert', age: 50})); // Test case 2 +assert.commandWorked(coll.insert({_id: 5, name: 'james', age: 55})); // Test case 3 +assert.commandWorked(coll.insert({_id: 6, name: 'liam', age: 60})); // Test case 4 // Move the chunk to the second shard leaving orphaned documents on the first shard. assert.commandWorked(st.s.adminCommand({split: collNS, middle: {_id: 0}})); @@ -60,64 +73,91 @@ assert.commandWorked( const changeStream = coll.watch([]); //////////////////////////////////////////////////////////////////////////////////////////////////// -// Direct operations to shard on orphaned documents +// Test case 1: Direct operations to shard on orphaned documents //////////////////////////////////////////////////////////////////////////////////////////////////// jsTest.log('A direct insert to a shard of an orphaned document does not generate an insert event'); { // Direct insert to first shard of an orphaned document. - assert.commandWorked(st.shard0.getCollection(collNS).insert({_id: 6, name: 'ken', age: 60})); + assert.commandWorked(st.shard0.getCollection(collNS).insert({_id: 7, name: 'ken', age: 65})); // No event is notified. - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); // The orphaned document on first shard has been inserted. - assert.neq(null, st.shard0.getCollection(collNS).findOne({_id: 6})); + assert.neq(null, st.shard0.getCollection(collNS).findOne({_id: 7})); } jsTest.log('A direct update to a shard of an orphaned document does not generate an update event'); { // Send a direct update to first shard on an orphaned document. - assert.commandWorked(st.shard0.getCollection(collNS).update({name: 'matt'}, {$set: {age: 31}})); + assert.commandWorked(st.shard0.getCollection(collNS).update({name: 'ken'}, {$set: {age: 66}})); // No change stream event is generated. - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); // The orphaned document on first shard has been updated. - assert.eq(31, st.shard0.getCollection(collNS).findOne({_id: 0}).age); + assert.eq(66, st.shard0.getCollection(collNS).findOne({_id: 7}).age); } jsTest.log('A direct delete to a shard of an orphaned document does generate an update event'); { // Send a direct delete to first shard on an orphaned document. - assert.commandWorked(st.shard0.getCollection(collNS).remove({name: 'matt'})); + assert.commandWorked(st.shard0.getCollection(collNS).remove({name: 'ken'})); // No change stream event is generated. - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); // The orphaned document on first shard has been removed. + assert.eq(null, st.shard0.getCollection(collNS).findOne({_id: 7})); +} + +jsTest.log('A direct update to a shard of multi-documents does not generate update events'); +{ + // Send a direct update to first shard on two orphaned documents. + assert.commandWorked( + st.shard0.getCollection(collNS).update({name: 'matt'}, {$set: {age: 31}}, {multi: true})); + + // No change stream event is generated. + assertNoChanges(changeStream); + + // The orphaned documents on first shard have been updated + assert.eq(31, st.shard0.getCollection(collNS).findOne({_id: 0}).age); + assert.eq(31, st.shard0.getCollection(collNS).findOne({_id: 1}).age); +} + +jsTest.log('A direct delete to a shard of multi-documents does not generate delete events'); +{ + // Send a direct delete to first shard on an orphaned document. + assert.commandWorked(st.shard0.getCollection(collNS).remove({name: 'matt'})); + + // No change stream event is generated. + assertNoChanges(changeStream); + + // The orphaned documents on first shard have been removed. assert.eq(null, st.shard0.getCollection(collNS).findOne({_id: 0})); + assert.eq(null, st.shard0.getCollection(collNS).findOne({_id: 1})); } //////////////////////////////////////////////////////////////////////////////////////////////////// -// Broadcasted operations (from router) on orphaned documents +// Test case 2: Broadcasted operations (from router) on orphaned documents //////////////////////////////////////////////////////////////////////////////////////////////////// jsTest.log('A broadcasted update of a single document generates an update event'); { // Send a broadcasted update (query on non-key field) on a single document to all the shards. - assert.commandWorked(coll.update({name: 'john'}, {$set: {age: 36}}, {multi: true})); + assert.commandWorked(coll.update({name: 'john'}, {$set: {age: 41}}, {multi: true})); // The document is hosted by the second shard and the update event is notified. The first shard // still hosts the orphaned document so no additional event must be notified. assert.soon(() => changeStream.hasNext(), 'An update event is expected'); assert.eq(changeStream.next().operationType, 'update'); - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); - // The orphaned document on first shard has not been updated, unlike the non-orphaned one on the - // second shard. - assert.eq(35, st.shard0.getCollection(collNS).findOne({_id: 1}).age); - assert.eq(36, st.shard1.getCollection(collNS).findOne({_id: 1}).age); + // The orphaned document on first shard has not been updated, unlike the owned one on the second + // shard. + assert.eq(40, st.shard0.getCollection(collNS).findOne({_id: 2}).age); + assert.eq(41, st.shard1.getCollection(collNS).findOne({_id: 2}).age); } jsTest.log('A broadcasted delete of a single document generates a delete event'); @@ -129,18 +169,18 @@ jsTest.log('A broadcasted delete of a single document generates a delete event') // still hosts the orphaned document so no additional event must be notified. assert.soon(() => changeStream.hasNext(), 'A delete event is expected'); assert.eq(changeStream.next().operationType, 'delete'); - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); - // The orphaned document on first shard has not been removed, unlike the non-orphaned one on the - // second shard. - assert.neq(null, st.shard0.getCollection(collNS).findOne({_id: 1})); - assert.eq(null, st.shard1.getCollection(collNS).findOne({_id: 1})); + // The orphaned document on first shard has not been removed, unlike the owned one on the second + // shard. + assert.neq(null, st.shard0.getCollection(collNS).findOne({_id: 2})); + assert.eq(null, st.shard1.getCollection(collNS).findOne({_id: 2})); } jsTest.log('A broadcasted update of multi-documents generates more update events'); { // Send a broadcasted update (query on non-key field) on two documents to all the shards. - assert.commandWorked(coll.update({name: 'robert'}, {$set: {age: 41}}, {multi: true})); + assert.commandWorked(coll.update({name: 'robert'}, {$set: {age: 46}}, {multi: true})); // The documents are hosted by the second shard and two delete events are notified. The first // shard still hosts the orphaned documents so no additional event must be notified. @@ -148,14 +188,14 @@ jsTest.log('A broadcasted update of multi-documents generates more update events assert.eq(changeStream.next().operationType, 'update'); assert.soon(() => changeStream.hasNext(), 'A second update event is expected'); assert.eq(changeStream.next().operationType, 'update'); - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); - // The orphaned documents on first shard have not been updated, unlike the non-orphaned ones on - // the second shard. - assert.eq(40, st.shard0.getCollection(collNS).findOne({_id: 2}).age); + // The orphaned documents on first shard have not been updated, unlike the owned ones on the + // second shard. assert.eq(45, st.shard0.getCollection(collNS).findOne({_id: 3}).age); - assert.eq(41, st.shard1.getCollection(collNS).findOne({_id: 2}).age); - assert.eq(41, st.shard1.getCollection(collNS).findOne({_id: 3}).age); + assert.eq(50, st.shard0.getCollection(collNS).findOne({_id: 4}).age); + assert.eq(46, st.shard1.getCollection(collNS).findOne({_id: 3}).age); + assert.eq(46, st.shard1.getCollection(collNS).findOne({_id: 4}).age); } jsTest.log('A broadcasted delete of multi-documents generates more delete events'); @@ -169,55 +209,52 @@ jsTest.log('A broadcasted delete of multi-documents generates more delete events assert.eq(changeStream.next().operationType, 'delete'); assert.soon(() => changeStream.hasNext(), 'A second delete event is expected'); assert.eq(changeStream.next().operationType, 'delete'); - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); - // The orphaned documents on first shard have not been removed, unlike the non-orphaned ones on - // the second shard. - assert.neq(null, st.shard0.getCollection(collNS).findOne({_id: 2})); + // The orphaned documents on first shard have not been removed, unlike the owned ones on the + // second shard. assert.neq(null, st.shard0.getCollection(collNS).findOne({_id: 3})); - assert.eq(null, st.shard1.getCollection(collNS).findOne({_id: 2})); + assert.neq(null, st.shard0.getCollection(collNS).findOne({_id: 4})); assert.eq(null, st.shard1.getCollection(collNS).findOne({_id: 3})); + assert.eq(null, st.shard1.getCollection(collNS).findOne({_id: 4})); } //////////////////////////////////////////////////////////////////////////////////////////////////// -// Transaction from router updating both orphaned and non-orphaned documents +// Test case 3: Transaction from router updating both orphaned and owned documents //////////////////////////////////////////////////////////////////////////////////////////////////// -jsTest.log('Broadcasted updates (via a transaction through the router) of both orphaned and ' + - 'non-orphaned documents generate events only for operations on non-orphaned documents'); +jsTest.log('Broadcasted updates (via a transaction through the router) of both orphaned and owned' + + 'documents generate events only for operations on owned documents'); { - // Send a broadcasted transaction to the router updating both orphaned and non-orphaned - // documents. + // Send a broadcasted transaction to the router updating both orphaned and owned documents. const session = st.s.startSession(); const sessionDB = session.getDatabase(dbName); const sessionColl = sessionDB.getCollection(collName); session.startTransaction(); assert.commandWorked(sessionColl.update({name: 'olivia'}, {$set: {age: 26}}, {multi: true})); - assert.commandWorked(sessionColl.update({name: 'james'}, {$set: {age: 51}}, {multi: true})); + assert.commandWorked(sessionColl.update({name: 'james'}, {$set: {age: 56}}, {multi: true})); assert.commandWorked(session.commitTransaction_forTesting()); session.endSession(); - // The primary shard hosts orphaned (james) and non-orphaned (olivia) documents, whereas the - // second shard hosts a non-orphaned document (james). Consequently, two update events are - // notified. + // The primary shard hosts orphaned (james) and owned (olivia) documents, whereas the second + // shard hosts an owned document (james). Consequently, two update events are notified. assert.soon(() => changeStream.hasNext(), 'A first update event is expected'); assert.eq(changeStream.next().operationType, 'update'); assert.soon(() => changeStream.hasNext(), 'A second update event is expected'); assert.eq(changeStream.next().operationType, 'update'); - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); - // The orphaned document on first shard (james) has not been updated, unlike the non-orphaned - // ones on both primary and second shards (olivia and james). + // The orphaned document on first shard (james) has not been updated, unlike the owned ones on + // both primary and second shards (olivia and james). assert.eq(26, st.shard0.getCollection(collNS).findOne({_id: -1}).age); - assert.eq(50, st.shard0.getCollection(collNS).findOne({_id: 4}).age); - assert.eq(51, st.shard1.getCollection(collNS).findOne({_id: 4}).age); + assert.eq(55, st.shard0.getCollection(collNS).findOne({_id: 5}).age); + assert.eq(56, st.shard1.getCollection(collNS).findOne({_id: 5}).age); } -jsTest.log('Broadcasted deletes (via a transaction through the router) of both orphaned and ' + - 'non-orphaned documents generate events only for operations on non-orphaned documents'); +jsTest.log('Broadcasted deletes (via a transaction through the router) of both orphaned and owned' + + 'documents generate events only for operations on owned documents'); { - // Send a broadcasted transaction to the router deleting both orphaned and non-orphaned - // documents. + // Send a broadcasted transaction to the router deleting both orphaned and owned documents. const session = st.s.startSession(); const sessionDB = session.getDatabase(dbName); const sessionColl = sessionDB.getCollection(collName); @@ -227,58 +264,57 @@ jsTest.log('Broadcasted deletes (via a transaction through the router) of both o assert.commandWorked(session.commitTransaction_forTesting()); session.endSession(); - // The primary shard hosts orphaned (james) and non-orphaned (olivia) documents, whereas the - // second shard hosts a non-orphaned document (james). Consequently, two delete events are - // notified. + // The primary shard hosts orphaned (james) and owned (olivia) documents, whereas the second + // shard hosts an owned document (james). Consequently, two delete events are notified. assert.soon(() => changeStream.hasNext(), 'A first delete event is expected'); assert.eq(changeStream.next().operationType, 'delete'); assert.soon(() => changeStream.hasNext(), 'A second delete event is expected'); assert.eq(changeStream.next().operationType, 'delete'); - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); - // The orphaned document on first shard (james) has not been removed, unlike the non-orphaned - // ones on both primary and second shards (olivia and james). + // The orphaned document on first shard (james) has not been removed, unlike the owned ones on + // both primary and second shards (olivia and james). assert.eq(null, st.shard0.getCollection(collNS).findOne({_id: -1})); - assert.neq(null, st.shard0.getCollection(collNS).findOne({_id: 4})); - assert.eq(null, st.shard1.getCollection(collNS).findOne({_id: 4})); + assert.neq(null, st.shard0.getCollection(collNS).findOne({_id: 5})); + assert.eq(null, st.shard1.getCollection(collNS).findOne({_id: 5})); } //////////////////////////////////////////////////////////////////////////////////////////////////// -// Transaction to shard updating both orphaned and non-orphaned documents +// Test case 4: Transaction to shard updating both orphaned and owned documents //////////////////////////////////////////////////////////////////////////////////////////////////// -jsTest.log('Direct updates (via a transaction to a shard) of both orphaned and non-orphaned' + - 'documents generate events only for operations on non-orphaned documents'); +jsTest.log('Direct updates (via a transaction to a shard) of both orphaned and owned documents' + + 'generate events only for operations on owned documents'); { - // Send a direct transaction to a shard updating both orphaned and non-orphaned documents. + // Send a direct transaction to a shard updating both orphaned and owned documents. const session = st.rs0.getPrimary().getDB(dbName).getMongo().startSession(); const sessionDB = session.getDatabase(dbName); const sessionColl = sessionDB.getCollection(collName); session.startTransaction(); assert.commandWorked(sessionColl.update({name: 'emma'}, {$set: {age: 21}}, {multi: true})); - assert.commandWorked(sessionColl.update({name: 'liam'}, {$set: {age: 56}}, {multi: true})); + assert.commandWorked(sessionColl.update({name: 'liam'}, {$set: {age: 61}}, {multi: true})); assert.commandWorked(session.commitTransaction_forTesting()); session.endSession(); - // The shard hosts both orphaned (liam) and non-orphaned (emma) documents. Consequently, only - // one update event is notified. + // The shard hosts both orphaned (liam) and owned (emma) documents. Consequently, only one + // update event is notified. // TODO (SERVER-65859): The second update event will be filtered out when the ticket is // completed. assert.soon(() => changeStream.hasNext(), 'A first update event is expected'); assert.eq(changeStream.next().operationType, 'update'); assert.soon(() => changeStream.hasNext(), 'A second update event is expected'); assert.eq(changeStream.next().operationType, 'update'); - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); - // Both orphaned (liam) and non-orphaned (emma) documents on the shard have been updated. + // Both orphaned (liam) and owned (emma) documents on the shard have been updated. assert.eq(21, st.shard0.getCollection(collNS).findOne({_id: -2}).age); - assert.eq(56, st.shard0.getCollection(collNS).findOne({_id: 5}).age); + assert.eq(61, st.shard0.getCollection(collNS).findOne({_id: 6}).age); } -jsTest.log('Direct deletes (via a transaction to a shard) of both orphaned and non-orphaned' + - 'documents generate events only for operations on non-orphaned documents'); +jsTest.log('Direct deletes (via a transaction to a shard) of both orphaned and owned documents' + + 'generate events only for operations on owned documents'); { - // Send a direct transaction to a shard deleting both orphaned and non-orphaned documents. + // Send a direct transaction to a shard deleting both orphaned and owned documents. const session = st.rs0.getPrimary().getDB(dbName).getMongo().startSession(); const sessionDB = session.getDatabase(dbName); const sessionColl = sessionDB.getCollection(collName); @@ -288,19 +324,19 @@ jsTest.log('Direct deletes (via a transaction to a shard) of both orphaned and n assert.commandWorked(session.commitTransaction_forTesting()); session.endSession(); - // The shard hosts both orphaned (liam) and non-orphaned (emma) documents. Consequently, only - // one update event is notified. + // The shard hosts both orphaned (liam) and owned (emma) documents. Consequently, only one + // update event is notified. // TODO (SERVER-65859): The second delete event will be filtered out when the ticket is // completed. assert.soon(() => changeStream.hasNext(), 'A first delete event is expected'); assert.eq(changeStream.next().operationType, 'delete'); assert.soon(() => changeStream.hasNext(), 'A second delete event is expected'); assert.eq(changeStream.next().operationType, 'delete'); - assert(!changeStream.hasNext()); + assertNoChanges(changeStream); - // Both orphaned (liam) and non-orphaned (emma) documents on the shard have been removed. + // Both orphaned (liam) and owned (emma) documents on the shard have been removed. assert.eq(null, st.shard0.getCollection(collNS).findOne({_id: -2})); - assert.eq(null, st.shard0.getCollection(collNS).findOne({_id: 5})); + assert.eq(null, st.shard0.getCollection(collNS).findOne({_id: 6})); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -315,92 +351,6 @@ jsTest.log('The collection drop generates a drop event'); assert.eq(changeStream.next().operationType, 'drop'); } -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Batched deletes from router and to shard -//////////////////////////////////////////////////////////////////////////////////////////////////// - -// Set the database to use batched deletes. -const db2 = st.rs0.getPrimary().getDB(dbName); -assert.commandWorked(db2.adminCommand({setParameter: 1, batchedDeletesTargetStagedDocBytes: 0})); -assert.commandWorked(db2.adminCommand({setParameter: 1, batchedDeletesTargetBatchTimeMS: 0})); -assert.commandWorked(db2.adminCommand({setParameter: 1, batchedDeletesTargetBatchDocs: 2})); - -// Create a non-sharded collection. -const coll2 = db2.getCollection(collName); - -// Setup a change stream on the collection to receive real-time events on any data changes. -const changeStream2 = coll2.watch([]); - -jsTest.log('A batched delete from router generates only one delete event'); -{ - // Insert two documents in the collection (see 'batchedDeletesTargetBatchDocs') and skip the - // generated events. - assert.commandWorked(coll2.insert({_id: 0, name: 'volkswagen'})); - assert.commandWorked(coll2.insert({_id: 1, name: 'renault'})); - assert.soon(() => changeStream2.hasNext(), 'A first insert event is expected'); - assert.eq(changeStream2.next().operationType, 'insert'); - assert.soon(() => changeStream2.hasNext(), 'A second insert event is expected'); - assert.eq(changeStream2.next().operationType, 'insert'); - assert(!changeStream2.hasNext()); - - // Delete all documents in batch from the collection. - assert.commandWorked(coll2.deleteMany({_id: {$gte: 0}})); - - // Actually only one delete operation is performed. Consequently, only one delete event is - // notified. - // TODO (SERVER-65859): The second delete event will be filtered out when the ticket is - // completed. - assert.soon(() => changeStream2.hasNext(), 'A first delete event is expected'); - assert.eq(changeStream2.next().operationType, 'delete'); - assert.soon(() => changeStream2.hasNext(), 'A second delete event is expected for now'); - assert.eq(changeStream2.next().operationType, 'delete'); - assert(!changeStream2.hasNext()); - - // All documents have been removed from the collection. - assert.eq(0, coll2.find().itcount()); -} - -jsTest.log('A batched delete to shard generates only one delete event'); -{ - // Insert two documents in the collection (see 'batchedDeletesTargetBatchDocs') and skip the - // generated events. - assert.commandWorked(coll2.insert({_id: 0, name: 'volkswagen'})); - assert.commandWorked(coll2.insert({_id: 1, name: 'renault'})); - assert.soon(() => changeStream2.hasNext(), 'A first insert event is expected'); - assert.eq(changeStream2.next().operationType, 'insert'); - assert.soon(() => changeStream2.hasNext(), 'A second insert event is expected'); - assert.eq(changeStream2.next().operationType, 'insert'); - assert(!changeStream2.hasNext()); - - // Delete all documents in batch from the collection. - assert.commandWorked(st.shard0.getCollection(collNS).deleteMany({_id: {$gte: 0}})); - - // Actually only one delete operation is performed. Consequently, only one delete event is - // notified. - // TODO (SERVER-65859): The second delete event will be filtered out when the ticket is - // completed. - assert.soon(() => changeStream2.hasNext(), 'A first delete event is expected'); - assert.eq(changeStream2.next().operationType, 'delete'); - assert.soon(() => changeStream2.hasNext(), 'A second delete event is expected for now'); - assert.eq(changeStream2.next().operationType, 'delete'); - assert(!changeStream2.hasNext()); - - // All documents have been removed from the collection. - assert.eq(0, coll2.find().itcount()); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -jsTest.log('The collection drop generates a drop event'); -{ - coll2.drop(); - - // Essentially, this verifies that the operation before dropping the collection did not notify - // additional and unexpected events. - assert.soon(() => changeStream2.hasNext(), 'A drop event is expected'); - assert.eq(changeStream2.next().operationType, 'drop'); -} - suspendRangeDeletionShard0.off(); st.stop(); -- cgit v1.2.1