Skip to content

Commit 39fc198

Browse files
fix(NODE-5925): driver throws error when non-read operation in a transaction has a ReadPreferenceMode other than 'primary' (#4075)
1 parent 8845206 commit 39fc198

File tree

4 files changed

+12
-10
lines changed

4 files changed

+12
-10
lines changed

src/operations/execute_operation.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,14 @@ export async function executeOperation<
119119
const readPreference = operation.readPreference ?? ReadPreference.primary;
120120
const inTransaction = !!session?.inTransaction();
121121

122-
if (inTransaction && !readPreference.equals(ReadPreference.primary)) {
122+
const hasReadAspect = operation.hasAspect(Aspect.READ_OPERATION);
123+
const hasWriteAspect = operation.hasAspect(Aspect.WRITE_OPERATION);
124+
125+
if (
126+
inTransaction &&
127+
!readPreference.equals(ReadPreference.primary) &&
128+
(hasReadAspect || operation.commandName === 'runCommand')
129+
) {
123130
throw new MongoTransactionError(
124131
`Read preference in a transaction must be primary, not: ${readPreference.mode}`
125132
);
@@ -177,8 +184,6 @@ export async function executeOperation<
177184
supportsRetryableWrites(server) &&
178185
operation.canRetryWrite;
179186

180-
const hasReadAspect = operation.hasAspect(Aspect.READ_OPERATION);
181-
const hasWriteAspect = operation.hasAspect(Aspect.WRITE_OPERATION);
182187
const willRetry = (hasReadAspect && willRetryRead) || (hasWriteAspect && willRetryWrite);
183188

184189
if (hasWriteAspect && willRetryWrite) {

src/sessions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ export class ClientSession extends TypedEventEmitter<ClientSessionEvents> {
194194

195195
this.operationTime = undefined;
196196
this.owner = options.owner;
197-
this.defaultTransactionOptions = Object.assign({}, options.defaultTransactionOptions);
197+
this.defaultTransactionOptions = { ...options.defaultTransactionOptions };
198198
this.transaction = new Transaction();
199199
}
200200

test/integration/transactions/transactions.spec.test.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import { loadSpecTests } from '../../spec';
44
import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner';
55

66
const SKIPPED_TESTS = [
7-
// TODO(NODE-5925) - secondary read preference not allowed in transactions.
8-
'readPreference inherited from defaultTransactionOptions',
97
// TODO(NODE-5924) - Fix modification of readConcern object post message send.
108
'readConcern local in defaultTransactionOptions',
119
'defaultTransactionOptions override client options',
@@ -17,7 +15,7 @@ const SKIPPED_TESTS = [
1715
describe('Transactions Spec Unified Tests', function () {
1816
runUnifiedSuite(loadSpecTests(path.join('transactions', 'unified')), test => {
1917
return SKIPPED_TESTS.includes(test.description)
20-
? 'TODO(NODE-5924/NODE-5925): Skipping failing transaction tests'
18+
? 'TODO(NODE-5924): Skipping failing transaction tests'
2119
: false;
2220
});
2321
});

test/tools/unified-spec-runner/entities.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -620,9 +620,8 @@ export class EntitiesMap<E = Entity> extends Map<string, E> {
620620
WriteConcern.fromOptions(defaultOptions);
621621
}
622622
if (defaultOptions.readPreference) {
623-
options.defaultTransactionOptions.readPreference = ReadPreference.fromOptions(
624-
defaultOptions.readPreference
625-
);
623+
options.defaultTransactionOptions.readPreference =
624+
ReadPreference.fromOptions(defaultOptions);
626625
}
627626
if (typeof defaultOptions.maxCommitTimeMS === 'number') {
628627
options.defaultTransactionOptions.maxCommitTimeMS = defaultOptions.maxCommitTimeMS;

0 commit comments

Comments
 (0)