Skip to content

Commit

Permalink
fix(topology): add new error for retryWrites on MMAPv1
Browse files Browse the repository at this point in the history
Fixes NODE-2098
  • Loading branch information
kvwalker authored and daprahamian committed Aug 13, 2019
1 parent 2ef8f2c commit 392f5a6
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/core/sdam/topology.js
Expand Up @@ -25,6 +25,7 @@ const createClientInfo = require('../topologies/shared').createClientInfo;
const MongoError = require('../error').MongoError;
const resolveClusterTime = require('../topologies/shared').resolveClusterTime;
const SrvPoller = require('./srv_polling').SrvPoller;
const getMMAPError = require('../topologies/shared').getMMAPError;

// Global state
let globalTopologyCounter = 0;
Expand Down Expand Up @@ -972,6 +973,7 @@ function executeWriteOperation(args, options, callback) {
const handler = (err, result) => {
if (!err) return callback(null, result);
if (!isRetryableError(err)) {
err = getMMAPError(err);
return callback(err);
}

Expand Down
2 changes: 2 additions & 0 deletions lib/core/topologies/mongos.js
Expand Up @@ -17,6 +17,7 @@ const isRetryableWritesSupported = require('./shared').isRetryableWritesSupporte
const relayEvents = require('../utils').relayEvents;
const isRetryableError = require('../error').isRetryableError;
const BSON = retrieveBSON();
const getMMAPError = require('./shared').getMMAPError;

/**
* @fileOverview The **Mongos** class is a class that represents a Mongos Proxy topology and is
Expand Down Expand Up @@ -880,6 +881,7 @@ function executeWriteOperation(args, options, callback) {
const handler = (err, result) => {
if (!err) return callback(null, result);
if (!isRetryableError(err) || !willRetryWrite) {
err = getMMAPError(err);
return callback(err);
}

Expand Down
2 changes: 2 additions & 0 deletions lib/core/topologies/replset.js
Expand Up @@ -20,6 +20,7 @@ const relayEvents = require('../utils').relayEvents;
const isRetryableError = require('../error').isRetryableError;
const BSON = retrieveBSON();
const calculateDurationInMs = require('../utils').calculateDurationInMs;
const getMMAPError = require('./shared').getMMAPError;

//
// States
Expand Down Expand Up @@ -1190,6 +1191,7 @@ function executeWriteOperation(args, options, callback) {
const handler = (err, result) => {
if (!err) return callback(null, result);
if (!isRetryableError(err)) {
err = getMMAPError(err);
return callback(err);
}

Expand Down
22 changes: 22 additions & 0 deletions lib/core/topologies/shared.js
Expand Up @@ -5,6 +5,9 @@ const f = require('util').format;
const ReadPreference = require('./read_preference');
const Buffer = require('safe-buffer').Buffer;
const TopologyType = require('../sdam/topology_description').TopologyType;
const MongoError = require('../error').MongoError;

const MMAPv1_RETRY_WRITES_ERROR_CODE = 20;

/**
* Emit event if it exists
Expand Down Expand Up @@ -437,6 +440,24 @@ const isRetryableWritesSupported = function(topology) {
return true;
};

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

function getMMAPError(err) {
if (err.code !== MMAPv1_RETRY_WRITES_ERROR_CODE || !err.errmsg.includes('Transaction numbers')) {
return err;
}

// According to the retryable writes spec, we must replace the error message in this case.
// We need to replace err.message so the thrown message is correct and we need to replace err.errmsg to meet the spec requirement.
const newErr = new MongoError({
message: MMAPv1_RETRY_WRITES_ERROR_MESSAGE,
errmsg: MMAPv1_RETRY_WRITES_ERROR_MESSAGE,
originalError: err
});
return newErr;
}

module.exports.SessionMixins = SessionMixins;
module.exports.resolveClusterTime = resolveClusterTime;
module.exports.inquireServerState = inquireServerState;
Expand All @@ -451,3 +472,4 @@ module.exports.diff = diff;
module.exports.Interval = Interval;
module.exports.Timeout = Timeout;
module.exports.isRetryableWritesSupported = isRetryableWritesSupported;
module.exports.getMMAPError = getMMAPError;

0 comments on commit 392f5a6

Please sign in to comment.