Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ export type {
CollationOptions,
CommandOperation,
CommandOperationOptions,
ModernizedCommandOperation,
CommandOperation as ModernizedCommandOperation,
OperationParent
} from './operations/command';
export type { CountOptions } from './operations/count';
Expand Down Expand Up @@ -547,7 +547,7 @@ export type { ListDatabasesOptions, ListDatabasesResult } from './operations/lis
export type {
AbstractOperation,
Hint,
ModernizedOperation,
AbstractOperation as ModernizedOperation,
OperationOptions
} from './operations/operation';
export type { ProfilingLevelOptions } from './operations/profiling_level';
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
8 changes: 2 additions & 6 deletions src/operations/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import type { ServerCommandOptions } from '../sdam/server';
import { formatSort, type Sort } from '../sort';
import { type TimeoutContext } from '../timeout';
import { type MongoDBNamespace, normalizeHintField } from '../utils';
import {
type CollationOptions,
type CommandOperationOptions,
ModernizedCommandOperation
} from './command';
import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
import { Aspect, defineAspects, type Hint } from './operation';

/**
Expand Down Expand Up @@ -90,7 +86,7 @@ export interface FindOneOptions extends FindOptions {
}

/** @internal */
export class FindOperation extends ModernizedCommandOperation<CursorResponse> {
export class FindOperation extends CommandOperation<CursorResponse> {
override SERVER_COMMAND_RESPONSE_TYPE = CursorResponse;

/**
Expand Down
Loading