Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,6 @@ export type {
CollationOptions,
CommandOperation,
CommandOperationOptions,
ModernizedCommandOperation,
OperationParent
} from './operations/command';
export type { CountOptions } from './operations/count';
Expand Down Expand Up @@ -544,12 +543,7 @@ export type {
export type { InsertManyResult, InsertOneOptions, InsertOneResult } from './operations/insert';
export type { CollectionInfo, ListCollectionsOptions } from './operations/list_collections';
export type { ListDatabasesOptions, ListDatabasesResult } from './operations/list_databases';
export type {
AbstractOperation,
Hint,
ModernizedOperation,
OperationOptions
} from './operations/operation';
export type { AbstractOperation, Hint, OperationOptions } from './operations/operation';
export type { ProfilingLevelOptions } from './operations/profiling_level';
export type { RemoveUserOptions } from './operations/remove_user';
export type { RenameOptions } from './operations/rename';
Expand Down
4 changes: 2 additions & 2 deletions src/mongo_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
} from './operations/client_bulk_write/common';
import { ClientBulkWriteExecutor } from './operations/client_bulk_write/executor';
import { executeOperation } from './operations/execute_operation';
import { ModernizedOperation } from './operations/operation';
import { AbstractOperation } from './operations/operation';
import type { ReadConcern, ReadConcernLevel, ReadConcernLike } from './read_concern';
import { ReadPreference, type ReadPreferenceMode } from './read_preference';
import { type AsyncDisposable, configureResourceManagement } from './resource_management';
Expand Down Expand Up @@ -792,7 +792,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
const endSessions = Array.from(this.s.sessionPool.sessions, ({ id }) => id);
if (endSessions.length !== 0) {
try {
class EndSessionsOperation extends ModernizedOperation<void> {
class EndSessionsOperation extends AbstractOperation<void> {
override ns = MongoDBNamespace.fromString('admin.$cmd');
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override buildCommand(_connection: Connection, _session?: ClientSession): Document {
Expand Down
8 changes: 2 additions & 6 deletions src/operations/aggregate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ import { MongoInvalidArgumentError } from '../error';
import { type ExplainOptions } from '../explain';
import { maxWireVersion, type MongoDBNamespace } from '../utils';
import { WriteConcern } from '../write_concern';
import {
type CollationOptions,
type CommandOperationOptions,
ModernizedCommandOperation
} from './command';
import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
import { Aspect, defineAspects, type Hint } from './operation';

/** @internal */
Expand Down Expand Up @@ -53,7 +49,7 @@ export interface AggregateOptions extends Omit<CommandOperationOptions, 'explain
}

/** @internal */
export class AggregateOperation extends ModernizedCommandOperation<CursorResponse> {
export class AggregateOperation extends CommandOperation<CursorResponse> {
override SERVER_COMMAND_RESPONSE_TYPE = CursorResponse;
override options: AggregateOptions;
target: string | typeof DB_AGGREGATE_COLLECTION;
Expand Down
4 changes: 2 additions & 2 deletions src/operations/client_bulk_write/client_bulk_write.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { type Connection } from '../../cmap/connection';
import { ClientBulkWriteCursorResponse } from '../../cmap/wire_protocol/responses';
import type { ClientSession } from '../../sessions';
import { MongoDBNamespace } from '../../utils';
import { ModernizedCommandOperation } from '../command';
import { CommandOperation } from '../command';
import { Aspect, defineAspects } from '../operation';
import { type ClientBulkWriteCommand, type ClientBulkWriteCommandBuilder } from './command_builder';
import { type ClientBulkWriteOptions } from './common';
Expand All @@ -11,7 +11,7 @@ import { type ClientBulkWriteOptions } from './common';
* Executes a single client bulk write operation within a potential batch.
* @internal
*/
export class ClientBulkWriteOperation extends ModernizedCommandOperation<ClientBulkWriteCursorResponse> {
export class ClientBulkWriteOperation extends CommandOperation<ClientBulkWriteCursorResponse> {
override SERVER_COMMAND_RESPONSE_TYPE = ClientBulkWriteCursorResponse;

commandBuilder: ClientBulkWriteCommandBuilder;
Expand Down
108 changes: 2 additions & 106 deletions src/operations/command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { type Connection } from '..';
import type { BSONSerializeOptions, Document } from '../bson';
import { type MongoDBResponseConstructor } from '../cmap/wire_protocol/responses';
import { MongoInvalidArgumentError } from '../error';
import {
decorateWithExplain,
Expand All @@ -10,13 +9,13 @@ import {
} from '../explain';
import { ReadConcern } from '../read_concern';
import type { ReadPreference } from '../read_preference';
import type { Server, ServerCommandOptions } from '../sdam/server';
import type { ServerCommandOptions } from '../sdam/server';
import type { ClientSession } from '../sessions';
import { type TimeoutContext } from '../timeout';
import { commandSupportsReadConcern, MongoDBNamespace } from '../utils';
import { WriteConcern, type WriteConcernOptions } from '../write_concern';
import type { ReadConcernLike } from './../read_concern';
import { AbstractOperation, Aspect, ModernizedOperation, type OperationOptions } from './operation';
import { AbstractOperation, Aspect, type OperationOptions } from './operation';

/** @public */
export interface CollationOptions {
Expand Down Expand Up @@ -117,109 +116,6 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
return super.canRetryWrite;
}

public async executeCommand<T extends MongoDBResponseConstructor>(
server: Server,
session: ClientSession | undefined,
cmd: Document,
timeoutContext: TimeoutContext,
responseType: T | undefined
): Promise<typeof responseType extends undefined ? Document : InstanceType<T>>;

public async executeCommand(
server: Server,
session: ClientSession | undefined,
cmd: Document,
timeoutContext: TimeoutContext
): Promise<Document>;

async executeCommand(
server: Server,
session: ClientSession | undefined,
cmd: Document,
timeoutContext: TimeoutContext,
responseType?: MongoDBResponseConstructor
): Promise<Document> {
this.server = server;

const options = {
...this.options,
...this.bsonOptions,
timeoutContext,
readPreference: this.readPreference,
session
};

const inTransaction = this.session && this.session.inTransaction();

if (this.readConcern && commandSupportsReadConcern(cmd) && !inTransaction) {
Object.assign(cmd, { readConcern: this.readConcern });
}

if (this.writeConcern && this.hasAspect(Aspect.WRITE_OPERATION) && !inTransaction) {
WriteConcern.apply(cmd, this.writeConcern);
}

if (
options.collation &&
typeof options.collation === 'object' &&
!this.hasAspect(Aspect.SKIP_COLLATION)
) {
Object.assign(cmd, { collation: options.collation });
}

if (typeof options.maxTimeMS === 'number') {
cmd.maxTimeMS = options.maxTimeMS;
}

if (this.hasAspect(Aspect.EXPLAINABLE) && this.explain) {
cmd = decorateWithExplain(cmd, this.explain);
}

return await server.command(this.ns, cmd, options, responseType);
}
}

/** @internal */
export abstract class ModernizedCommandOperation<T> extends ModernizedOperation<T> {
override options: CommandOperationOptions;
readConcern?: ReadConcern;
writeConcern?: WriteConcern;
explain?: Explain;

constructor(parent?: OperationParent, options?: CommandOperationOptions) {
super(options);
this.options = options ?? {};

// NOTE: this was explicitly added for the add/remove user operations, it's likely
// something we'd want to reconsider. Perhaps those commands can use `Admin`
// as a parent?
const dbNameOverride = options?.dbName || options?.authdb;
if (dbNameOverride) {
this.ns = new MongoDBNamespace(dbNameOverride, '$cmd');
} else {
this.ns = parent
? parent.s.namespace.withCollection('$cmd')
: new MongoDBNamespace('admin', '$cmd');
}

this.readConcern = ReadConcern.fromOptions(options);
this.writeConcern = WriteConcern.fromOptions(options);

if (this.hasAspect(Aspect.EXPLAINABLE)) {
this.explain = Explain.fromOptions(options);
if (this.explain) validateExplainTimeoutOptions(this.options, this.explain);
} else if (options?.explain != null) {
throw new MongoInvalidArgumentError(`Option "explain" is not supported on this command`);
}
}

override get canRetryWrite(): boolean {
if (this.hasAspect(Aspect.EXPLAINABLE)) {
return this.explain == null;
}
return super.canRetryWrite;
}

abstract buildCommandDocument(connection: Connection, session?: ClientSession): Document;

override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
Expand Down
4 changes: 2 additions & 2 deletions src/operations/count.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { MongoDBResponse } from '../cmap/wire_protocol/responses';
import type { Collection } from '../collection';
import type { ClientSession } from '../sessions';
import type { MongoDBNamespace } from '../utils';
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
import { CommandOperation, type CommandOperationOptions } from './command';
import { Aspect, defineAspects } from './operation';

/** @public */
Expand All @@ -22,7 +22,7 @@ export interface CountOptions extends CommandOperationOptions {
}

/** @internal */
export class CountOperation extends ModernizedCommandOperation<number> {
export class CountOperation extends CommandOperation<number> {
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override options: CountOptions;
collectionName?: string;
Expand Down
4 changes: 2 additions & 2 deletions src/operations/create_collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { PkFactory } from '../mongo_client';
import type { ClientSession } from '../sessions';
import { TimeoutContext } from '../timeout';
import { maxWireVersion } from '../utils';
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
import { CommandOperation, type CommandOperationOptions } from './command';
import { executeOperation } from './execute_operation';
import { CreateIndexesOperation } from './indexes';
import { Aspect, defineAspects } from './operation';
Expand Down Expand Up @@ -112,7 +112,7 @@ const INVALID_QE_VERSION =
'Driver support of Queryable Encryption is incompatible with server. Upgrade server to use Queryable Encryption.';

/** @internal */
export class CreateCollectionOperation extends ModernizedCommandOperation<Collection> {
export class CreateCollectionOperation extends CommandOperation<Collection> {
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override options: CreateCollectionOptions;
db: Db;
Expand Down
8 changes: 2 additions & 6 deletions src/operations/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import { MongoCompatibilityError, MongoServerError } from '../error';
import type { ClientSession } from '../sessions';
import { type MongoDBCollectionNamespace, type MongoDBNamespace } from '../utils';
import { type WriteConcernOptions } from '../write_concern';
import {
type CollationOptions,
type CommandOperationOptions,
ModernizedCommandOperation
} from './command';
import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
import { Aspect, defineAspects, type Hint } from './operation';

/** @public */
Expand Down Expand Up @@ -45,7 +41,7 @@ export interface DeleteStatement {
}

/** @internal */
export class DeleteOperation extends ModernizedCommandOperation<Document> {
export class DeleteOperation extends CommandOperation<Document> {
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override options: DeleteOptions;
statements: DeleteStatement[];
Expand Down
4 changes: 2 additions & 2 deletions src/operations/distinct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { type Document } from '../bson';
import { type Connection } from '../cmap/connection';
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
import type { Collection } from '../collection';
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
import { CommandOperation, type CommandOperationOptions } from './command';
import { Aspect, defineAspects } from './operation';

/** @public */
Expand All @@ -25,7 +25,7 @@ export type DistinctOptions = CommandOperationOptions & {
* Return a list of distinct values for the given key across a collection.
* @internal
*/
export class DistinctOperation extends ModernizedCommandOperation<any[] | Document> {
export class DistinctOperation extends CommandOperation<any[] | Document> {
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override options: DistinctOptions;
collection: Collection;
Expand Down
6 changes: 3 additions & 3 deletions src/operations/drop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { Db } from '../db';
import { MONGODB_ERROR_CODES } from '../error';
import type { ClientSession } from '../sessions';
import { TimeoutContext } from '../timeout';
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
import { CommandOperation, type CommandOperationOptions } from './command';
import { executeOperation } from './execute_operation';
import { Aspect, defineAspects } from './operation';

Expand All @@ -17,7 +17,7 @@ export interface DropCollectionOptions extends CommandOperationOptions {
}

/** @internal */
export class DropCollectionOperation extends ModernizedCommandOperation<boolean> {
export class DropCollectionOperation extends CommandOperation<boolean> {
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;

override options: DropCollectionOptions;
Expand Down Expand Up @@ -107,7 +107,7 @@ export async function dropCollections(
export type DropDatabaseOptions = CommandOperationOptions;

/** @internal */
export class DropDatabaseOperation extends ModernizedCommandOperation<boolean> {
export class DropDatabaseOperation extends CommandOperation<boolean> {
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override options: DropDatabaseOptions;

Expand Down
4 changes: 2 additions & 2 deletions src/operations/estimated_document_count.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Document } from '../bson';
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
import type { Collection } from '../collection';
import type { ClientSession } from '../sessions';
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
import { CommandOperation, type CommandOperationOptions } from './command';
import { Aspect, defineAspects } from './operation';

/** @public */
Expand All @@ -17,7 +17,7 @@ export interface EstimatedDocumentCountOptions extends CommandOperationOptions {
}

/** @internal */
export class EstimatedDocumentCountOperation extends ModernizedCommandOperation<number> {
export class EstimatedDocumentCountOperation extends CommandOperation<number> {
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override options: EstimatedDocumentCountOptions;
collectionName: string;
Expand Down
19 changes: 5 additions & 14 deletions src/operations/execute_operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,15 @@ import type { ClientSession } from '../sessions';
import { TimeoutContext } from '../timeout';
import { abortable, supportsRetryableWrites } from '../utils';
import { AggregateOperation } from './aggregate';
import { AbstractOperation, Aspect, ModernizedOperation } from './operation';
import { AbstractOperation, Aspect } from './operation';

const MMAPv1_RETRY_WRITES_ERROR_CODE = MONGODB_ERROR_CODES.IllegalOperation;
const MMAPv1_RETRY_WRITES_ERROR_MESSAGE =
'This MongoDB deployment does not support retryable writes. Please add retryWrites=false to your connection string.';

type ResultTypeFromOperation<TOperation> =
TOperation extends ModernizedOperation<infer _>
? ReturnType<TOperation['handleOk']>
: TOperation extends AbstractOperation<infer K>
? K
: never;
type ResultTypeFromOperation<TOperation extends AbstractOperation> = ReturnType<
TOperation['handleOk']
>;

/**
* Executes the given operation with provided arguments.
Expand Down Expand Up @@ -235,8 +232,6 @@ async function tryOperation<T extends AbstractOperation, TResult = ResultTypeFro
let previousOperationError: MongoError | undefined;
let previousServer: ServerDescription | undefined;

const isModernOperation = operation instanceof ModernizedOperation;

for (let tries = 0; tries < maxTries; tries++) {
if (previousOperationError) {
if (hasWriteAspect && previousOperationError.code === MMAPv1_RETRY_WRITES_ERROR_CODE) {
Expand Down Expand Up @@ -290,12 +285,8 @@ async function tryOperation<T extends AbstractOperation, TResult = ResultTypeFro
operation.resetBatch();
}

if (!isModernOperation) {
return await operation.execute(server, session, timeoutContext);
}

try {
const result = await server.modernCommand(operation, timeoutContext);
const result = await server.command(operation, timeoutContext);
return operation.handleOk(result);
} catch (error) {
return operation.handleError(error);
Expand Down
Loading