Skip to content

Instantly share code, notes, and snippets.

@zeusdeux
Created November 20, 2018 10:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zeusdeux/ac0e2fa9d1cc65686f0dbbf0a399d474 to your computer and use it in GitHub Desktop.
Save zeusdeux/ac0e2fa9d1cc65686f0dbbf0a399d474 to your computer and use it in GitHub Desktop.
Simple transaction in js
/**
* @description
* Returns a transaction object which is composed of operations.
* The transaction resolves only when all operations it is made of succeed.
* If any operation fails, it reverts ALL operations and rejects the transaction.
* If any of the reverts also fail, then it rejects the transaction as well
* with an error that can help the developer manually make data consistent.
*
* @param {function} transaction - A function that builds operations and calls run on them
*
* @return Promise
*/
function makeTransaction(transaction) {
const ops = [];
function makeOperation(op, revertOp) {
const wrappedOp = {
async run() {
try {
await op();
} catch (e) {
e.failedOperation = op;
e.failedOperationName = op.name;
e.failType = 'operation:run';
throw e;
}
},
async revert() {
try {
await revertOp();
} catch (e) {
e.failedOperation = revertOp;
e.failedOperationName = revertOp.name;
e.failType = 'operation:revert';
throw e;
}
},
toString: () => `Operation: ${op.name}\nRevert operation: ${revertOp.name}`
};
ops.push(wrappedOp);
return wrappedOp;
}
return {
run: async () => {
try {
const result = await transaction(makeOperation);
return result;
} catch (e) {
for (const op of ops) {
try {
await op.revert();
} catch (revertError) {
revertError.message = `Revert failed. ${op.toString()}\nOriginal error message: ${
revertError.message
}`;
throw revertError;
}
}
e.message = `Transaction failed due to ${e.failedOperationName ||
e.failedOperation.toString()} failing, but reverts were successful.\nOriginal error message: ${
e.message
}`;
e.transactionCompleted = true;
throw e;
}
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment