From 67d7bab434164fa9a81e22edde9339f89be91f65 Mon Sep 17 00:00:00 2001 From: Aditi Khare <106987683+aditi-khare-mongoDB@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:35:29 -0400 Subject: [PATCH] fix(NODE-5745): ignore Read/Write Concern in Atlas Search Index Helpers (#4042) --- src/collection.ts | 1 + src/cursor/list_search_indexes_cursor.ts | 2 +- .../search-index-management.test.ts | 68 +++++ .../searchIndexIgnoresReadWriteConcern.json | 252 ++++++++++++++++++ .../searchIndexIgnoresReadWriteConcern.yml | 146 ++++++++++ 5 files changed, 468 insertions(+), 1 deletion(-) create mode 100644 test/integration/index-management/search-index-management.test.ts create mode 100644 test/spec/index-management/searchIndexIgnoresReadWriteConcern.json create mode 100644 test/spec/index-management/searchIndexIgnoresReadWriteConcern.yml diff --git a/src/collection.ts b/src/collection.ts index 3665498995d..04bc6c0793f 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -1074,6 +1074,7 @@ export class Collection { ): ListSearchIndexesCursor { options = typeof indexNameOrOptions === 'object' ? indexNameOrOptions : options == null ? {} : options; + const indexName = indexNameOrOptions == null ? null diff --git a/src/cursor/list_search_indexes_cursor.ts b/src/cursor/list_search_indexes_cursor.ts index bf5a0b56120..cfe1358f725 100644 --- a/src/cursor/list_search_indexes_cursor.ts +++ b/src/cursor/list_search_indexes_cursor.ts @@ -3,7 +3,7 @@ import type { AggregateOptions } from '../operations/aggregate'; import { AggregationCursor } from './aggregation_cursor'; /** @public */ -export type ListSearchIndexesOptions = AggregateOptions; +export type ListSearchIndexesOptions = Omit; /** @public */ export class ListSearchIndexesCursor extends AggregationCursor<{ name: string }> { diff --git a/test/integration/index-management/search-index-management.test.ts b/test/integration/index-management/search-index-management.test.ts new file mode 100644 index 00000000000..1c191f79517 --- /dev/null +++ b/test/integration/index-management/search-index-management.test.ts @@ -0,0 +1,68 @@ +import { expect } from 'chai'; + +import { type Collection, type CommandStartedEvent, type MongoClient } from '../../mongodb'; + +describe('Search Index Management Integration Tests', function () { + describe('read concern and write concern ', function () { + let client: MongoClient; + let collection: Collection; + let commandStartedEvents: CommandStartedEvent[]; + + beforeEach(async function () { + client = this.configuration.newClient({}, { monitorCommands: true }); + await client.connect(); + collection = client.db('client').collection('searchIndexManagement'); + commandStartedEvents = []; + client.on('commandStarted', e => commandStartedEvents.push(e)); + }); + + afterEach(async function () { + await client.close(); + }); + + context('when listSearchIndexes operation is run with causalConsistency', function () { + it('should not include write concern or read concern in command', { + metadata: { + requires: { + topology: '!single', + mongodb: '>=7.0', + serverless: 'forbid' + } + }, + test: async function () { + await client.withSession({ causalConsistency: true }, async session => { + const res = collection.listSearchIndexes({ session }); + await res.toArray().catch(e => expect(e.errmsg).to.match(/^.*Atlas.*$/)); + expect(commandStartedEvents[0]).to.exist; + expect(commandStartedEvents[0]?.command?.readConcern).to.not.exist; + expect(commandStartedEvents[0]?.command?.writeConcern).to.not.exist; + }); + } + }); + }); + + context('when listSearchIndexes operation is run with snapshot on', function () { + // TODO(NODE-6047): Ignore read/write concern in applySession for Atlas Search Index Helpers + it('should include write concern or read concern in command - TODO(NODE-6047)', { + metadata: { + requires: { + topology: ['replicaset', 'sharded'], + mongodb: '>=7.0', + serverless: 'forbid' + } + }, + test: async function () { + await client.withSession({ snapshot: true }, async session => { + const res = collection.listSearchIndexes({ session }); + const error = await res.toArray().catch(e => e); + expect(error.errmsg).to.match(/^.*snapshot.*$/); + expect(commandStartedEvents[0]).to.exist; + // flip assertion after NODE-6047 implementation + expect(commandStartedEvents[0]?.command?.readConcern).to.exist; + expect(commandStartedEvents[0]?.command?.writeConcern).to.not.exist; + }); + } + }); + }); + }); +}); diff --git a/test/spec/index-management/searchIndexIgnoresReadWriteConcern.json b/test/spec/index-management/searchIndexIgnoresReadWriteConcern.json new file mode 100644 index 00000000000..edf71b7b7e4 --- /dev/null +++ b/test/spec/index-management/searchIndexIgnoresReadWriteConcern.json @@ -0,0 +1,252 @@ +{ + "description": "search index operations ignore read and write concern", + "schemaVersion": "1.4", + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "uriOptions": { + "readConcernLevel": "local", + "w": 1 + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "database0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "collection0" + } + } + ], + "runOnRequirements": [ + { + "minServerVersion": "7.0.0", + "topologies": [ + "replicaset", + "load-balanced", + "sharded" + ], + "serverless": "forbid" + } + ], + "tests": [ + { + "description": "createSearchIndex ignores read and write concern", + "operations": [ + { + "name": "createSearchIndex", + "object": "collection0", + "arguments": { + "model": { + "definition": { + "mappings": { + "dynamic": true + } + } + } + }, + "expectError": { + "isError": true, + "errorContains": "Atlas" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "createSearchIndexes": "collection0", + "indexes": [ + { + "definition": { + "mappings": { + "dynamic": true + } + } + } + ], + "$db": "database0", + "writeConcern": { + "$$exists": false + }, + "readConcern": { + "$$exists": false + } + } + } + } + ] + } + ] + }, + { + "description": "createSearchIndexes ignores read and write concern", + "operations": [ + { + "name": "createSearchIndexes", + "object": "collection0", + "arguments": { + "models": [] + }, + "expectError": { + "isError": true, + "errorContains": "Atlas" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "createSearchIndexes": "collection0", + "indexes": [], + "$db": "database0", + "writeConcern": { + "$$exists": false + }, + "readConcern": { + "$$exists": false + } + } + } + } + ] + } + ] + }, + { + "description": "dropSearchIndex ignores read and write concern", + "operations": [ + { + "name": "dropSearchIndex", + "object": "collection0", + "arguments": { + "name": "test index" + }, + "expectError": { + "isError": true, + "errorContains": "Atlas" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "dropSearchIndex": "collection0", + "name": "test index", + "$db": "database0", + "writeConcern": { + "$$exists": false + }, + "readConcern": { + "$$exists": false + } + } + } + } + ] + } + ] + }, + { + "description": "listSearchIndexes ignores read and write concern", + "operations": [ + { + "name": "listSearchIndexes", + "object": "collection0", + "expectError": { + "isError": true, + "errorContains": "Atlas" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "collection0", + "pipeline": [ + { + "$listSearchIndexes": {} + } + ], + "writeConcern": { + "$$exists": false + }, + "readConcern": { + "$$exists": false + } + } + } + } + ] + } + ] + }, + { + "description": "updateSearchIndex ignores the read and write concern", + "operations": [ + { + "name": "updateSearchIndex", + "object": "collection0", + "arguments": { + "name": "test index", + "definition": {} + }, + "expectError": { + "isError": true, + "errorContains": "Atlas" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "updateSearchIndex": "collection0", + "name": "test index", + "definition": {}, + "$db": "database0", + "writeConcern": { + "$$exists": false + }, + "readConcern": { + "$$exists": false + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/index-management/searchIndexIgnoresReadWriteConcern.yml b/test/spec/index-management/searchIndexIgnoresReadWriteConcern.yml new file mode 100644 index 00000000000..c2026b18dc6 --- /dev/null +++ b/test/spec/index-management/searchIndexIgnoresReadWriteConcern.yml @@ -0,0 +1,146 @@ +description: "search index operations ignore read and write concern" +schemaVersion: "1.4" +createEntities: + - client: + id: &client0 client0 + useMultipleMongoses: false + # Set a non-default read and write concern. + uriOptions: + readConcernLevel: local + w: 1 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: *database0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: *collection0 + +runOnRequirements: + - minServerVersion: "7.0.0" + topologies: [ replicaset, load-balanced, sharded ] + serverless: forbid + +tests: + - description: "createSearchIndex ignores read and write concern" + operations: + - name: createSearchIndex + object: *collection0 + arguments: + model: { definition: &definition { mappings: { dynamic: true } } } + expectError: + # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting + # that the driver constructs and sends the correct command. + # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages. + isError: true + errorContains: Atlas + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + createSearchIndexes: *collection0 + indexes: [ { definition: *definition } ] + $db: *database0 + # Expect no writeConcern or readConcern to be sent. + writeConcern: { $$exists: false } + readConcern: { $$exists: false } + + - description: "createSearchIndexes ignores read and write concern" + operations: + - name: createSearchIndexes + object: *collection0 + arguments: + models: [] + expectError: + # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting + # that the driver constructs and sends the correct command. + # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages. + isError: true + errorContains: Atlas + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + createSearchIndexes: *collection0 + indexes: [] + $db: *database0 + # Expect no writeConcern or readConcern to be sent. + writeConcern: { $$exists: false } + readConcern: { $$exists: false } + + - description: "dropSearchIndex ignores read and write concern" + operations: + - name: dropSearchIndex + object: *collection0 + arguments: + name: &indexName 'test index' + expectError: + # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting + # that the driver constructs and sends the correct command. + # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages. + isError: true + errorContains: Atlas + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + dropSearchIndex: *collection0 + name: *indexName + $db: *database0 + # Expect no writeConcern or readConcern to be sent. + writeConcern: { $$exists: false } + readConcern: { $$exists: false } + + - description: "listSearchIndexes ignores read and write concern" + operations: + - name: listSearchIndexes + object: *collection0 + expectError: + # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting + # that the driver constructs and sends the correct command. + # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages. + isError: true + errorContains: Atlas + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0 + pipeline: + - $listSearchIndexes: {} + # Expect no writeConcern or readConcern to be sent. + writeConcern: { $$exists: false } + readConcern: { $$exists: false } + + - description: "updateSearchIndex ignores the read and write concern" + operations: + - name: updateSearchIndex + object: *collection0 + arguments: + name: &indexName 'test index' + definition: &definition {} + expectError: + # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting + # that the driver constructs and sends the correct command. + # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages. + isError: true + errorContains: Atlas + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + updateSearchIndex: *collection0 + name: *indexName + definition: *definition + $db: *database0 + # Expect no writeConcern or readConcern to be sent. + writeConcern: { $$exists: false } + readConcern: { $$exists: false } \ No newline at end of file