From 45a7c29301cc321d413b0b40fc14c52550cbc436 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Mon, 17 Jul 2023 14:18:19 -0400 Subject: [PATCH 01/12] wip --- src/operations/common_functions.ts | 48 ++++++++++-------------------- src/operations/indexes.ts | 48 ++++++++++-------------------- 2 files changed, 31 insertions(+), 65 deletions(-) diff --git a/src/operations/common_functions.ts b/src/operations/common_functions.ts index 4d342b76f61..b32d00b3139 100644 --- a/src/operations/common_functions.ts +++ b/src/operations/common_functions.ts @@ -4,7 +4,7 @@ import type { Db } from '../db'; import { MongoTopologyClosedError } from '../error'; import type { ReadPreference } from '../read_preference'; import type { ClientSession } from '../sessions'; -import { type Callback, getTopology } from '../utils'; +import { getTopology } from '../utils'; /** @public */ export interface IndexInformationOptions { @@ -18,37 +18,26 @@ export interface IndexInformationOptions { * @param db - The Db instance on which to retrieve the index info. * @param name - The name of the collection. */ -export function indexInformation(db: Db, name: string, callback: Callback): void; -export function indexInformation( +export async function indexInformation(db: Db, name: string): Promise; +export async function indexInformation( db: Db, name: string, - options: IndexInformationOptions, - callback?: Callback -): void; -export function indexInformation( + options?: IndexInformationOptions +): Promise; +export async function indexInformation( db: Db, name: string, - _optionsOrCallback: IndexInformationOptions | Callback, - _callback?: Callback -): void { - let options = _optionsOrCallback as IndexInformationOptions; - let callback = _callback as Callback; - if ('function' === typeof _optionsOrCallback) { - callback = _optionsOrCallback; + options?: IndexInformationOptions +): Promise { + if (options == null) { options = {}; } // If we specified full information const full = options.full == null ? false : options.full; - - let topology; - try { - topology = getTopology(db); - } catch (error) { - return callback(error); - } + const topology = getTopology(db); // Did the user destroy the topology - if (topology.isDestroyed()) return callback(new MongoTopologyClosedError()); + if (topology.isDestroyed()) throw new MongoTopologyClosedError(); // Process all the results from the index command and collection function processResults(indexes: any) { // Contains all the information @@ -67,17 +56,10 @@ export function indexInformation( } // Get the list of indexes of the specified collection - db.collection(name) - .listIndexes(options) - .toArray() - .then( - indexes => { - if (!Array.isArray(indexes)) return callback(undefined, []); - if (full) return callback(undefined, indexes); - callback(undefined, processResults(indexes)); - }, - error => callback(error) - ); + const indexes = await db.collection(name).listIndexes(options).toArray(); + if (!Array.isArray(indexes)) return []; + if (full) return indexes; + return processResults(indexes); } export function prepareDocs( diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index 481cdda7f48..d5b1244de49 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -15,7 +15,7 @@ import { type OperationParent } from './command'; import { indexInformation, type IndexInformationOptions } from './common_functions'; -import { AbstractCallbackOperation, Aspect, defineAspects } from './operation'; +import { AbstractCallbackOperation, AbstractOperation, Aspect, defineAspects } from './operation'; const VALID_INDEX_OPTIONS = new Set([ 'background', @@ -177,7 +177,7 @@ function makeIndexSpec( } /** @internal */ -export class IndexesOperation extends AbstractCallbackOperation { +export class IndexesOperation extends AbstractOperation { override options: IndexInformationOptions; collection: Collection; @@ -187,27 +187,23 @@ export class IndexesOperation extends AbstractCallbackOperation { this.collection = collection; } - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { + override execute(server: Server, session: ClientSession | undefined): Promise { const coll = this.collection; const options = this.options; - indexInformation( - coll.s.db, - coll.collectionName, - { full: true, ...options, readPreference: this.readPreference, session }, - callback - ); + return indexInformation(coll.s.db, coll.collectionName, { + full: true, + ...options, + readPreference: this.readPreference, + session + }); } } /** @internal */ export class CreateIndexesOperation< T extends string | string[] = string[] -> extends CommandCallbackOperation { +> extends CommandOperation { override options: CreateIndexesOptions; collectionName: string; indexes: ReadonlyArray & { key: Map }>; @@ -240,11 +236,7 @@ export class CreateIndexesOperation< }); } - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { + override async execute(server: Server, session: ClientSession | undefined): Promise { const options = this.options; const indexes = this.indexes; @@ -254,12 +246,9 @@ export class CreateIndexesOperation< if (options.commitQuorum != null) { if (serverWireVersion < 9) { - callback( - new MongoCompatibilityError( - 'Option `commitQuorum` for `createIndexes` not supported on servers < 4.4' - ) + throw new MongoCompatibilityError( + 'Option `commitQuorum` for `createIndexes` not supported on servers < 4.4' ); - return; } cmd.commitQuorum = options.commitQuorum; } @@ -267,15 +256,10 @@ export class CreateIndexesOperation< // collation is set on each index, it should not be defined at the root this.options.collation = undefined; - super.executeCommandCallback(server, session, cmd, err => { - if (err) { - callback(err); - return; - } + await super.executeCommand(server, session, cmd); - const indexNames = indexes.map(index => index.name || ''); - callback(undefined, indexNames as T); - }); + const indexNames = indexes.map(index => index.name || ''); + return indexNames as T; } } From 693a418f3eb7987562f33644b170feba194c59be Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Mon, 17 Jul 2023 16:16:43 -0400 Subject: [PATCH 02/12] changed index operations to promise --- src/operations/common_functions.ts | 6 +- src/operations/indexes.ts | 131 +++++++++++++---------------- 2 files changed, 62 insertions(+), 75 deletions(-) diff --git a/src/operations/common_functions.ts b/src/operations/common_functions.ts index b32d00b3139..855919f46db 100644 --- a/src/operations/common_functions.ts +++ b/src/operations/common_functions.ts @@ -18,17 +18,17 @@ export interface IndexInformationOptions { * @param db - The Db instance on which to retrieve the index info. * @param name - The name of the collection. */ -export async function indexInformation(db: Db, name: string): Promise; +export async function indexInformation(db: Db, name: string): Promise; export async function indexInformation( db: Db, name: string, options?: IndexInformationOptions -): Promise; +): Promise; export async function indexInformation( db: Db, name: string, options?: IndexInformationOptions -): Promise { +): Promise { if (options == null) { options = {}; } diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index d5b1244de49..249428f3f13 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -261,6 +261,14 @@ export class CreateIndexesOperation< const indexNames = indexes.map(index => index.name || ''); return indexNames as T; } + + protected executeCallback( + _server: Server, + _session: ClientSession | undefined, + _callback: Callback + ): void { + throw new Error('Method not implemented.'); + } } /** @internal */ @@ -273,15 +281,9 @@ export class CreateIndexOperation extends CreateIndexesOperation { ) { super(parent, collectionName, [makeIndexSpec(indexSpec, options)], options); } - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { - super.executeCallback(server, session, (err, indexNames) => { - if (err || !indexNames) return callback(err); - return callback(undefined, indexNames[0]); - }); + override async execute(server: Server, session: ClientSession | undefined): Promise { + const indexNames = await super.execute(server, session); + return indexNames[0]; } } @@ -302,30 +304,20 @@ export class EnsureIndexOperation extends CreateIndexOperation { this.collectionName = collectionName; } - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { + override async execute(server: Server, session: ClientSession | undefined): Promise { const indexName = this.indexes[0].name; const cursor = this.db.collection(this.collectionName).listIndexes({ session }); - cursor.toArray().then( - indexes => { - indexes = Array.isArray(indexes) ? indexes : [indexes]; - if (indexes.some(index => index.name === indexName)) { - callback(undefined, indexName); - return; - } - super.executeCallback(server, session, callback); - }, - error => { - if (error instanceof MongoError && error.code === MONGODB_ERROR_CODES.NamespaceNotFound) { - // ignore "NamespaceNotFound" errors - return super.executeCallback(server, session, callback); - } - return callback(error); + try { + const indexes = await cursor.toArray(); + if (indexName && indexes.some(index => index.name === indexName)) return indexName; + return await super.execute(server, session); + } catch (error) { + if (error instanceof MongoError && error.code === MONGODB_ERROR_CODES.NamespaceNotFound) { + // ignore "NamespaceNotFound" errors + return super.execute(server, session); } - ); + return error; + } } } @@ -333,7 +325,7 @@ export class EnsureIndexOperation extends CreateIndexOperation { export type DropIndexesOptions = CommandOperationOptions; /** @internal */ -export class DropIndexOperation extends CommandCallbackOperation { +export class DropIndexOperation extends CommandOperation { override options: DropIndexesOptions; collection: Collection; indexName: string; @@ -346,13 +338,17 @@ export class DropIndexOperation extends CommandCallbackOperation { this.indexName = indexName; } - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { + override async execute(server: Server, session: ClientSession | undefined): Promise { const cmd = { dropIndexes: this.collection.collectionName, index: this.indexName }; - super.executeCommandCallback(server, session, cmd, callback); + return super.executeCommand(server, session, cmd); + } + + protected executeCallback( + _server: Server, + _session: ClientSession | undefined, + _callback: Callback + ): void { + throw new Error('Method not implemented.'); } } @@ -362,12 +358,11 @@ export class DropIndexesOperation extends DropIndexOperation { super(collection, '*', options); } - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { - super.executeCallback(server, session, err => { + override execute(server: Server, session: ClientSession | undefined): Promise { + try { + super.execute(server, session); + } + super.execute(server, session, err => { if (err) return callback(err, false); callback(undefined, true); }); @@ -426,7 +421,7 @@ export class ListIndexesOperation extends CommandOperation { } /** @internal */ -export class IndexExistsOperation extends AbstractCallbackOperation { +export class IndexExistsOperation extends AbstractOperation { override options: IndexInformationOptions; collection: Collection; indexes: string | string[]; @@ -442,39 +437,33 @@ export class IndexExistsOperation extends AbstractCallbackOperation { this.indexes = indexes; } - override executeCallback( + override async execute( server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { + session: ClientSession | undefined + ): Promise { const coll = this.collection; const indexes = this.indexes; - indexInformation( + const info = await indexInformation( coll.s.db, coll.collectionName, - { ...this.options, readPreference: this.readPreference, session }, - (err, indexInformation) => { - // If we have an error return - if (err != null) return callback(err); - // Let's check for the index names - if (!Array.isArray(indexes)) return callback(undefined, indexInformation[indexes] != null); - // Check in list of indexes - for (let i = 0; i < indexes.length; i++) { - if (indexInformation[indexes[i]] == null) { - return callback(undefined, false); - } - } + { ...this.options, readPreference: this.readPreference, session }); + // Let's check for the index names + if (!Array.isArray(indexes)) return info[indexes] != null; + // Check in list of indexes + for (let i = 0; i < indexes.length; i++) { + if (info[indexes[i]] == null) { + return false; + } + } // All keys found return true - return callback(undefined, true); - } - ); + return true; } } /** @internal */ -export class IndexInformationOperation extends AbstractCallbackOperation { +export class IndexInformationOperation extends AbstractOperation { override options: IndexInformationOptions; db: Db; name: string; @@ -486,19 +475,17 @@ export class IndexInformationOperation extends AbstractCallbackOperation - ): void { + session: ClientSession | undefined + ): Promise { const db = this.db; const name = this.name; - indexInformation( + return indexInformation( db, name, - { ...this.options, readPreference: this.readPreference, session }, - callback + { ...this.options, readPreference: this.readPreference, session } ); } } From d586b090c32057c45f06cdbc4ed15e2cc3f3eba7 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Mon, 17 Jul 2023 16:32:42 -0400 Subject: [PATCH 03/12] finished converting index callbacks to async/await --- src/operations/indexes.ts | 67 ++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index 249428f3f13..b9a837818ff 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -9,13 +9,12 @@ import type { ClientSession } from '../sessions'; import { type Callback, isObject, maxWireVersion, type MongoDBNamespace } from '../utils'; import { type CollationOptions, - CommandCallbackOperation, CommandOperation, type CommandOperationOptions, type OperationParent } from './command'; import { indexInformation, type IndexInformationOptions } from './common_functions'; -import { AbstractCallbackOperation, AbstractOperation, Aspect, defineAspects } from './operation'; +import { AbstractOperation, Aspect, defineAspects } from './operation'; const VALID_INDEX_OPTIONS = new Set([ 'background', @@ -353,19 +352,34 @@ export class DropIndexOperation extends CommandOperation { } /** @internal */ -export class DropIndexesOperation extends DropIndexOperation { - constructor(collection: Collection, options: DropIndexesOptions) { - super(collection, '*', options); +export class DropIndexesOperation extends CommandOperation { + override options: DropIndexesOptions; + collection: Collection; + indexName: string; + + constructor(collection: Collection, indexName: string, options?: DropIndexesOptions) { + super(collection, options); + + this.options = options ?? {}; + this.collection = collection; + this.indexName = indexName; } - override execute(server: Server, session: ClientSession | undefined): Promise { + override async execute(server: Server, session: ClientSession | undefined): Promise { try { - super.execute(server, session); + await super.execute(server, session); + return true; + } catch (error) { + return false; } - super.execute(server, session, err => { - if (err) return callback(err, false); - callback(undefined, true); - }); + } + + protected executeCallback( + _server: Server, + _session: ClientSession | undefined, + _callback: Callback + ): void { + throw new Error('Method not implemented.'); } } @@ -437,17 +451,15 @@ export class IndexExistsOperation extends AbstractOperation { this.indexes = indexes; } - override async execute( - server: Server, - session: ClientSession | undefined - ): Promise { + override async execute(server: Server, session: ClientSession | undefined): Promise { const coll = this.collection; const indexes = this.indexes; - const info = await indexInformation( - coll.s.db, - coll.collectionName, - { ...this.options, readPreference: this.readPreference, session }); + const info = await indexInformation(coll.s.db, coll.collectionName, { + ...this.options, + readPreference: this.readPreference, + session + }); // Let's check for the index names if (!Array.isArray(indexes)) return info[indexes] != null; // Check in list of indexes @@ -457,7 +469,7 @@ export class IndexExistsOperation extends AbstractOperation { } } - // All keys found return true + // All keys found return true return true; } } @@ -475,18 +487,15 @@ export class IndexInformationOperation extends AbstractOperation { this.name = name; } - override execute( - server: Server, - session: ClientSession | undefined - ): Promise { + override execute(server: Server, session: ClientSession | undefined): Promise { const db = this.db; const name = this.name; - return indexInformation( - db, - name, - { ...this.options, readPreference: this.readPreference, session } - ); + return indexInformation(db, name, { + ...this.options, + readPreference: this.readPreference, + session + }); } } From 2d6d8b5b27edfc277cd61e3166c5e531ac237791 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Tue, 18 Jul 2023 14:23:17 -0400 Subject: [PATCH 04/12] removed DropIndexesOperation collection.dropIndexes invoked dropIndex with a "*" --- src/collection.ts | 16 ++++++++++------ src/operations/indexes.ts | 35 +---------------------------------- 2 files changed, 11 insertions(+), 40 deletions(-) diff --git a/src/collection.ts b/src/collection.ts index 941618f4e73..3b47c78114d 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -53,7 +53,6 @@ import { CreateIndexesOperation, type CreateIndexesOptions, CreateIndexOperation, - DropIndexesOperation, type DropIndexesOptions, DropIndexOperation, type IndexDescription, @@ -647,11 +646,16 @@ export class Collection { * * @param options - Optional settings for the command */ - async dropIndexes(options?: DropIndexesOptions): Promise { - return executeOperation( - this.client, - new DropIndexesOperation(this as TODO_NODE_3286, resolveOptions(this, options)) - ); + async dropIndexes(options?: DropIndexesOptions): Promise { + try { + await executeOperation( + this.client, + new DropIndexOperation(this as TODO_NODE_3286, '*', resolveOptions(this, options)) + ); + return true; + } catch { + return false; + } } /** diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index b9a837818ff..e642e3eab0d 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -2,7 +2,7 @@ import type { Document } from '../bson'; import type { Collection } from '../collection'; import type { Db } from '../db'; import { MongoCompatibilityError, MONGODB_ERROR_CODES, MongoError } from '../error'; -import type { OneOrMore } from '../mongo_types'; +import { type OneOrMore } from '../mongo_types'; import { ReadPreference } from '../read_preference'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; @@ -351,38 +351,6 @@ export class DropIndexOperation extends CommandOperation { } } -/** @internal */ -export class DropIndexesOperation extends CommandOperation { - override options: DropIndexesOptions; - collection: Collection; - indexName: string; - - constructor(collection: Collection, indexName: string, options?: DropIndexesOptions) { - super(collection, options); - - this.options = options ?? {}; - this.collection = collection; - this.indexName = indexName; - } - - override async execute(server: Server, session: ClientSession | undefined): Promise { - try { - await super.execute(server, session); - return true; - } catch (error) { - return false; - } - } - - protected executeCallback( - _server: Server, - _session: ClientSession | undefined, - _callback: Callback - ): void { - throw new Error('Method not implemented.'); - } -} - /** @public */ export interface ListIndexesOptions extends Omit { /** The batchSize for the returned command cursor or if pre 2.8 the systems batch collection */ @@ -508,4 +476,3 @@ defineAspects(CreateIndexesOperation, [Aspect.WRITE_OPERATION]); defineAspects(CreateIndexOperation, [Aspect.WRITE_OPERATION]); defineAspects(EnsureIndexOperation, [Aspect.WRITE_OPERATION]); defineAspects(DropIndexOperation, [Aspect.WRITE_OPERATION]); -defineAspects(DropIndexesOperation, [Aspect.WRITE_OPERATION]); From f19a9ada5c0177164241c3e8ed388e47161cce15 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Wed, 19 Jul 2023 14:19:42 -0400 Subject: [PATCH 05/12] added testing for dropIndexes --- test/integration/index_management.test.js | 98 ++++++++++++++++------- 1 file changed, 68 insertions(+), 30 deletions(-) diff --git a/test/integration/index_management.test.js b/test/integration/index_management.test.js index e2465cae8c1..2be2e65b01f 100644 --- a/test/integration/index_management.test.js +++ b/test/integration/index_management.test.js @@ -1,13 +1,26 @@ 'use strict'; const { expect } = require('chai'); + const { assert: test, setupDatabase } = require('./shared'); const shared = require('../tools/contexts'); describe('Indexes', function () { + let client; + let db; + before(function () { return setupDatabase(this.configuration); }); + beforeEach(function () { + client = this.configuration.newClient(); + db = client.db(); + }); + + this.afterEach(async function () { + await client.close(); + }); + it('Should correctly execute createIndex', { metadata: { requires: { @@ -258,39 +271,64 @@ describe('Indexes', function () { } }); - it('shouldCorrectlyDropIndexes', { - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } - }, + context('resolved dropIndexes', function () { + let collection; - test: function (done) { - var configuration = this.configuration; - var client = configuration.newClient(configuration.writeConcernMax(), { maxPoolSize: 1 }); - var db = client.db(configuration.db); - db.createCollection('test_drop_indexes', function (err, collection) { - collection.insert({ a: 1 }, configuration.writeConcernMax(), function (err) { - expect(err).to.not.exist; - // Create an index on the collection - db.createIndex( - collection.collectionName, - 'a', - configuration.writeConcernMax(), - function (err, indexName) { - test.equal('a_1', indexName); - // Drop all the indexes - collection.dropIndexes(function (err, result) { - test.equal(true, result); + beforeEach(async function () { + collection = await db.createCollection('test_drop_indexes'); + await collection.insert({ a: 1 }); + // Create an index on the collection + await db.createIndex(collection.collectionName, 'a'); + /**@type {import('../tools/utils').FailPoint} */ + }); - collection.indexInformation(function (err, result) { - test.ok(result['a_1'] == null); - client.close(done); - }); - }); - } - ); + afterEach(async function () { + await db.dropCollection('test_drop_indexes'); + }); + + it('should return true and be undefined in the collection', async function () { + // Drop all the indexes + const result = await collection.dropIndexes(); + expect(result).to.equal(true); + + const res = await collection.indexInformation(); + expect(res['a_1']).to.equal(undefined); + }); + }); + + context('rejected dropIndexes', function () { + let collection; + + beforeEach(async function () { + collection = await db.createCollection('test_drop_indexes'); + await collection.insert({ a: 1 }); + // Create an index on the collection + await db.createIndex(collection.collectionName, 'a'); + /**@type {import('../tools/utils').FailPoint} */ + const result = await client + .db() + .admin() + .command({ + configureFailPoint: 'failCommand', + mode: { + times: 4 + }, + data: { + failCommands: ['dropIndexes'], + errorCode: 91 + } }); - }); - } + console.log(result); + }); + + afterEach(async function () { + await db.dropCollection('test_drop_indexes'); + }); + + it('should return false', async function () { + const result = await collection.dropIndexes(); + expect(result).to.equal(false); + }); }); it('shouldCorrectlyHandleDistinctIndexes', { From 7afcad96f27e2e31a1204caff2a9502ab1afbda4 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Wed, 19 Jul 2023 14:26:31 -0400 Subject: [PATCH 06/12] removed debugging code --- test/integration/index_management.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/integration/index_management.test.js b/test/integration/index_management.test.js index 2be2e65b01f..cc137521acc 100644 --- a/test/integration/index_management.test.js +++ b/test/integration/index_management.test.js @@ -305,7 +305,7 @@ describe('Indexes', function () { // Create an index on the collection await db.createIndex(collection.collectionName, 'a'); /**@type {import('../tools/utils').FailPoint} */ - const result = await client + await client .db() .admin() .command({ @@ -318,7 +318,6 @@ describe('Indexes', function () { errorCode: 91 } }); - console.log(result); }); afterEach(async function () { From 590477863e2b059248f5c56f8b4b61b2b25bdc71 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Wed, 19 Jul 2023 15:46:23 -0400 Subject: [PATCH 07/12] failPoint happens only 1 time --- test/integration/index_management.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/index_management.test.js b/test/integration/index_management.test.js index cc137521acc..321fa5c4fe3 100644 --- a/test/integration/index_management.test.js +++ b/test/integration/index_management.test.js @@ -311,7 +311,7 @@ describe('Indexes', function () { .command({ configureFailPoint: 'failCommand', mode: { - times: 4 + times: 1 }, data: { failCommands: ['dropIndexes'], From fc1cf36319fa546386557b9f758894637acfcd49 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Thu, 20 Jul 2023 14:37:51 -0400 Subject: [PATCH 08/12] fixed code after primary review comments --- src/operations/common_functions.ts | 31 +++++---------------- src/operations/indexes.ts | 33 +++++++++-------------- test/integration/index_management.test.js | 7 +++-- 3 files changed, 22 insertions(+), 49 deletions(-) diff --git a/src/operations/common_functions.ts b/src/operations/common_functions.ts index 855919f46db..6f79db71d31 100644 --- a/src/operations/common_functions.ts +++ b/src/operations/common_functions.ts @@ -1,10 +1,8 @@ import type { Document } from '../bson'; import type { Collection } from '../collection'; import type { Db } from '../db'; -import { MongoTopologyClosedError } from '../error'; import type { ReadPreference } from '../read_preference'; import type { ClientSession } from '../sessions'; -import { getTopology } from '../utils'; /** @public */ export interface IndexInformationOptions { @@ -34,32 +32,15 @@ export async function indexInformation( } // If we specified full information const full = options.full == null ? false : options.full; - const topology = getTopology(db); - - // Did the user destroy the topology - if (topology.isDestroyed()) throw new MongoTopologyClosedError(); - // Process all the results from the index command and collection - function processResults(indexes: any) { - // Contains all the information - const info: any = {}; - // Process all the indexes - for (let i = 0; i < indexes.length; i++) { - const index = indexes[i]; - // Let's unpack the object - info[index.name] = []; - for (const name in index.key) { - info[index.name].push([name, index.key[name]]); - } - } - - return info; - } - // Get the list of indexes of the specified collection const indexes = await db.collection(name).listIndexes(options).toArray(); - if (!Array.isArray(indexes)) return []; if (full) return indexes; - return processResults(indexes); + + const info: Record> = {}; + for (const index of indexes) { + info[index.name] = Object.entries(index.key); + } + return info; } export function prepareDocs( diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index e642e3eab0d..20ff4ee6159 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -186,7 +186,7 @@ export class IndexesOperation extends AbstractOperation { this.collection = collection; } - override execute(server: Server, session: ClientSession | undefined): Promise { + override execute(_server: Server, session: ClientSession | undefined): Promise { const coll = this.collection; const options = this.options; @@ -305,18 +305,17 @@ export class EnsureIndexOperation extends CreateIndexOperation { override async execute(server: Server, session: ClientSession | undefined): Promise { const indexName = this.indexes[0].name; - const cursor = this.db.collection(this.collectionName).listIndexes({ session }); - try { - const indexes = await cursor.toArray(); - if (indexName && indexes.some(index => index.name === indexName)) return indexName; - return await super.execute(server, session); - } catch (error) { - if (error instanceof MongoError && error.code === MONGODB_ERROR_CODES.NamespaceNotFound) { - // ignore "NamespaceNotFound" errors - return super.execute(server, session); - } - return error; - } + const indexes = await this.db + .collection(this.collectionName) + .listIndexes({ session }) + .toArray() + .catch(error => { + if (error instanceof MongoError && error.code === MONGODB_ERROR_CODES.NamespaceNotFound) + return []; + throw error; + }); + if (indexName && indexes.some(index => index.name === indexName)) return indexName; + return super.execute(server, session); } } @@ -430,15 +429,9 @@ export class IndexExistsOperation extends AbstractOperation { }); // Let's check for the index names if (!Array.isArray(indexes)) return info[indexes] != null; - // Check in list of indexes - for (let i = 0; i < indexes.length; i++) { - if (info[indexes[i]] == null) { - return false; - } - } // All keys found return true - return true; + return Array.prototype.every(indexName => info[indexName] != null); } } diff --git a/test/integration/index_management.test.js b/test/integration/index_management.test.js index 321fa5c4fe3..fe0d70dbd11 100644 --- a/test/integration/index_management.test.js +++ b/test/integration/index_management.test.js @@ -271,7 +271,7 @@ describe('Indexes', function () { } }); - context('resolved dropIndexes', function () { + context('when dropIndexes succeeds', function () { let collection; beforeEach(async function () { @@ -279,14 +279,13 @@ describe('Indexes', function () { await collection.insert({ a: 1 }); // Create an index on the collection await db.createIndex(collection.collectionName, 'a'); - /**@type {import('../tools/utils').FailPoint} */ }); afterEach(async function () { await db.dropCollection('test_drop_indexes'); }); - it('should return true and be undefined in the collection', async function () { + it('should return true and should no longer exist in the collection', async function () { // Drop all the indexes const result = await collection.dropIndexes(); expect(result).to.equal(true); @@ -296,7 +295,7 @@ describe('Indexes', function () { }); }); - context('rejected dropIndexes', function () { + context('when dropIndexes fails', function () { let collection; beforeEach(async function () { From 0f6f2cec7fcd15ad77c3281e6976a7dbe98a769a Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Mon, 24 Jul 2023 15:16:11 -0400 Subject: [PATCH 09/12] added tests for indexExists added metadata for failpoint in index_management --- src/operations/indexes.ts | 2 +- test/integration/index_management.test.js | 50 +++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index 20ff4ee6159..138d0bc7683 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -431,7 +431,7 @@ export class IndexExistsOperation extends AbstractOperation { if (!Array.isArray(indexes)) return info[indexes] != null; // All keys found return true - return Array.prototype.every(indexName => info[indexName] != null); + return indexes.every(indexName => info[indexName] != null); } } diff --git a/test/integration/index_management.test.js b/test/integration/index_management.test.js index fe0d70dbd11..8841e993b53 100644 --- a/test/integration/index_management.test.js +++ b/test/integration/index_management.test.js @@ -1,4 +1,4 @@ -'use strict'; +('use strict'); const { expect } = require('chai'); const { assert: test, setupDatabase } = require('./shared'); @@ -323,8 +323,52 @@ describe('Indexes', function () { await db.dropCollection('test_drop_indexes'); }); - it('should return false', async function () { - const result = await collection.dropIndexes(); + it('should return false', { + metadata: { + requires: { + mongodb: '>4.0' + } + }, + + test: async function () { + const result = await collection.dropIndexes(); + expect(result).to.equal(false); + } + }); + }); + + context('indexExists', function () { + let collection; + + beforeEach(async function () { + collection = await db.createCollection('test_index_exists'); + await collection.insert({ a: 1 }); + + await db.createIndex(collection.collectionName, 'a'); + await db.createIndex(collection.collectionName, ['c', 'd', 'e']); + }); + + afterEach(async function () { + await db.dropCollection('test_index_exists'); + }); + + it('should return true when index of type string exists', async function () { + const result = await collection.indexExists('a_1'); + expect(result).to.equal(true); + }); + + it('should return false when index of type string does not exist', async function () { + const result = await collection.indexExists('b_2'); + expect(result).to.equal(false); + }); + + it('should return true when an array of indexes exists', async function () { + const result = await collection.indexExists('c_1_d_1_e_1'); + expect(result).to.equal(true); + }); + + it('should return false when an array of indexes does not exist', async function () { + const result = await collection.indexExists('d_1_e_1_f_1'); expect(result).to.equal(false); }); }); From a57537cb4bc6492dac2c45020d72947b3e085f5f Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Tue, 25 Jul 2023 18:03:06 -0400 Subject: [PATCH 10/12] fixed index tests --- test/integration/index_management.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/integration/index_management.test.js b/test/integration/index_management.test.js index 8841e993b53..06e7bfd432b 100644 --- a/test/integration/index_management.test.js +++ b/test/integration/index_management.test.js @@ -1,4 +1,4 @@ -('use strict'); +'use strict'; const { expect } = require('chai'); const { assert: test, setupDatabase } = require('./shared'); @@ -17,7 +17,7 @@ describe('Indexes', function () { db = client.db(); }); - this.afterEach(async function () { + afterEach(async function () { await client.close(); }); @@ -326,7 +326,7 @@ describe('Indexes', function () { it('should return false', { metadata: { requires: { - mongodb: '>4.0' + mongodb: '>=4.0' } }, @@ -363,12 +363,12 @@ describe('Indexes', function () { }); it('should return true when an array of indexes exists', async function () { - const result = await collection.indexExists('c_1_d_1_e_1'); + const result = await collection.indexExists(['c_1_d_1_e_1', 'a_1']); expect(result).to.equal(true); }); it('should return false when an array of indexes does not exist', async function () { - const result = await collection.indexExists('d_1_e_1_f_1'); + const result = await collection.indexExists(['d_1_e_1', 'c_1']); expect(result).to.equal(false); }); }); From 705a7c4354ca5b77560577c42cc2a90bf431f189 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Wed, 26 Jul 2023 10:00:01 -0400 Subject: [PATCH 11/12] dummy commit --- src/operations/indexes.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index 138d0bc7683..69f998fd130 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -429,7 +429,6 @@ export class IndexExistsOperation extends AbstractOperation { }); // Let's check for the index names if (!Array.isArray(indexes)) return info[indexes] != null; - // All keys found return true return indexes.every(indexName => info[indexName] != null); } From 7b651803b562477ccc17ede55139c7adf1751cb9 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Wed, 26 Jul 2023 13:09:47 -0400 Subject: [PATCH 12/12] fixed mongo version --- test/integration/index_management.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/index_management.test.js b/test/integration/index_management.test.js index 06e7bfd432b..188452f11e0 100644 --- a/test/integration/index_management.test.js +++ b/test/integration/index_management.test.js @@ -326,7 +326,7 @@ describe('Indexes', function () { it('should return false', { metadata: { requires: { - mongodb: '>=4.0' + mongodb: '>4.0' } },