Skip to content

Instantly share code, notes, and snippets.

@arlukin
Last active May 8, 2020 08:16
Show Gist options
  • Save arlukin/28f99a3cbcec4c907e76d15e5f3c3077 to your computer and use it in GitHub Desktop.
Save arlukin/28f99a3cbcec4c907e76d15e5f3c3077 to your computer and use it in GitHub Desktop.
# /node_modules/feathers-mongodb/lib/index.js
# Patched version of _get()
_get (id, params = {}) {
const { query } = this.filterQuery(params);
query.$and = (query.$and || []).concat({ [this.id]: this._objectifyId(id) });
let result = null;
if (params.inTransaction)
result = this.Model.findOneAndUpdate(query, {$set: { myLock: ObjectID() }});
else
result = this.Model.findOne(query);
return result.then(data => {
if (!data) {
throw new errors.NotFound(`No record found for id '${id}'`);
}
return data;
}).then(select(params, this.id)).catch(errorHandler);
}
// eslint-disable-next-line no-unused-vars
function startTransaction(options = {}) {
const transactionOptions = {
readConcern: { level: "snapshot" },
writeConcern: { w: "majority" },
readPreference: "primary"
};
return async (context) => {
const { app } = context;
const client = await app.get("mongoClient");
context.mongoSession = client.startSession();
if (context.mongoSession.inTransaction())
console.error("Already in transaction");
await context.mongoSession.startTransaction(transactionOptions);
context.params.inTransaction = true;
return context;
};
}
// eslint-disable-next-line no-unused-vars
function stopTransaction(options = {}) {
return async (context) => {
try {
await commitWithRetry(context.mongoSession);
} catch (error) {
console.error("abortTransaction");
await context.mongoSession.abortTransaction();
throw error;
}
await context.mongoSession.endSession();
delete context.params.inTransaction;
return context;
};
}
async function commitWithRetry(session) {
try {
await session.commitTransaction();
} catch (error) {
if (error.hasErrorLabel("UnknownTransactionCommitResult")) {
console.error(
"UnknownTransactionCommitResult, retrying commit operation ..."
);
await commitWithRetry(session);
} else {
console.error("Error during commit ...");
throw error;
}
}
}
// eslint-disable-next-line no-unused-vars
function errorTransaction(options = {}) {
return async (context) => {
console.error("stopTransaction");
if (context.mongoSession) {
if (context.mongoSession.inTransaction())
await context.mongoSession.abortTransaction();
await context.mongoSession.endSession();
}
return context;
};
}
module.exports = { startTransaction, stopTransaction, errorTransaction };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment