From 5797beba7871c55c4249383dcd69f1510912b562 Mon Sep 17 00:00:00 2001
From: Hana Pearlman <hana.pearlman@mongodb.com>
Date: Wed, 21 Oct 2020 17:06:56 -0400
Subject: [PATCH] push error check to execute operation

---
 src/admin.ts                        |  6 ------
 src/collection.ts                   | 33 -----------------------------
 src/db.ts                           | 16 --------------
 src/operations/execute_operation.ts | 20 +++++++++++------
 4 files changed, 14 insertions(+), 61 deletions(-)

diff --git a/src/admin.ts b/src/admin.ts
index b06ceee7ef3..59be0ca9ecb 100644
--- a/src/admin.ts
+++ b/src/admin.ts
@@ -15,7 +15,6 @@ import type { Callback } from './utils';
 import type { Document } from './bson';
 import type { CommandOperationOptions } from './operations/command';
 import type { Db } from './db';
-import { MongoClientClosedError } from './error';
 
 /** @internal */
 export interface AdminPrivate {
@@ -80,7 +79,6 @@ export class Admin {
     if (typeof options === 'function') (callback = options), (options = {});
     options = Object.assign({ dbName: 'admin' }, options);
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new RunCommandOperation(this.s.db, command, options),
@@ -205,7 +203,6 @@ export class Admin {
 
     options = Object.assign({ dbName: 'admin' }, options);
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new AddUserOperation(this.s.db, username, password, options),
@@ -232,7 +229,6 @@ export class Admin {
     if (typeof options === 'function') (callback = options), (options = {});
     options = Object.assign({ dbName: 'admin' }, options);
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new RemoveUserOperation(this.s.db, username, options),
@@ -263,7 +259,6 @@ export class Admin {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new ValidateCollectionOperation(this, collectionName, options),
@@ -288,7 +283,6 @@ export class Admin {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new ListDatabasesOperation(this.s.db, options),
diff --git a/src/collection.ts b/src/collection.ts
index 40ecae090e1..f9d880c1323 100644
--- a/src/collection.ts
+++ b/src/collection.ts
@@ -313,7 +313,6 @@ export class Collection implements OperationParent {
       options.ignoreUndefined = this.s.options.ignoreUndefined;
     }
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new InsertOneOperation(this, doc, options),
@@ -346,7 +345,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options ? Object.assign({}, options) : { ordered: true };
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new InsertManyOperation(this, docs, options),
@@ -407,7 +405,6 @@ export class Collection implements OperationParent {
       throw new MongoError('operations must be an array of documents');
     }
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new BulkWriteOperation(this, operations, options),
@@ -447,7 +444,6 @@ export class Collection implements OperationParent {
       options.ignoreUndefined = this.s.options.ignoreUndefined;
     }
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new UpdateOneOperation(this, filter, update, options),
@@ -491,7 +487,6 @@ export class Collection implements OperationParent {
       options.ignoreUndefined = this.s.options.ignoreUndefined;
     }
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new ReplaceOneOperation(this, filter, replacement, options),
@@ -531,7 +526,6 @@ export class Collection implements OperationParent {
       options.ignoreUndefined = this.s.options.ignoreUndefined;
     }
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new UpdateManyOperation(this, filter, update, options),
@@ -564,7 +558,6 @@ export class Collection implements OperationParent {
       options.ignoreUndefined = this.s.options.ignoreUndefined;
     }
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new DeleteOneOperation(this, filter, options),
@@ -609,7 +602,6 @@ export class Collection implements OperationParent {
       options.ignoreUndefined = this.s.options.ignoreUndefined;
     }
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new DeleteManyOperation(this, filter, options),
@@ -636,7 +628,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = Object.assign({}, options, { readPreference: ReadPreference.PRIMARY });
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new RenameOperation(this, newName, options),
@@ -661,7 +652,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new DropCollectionOperation(this.s.db, this.collectionName, options),
@@ -697,7 +687,6 @@ export class Collection implements OperationParent {
     query = query || {};
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new FindOneOperation(this, query, options),
@@ -746,7 +735,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(this.s.db.topology, new OptionsOperation(this, options), callback);
   }
 
@@ -767,7 +755,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(this.s.db.topology, new IsCappedOperation(this, options), callback);
   }
 
@@ -816,7 +803,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new CreateIndexOperation(this, this.collectionName, indexSpec, options),
@@ -873,7 +859,6 @@ export class Collection implements OperationParent {
     options = options ? Object.assign({}, options) : {};
     if (typeof options.maxTimeMS !== 'number') delete options.maxTimeMS;
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new CreateIndexesOperation(this, this.collectionName, indexSpecs, options),
@@ -903,7 +888,6 @@ export class Collection implements OperationParent {
     // Run only against primary
     options.readPreference = ReadPreference.primary;
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new DropIndexOperation(this, indexName, options),
@@ -928,7 +912,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options ? Object.assign({}, options) : {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(this.s.db.topology, new DropIndexesOperation(this, options), callback);
   }
 
@@ -971,7 +954,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new IndexExistsOperation(this, indexes, options),
@@ -996,7 +978,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new IndexInformationOperation(this.s.db, this.collectionName, options),
@@ -1021,7 +1002,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new EstimatedDocumentCountOperation(this, options),
@@ -1079,7 +1059,6 @@ export class Collection implements OperationParent {
     query = query || {};
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new CountDocumentsOperation(this, query as Document, options as CountDocumentsOptions),
@@ -1123,7 +1102,6 @@ export class Collection implements OperationParent {
     query = query || {};
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new DistinctOperation(this, key, query as Document, options as DistinctOptions),
@@ -1148,7 +1126,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(this.s.db.topology, new IndexesOperation(this, options), callback);
   }
 
@@ -1169,7 +1146,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(this.s.db.topology, new CollStatsOperation(this, options), callback);
   }
 
@@ -1196,7 +1172,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new FindOneAndDeleteOperation(this, filter, options),
@@ -1234,7 +1209,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new FindOneAndReplaceOperation(this, filter, replacement, options),
@@ -1272,7 +1246,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new FindOneAndUpdateOperation(this, filter, update, options),
@@ -1383,7 +1356,6 @@ export class Collection implements OperationParent {
       options.finalize = options.finalize.toString();
     }
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new MapReduceOperation(this, map, reduce, options),
@@ -1516,7 +1488,6 @@ export class Collection implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new EnsureIndexOperation(this.s.db, this.collectionName, fieldOrSpec, options),
@@ -1557,7 +1528,6 @@ export class Collection implements OperationParent {
     query = query || {};
     options = options || {};
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new EstimatedDocumentCountOperation(this, query, options),
@@ -1607,7 +1577,6 @@ export class Collection implements OperationParent {
     // Add the remove option
     options.remove = true;
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new FindAndModifyOperation(this, query, sort as Sort, undefined, options),
@@ -1668,7 +1637,6 @@ export class Collection implements OperationParent {
     // Set up the command as default
     command = command == null ? true : command;
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     if (command == null) {
       return executeOperation(
         this.s.db.topology,
@@ -1728,7 +1696,6 @@ export class Collection implements OperationParent {
     // Force read preference primary
     options.readPreference = ReadPreference.primary;
 
-    if (!this.s.db.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.db.topology,
       new FindAndModifyOperation(this, query, sort, doc, options),
diff --git a/src/db.ts b/src/db.ts
index cdf0ce2562d..8f4a071e57d 100644
--- a/src/db.ts
+++ b/src/db.ts
@@ -252,7 +252,6 @@ export class Db implements OperationParent {
     options = options || {};
     options.readConcern = ReadConcern.fromOptions(options) ?? this.readConcern;
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new CreateCollectionOperation(this, name, options),
@@ -279,7 +278,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new RunCommandOperation(this, command, options),
@@ -419,7 +417,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(this.s.client.topology, new DbStatsOperation(this, options), callback);
   }
 
@@ -478,7 +475,6 @@ export class Db implements OperationParent {
     // Add return new collection
     options.new_collection = true;
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new RenameOperation(this.collection(fromCollection), toCollection, options),
@@ -505,7 +501,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new DropCollectionOperation(this, name, options),
@@ -530,7 +525,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new DropDatabaseOperation(this, options),
@@ -555,7 +549,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new CollectionsOperation(this, options),
@@ -586,7 +579,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new RunAdminCommandOperation(this, command, options),
@@ -624,7 +616,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options ? Object.assign({}, options) : {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new CreateIndexOperation(this, name, indexSpec, options),
@@ -673,7 +664,6 @@ export class Db implements OperationParent {
 
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new AddUserOperation(this, username, password, options),
@@ -700,7 +690,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new RemoveUserOperation(this, username, options),
@@ -734,7 +723,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new SetProfilingLevelOperation(this, level, options),
@@ -759,7 +747,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new ProfilingLevelOperation(this, options),
@@ -790,7 +777,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new IndexInformationOperation(this, name, options),
@@ -864,7 +850,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new EvalOperation(this, code, parameters, options),
@@ -903,7 +888,6 @@ export class Db implements OperationParent {
     if (typeof options === 'function') (callback = options), (options = {});
     options = options || {};
 
-    if (!this.s.client.topology) throw new MongoClientClosedError();
     return executeOperation(
       this.s.client.topology,
       new EnsureIndexOperation(this, name, fieldOrSpec, options),
diff --git a/src/operations/execute_operation.ts b/src/operations/execute_operation.ts
index 18c2f70c401..0d329b65f2b 100644
--- a/src/operations/execute_operation.ts
+++ b/src/operations/execute_operation.ts
@@ -1,5 +1,5 @@
 import { ReadPreference } from '../read_preference';
-import { MongoError, isRetryableError, AnyError } from '../error';
+import { MongoError, isRetryableError, AnyError, MongoClientClosedError } from '../error';
 import { Aspect, OperationBase, OperationOptions } from './operation';
 import { maxWireVersion, maybePromise, Callback } from '../utils';
 import { ServerType } from '../sdam/common';
@@ -40,24 +40,32 @@ export function executeOperation<
   T extends OperationBase<TOptions, TResult>,
   TOptions = OptionsFromOperation<T>,
   TResult = ResultTypeFromOperation<T>
->(topology: Topology, operation: T): Promise<TResult>;
+>(topology: Topology | undefined, operation: T): Promise<TResult>;
 export function executeOperation<
   T extends OperationBase<TOptions, TResult>,
   TOptions = OptionsFromOperation<T>,
   TResult = ResultTypeFromOperation<T>
->(topology: Topology, operation: T, callback: Callback<TResult>): void;
+>(topology: Topology | undefined, operation: T, callback: Callback<TResult>): void;
 export function executeOperation<
   T extends OperationBase<TOptions, TResult>,
   TOptions = OptionsFromOperation<T>,
   TResult = ResultTypeFromOperation<T>
->(topology: Topology, operation: T, callback?: Callback<TResult>): Promise<TResult> | void;
+>(
+  topology: Topology | undefined,
+  operation: T,
+  callback?: Callback<TResult>
+): Promise<TResult> | void;
 export function executeOperation<
   T extends OperationBase<TOptions, TResult>,
   TOptions = OptionsFromOperation<T>,
   TResult = ResultTypeFromOperation<T>
->(topology: Topology, operation: T, callback?: Callback<TResult>): Promise<TResult> | void {
+>(
+  topology: Topology | undefined,
+  operation: T,
+  callback?: Callback<TResult>
+): Promise<TResult> | void {
   if (topology == null) {
-    throw new TypeError('This method requires a valid topology instance');
+    throw new MongoClientClosedError();
   }
 
   if (!(operation instanceof OperationBase)) {