Undo changes in Sequelize transaction using a specific rollback target

In my current project, I am utilizing managed transactions. There is a specific scenario where I need to implement a single transaction and revert to a certain savepoint if it encounters an error, but still ensure that the changes are committed in the end.

For instance, I aim to create an Event and execute an action. In case the action fails, I wish to undo any database modifications made during the action while retaining the Event record and updating it with the outcome afterwards.

const transaction = await sequelize.transaction();

const event = await Event.create({ ... }, { transaction });

// Set a savepoint here

try {
  const action = await runAction(transaction);
  event.status = 'success';
  event.action_id = action.id;
} catch (err) {
  // Rollback changes since the savepoint
  event.status = 'failure';
  event.failure_message = err.message;
}

await event.save({ transaction });
await transaction.commit();

To achieve this functionality, my understanding leads me to believe that creating a new transaction within the existing one can act as a savepoint:

const transaction = await sequelize.transaction();

const event = await Event.create({ ... }, { transaction });

const savepoint = await sequelize.transaction({ transaction });

try {
  const action = await runAction(savepoint);
  ...
} catch (err) {
  await savepoint.rollback();
  ...
}

await event.save({ transaction });
await transaction.commit();

Nevertheless, despite attempting this method, the operations conducted within runAction using the transaction remain committed. Is there an alternative approach to resolve this issue?

Answer №1

It dawned on me that there was a findOrCreate function being invoked in the midst of executing runAction. In Sequelize, invoking findOrCreate with a transaction supplied in the options triggers the creation of savepoints.

Upon initializing a new transaction and passing a transaction in the options, an automatic savepoint is generated, as evidenced here. This particular savepoint receives an id (which corresponds to its position within the parent savepoint) and undergoes a database query to establish itself within the transaction. Therefore, when I executed

sequelize.transaction({ transaction });
, it resulted in the creation of a savepoint labeled "transaction-id-1". Subsequently, when findOrCreate was triggered with the same "savepoint" transaction, a savepoint bearing the identical name "transaction-id-1" materialized, effectively overwriting the previous savepoint.

Hence, the correct approach would have entailed passing the parent transaction to runAction instead of savepoint:

const transaction = await sequelize.transaction();

const event = await Event.create({ ... }, { transaction });

const savepoint = await sequelize.transaction({ transaction });

try {
  // Utilize parent transaction, not savepoint transaction
  const action = await runAction(transaction);
  ...
} catch (err) {
  await savepoint.rollback();
  ...
}

await event.save({ transaction });
await transaction.commit();

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Stylized search input inspired by Pinterest with a bubbly design

When it comes to my search bar, I want the user's entered keywords to be displayed within a bubble that has a delete option when they press space to add another keyword. This functionality is similar to what Pinterest does with their search bar, as de ...

Is it possible to pass a JavaScript array to a local variable by reference?

Within my namespace, I have an array defined in JavaScript like this: app.collection.box = []; Additionally, there is a function within the same namespace structured as follows: app.init = function () { var box = this.collection.box; // ... code ...

Tips for sending a function with arguments in a React application using TypeScript

Is there a way to streamline passing a handleClick function to the son component so that it does not need to be repeated? The code in question is as follows: Mother Component: const Mother = () => { const [selectedOption, setSelectedOption] = useSt ...

Displaying and Concealing Divisions

My journey to showing/hiding divs began with piecing together a series of questions: $(document).ready(function(){ $('.box').hide(); $('#categories').onMouseOver(function() { $('.box').hide(); $('#div' + ...

The file import is restricted based on the user's input

I am facing an issue with my small vue.js app. My goal is to import a specific json file based on user input. import content from "@/posts/posts/" + new URL(location.href).searchParams.get('id') + ".json"; Every time I attem ...

Execute a refresh command on a JQuery function in order to update the selection picker

Below is the HTML code I have created to allow for multiple options to be selected with live search capabilities. My knowledge of jQuery is limited, but I have included a code snippet to refresh the selections if more than one option is chosen. < ...

IE8 is encountering a null JSON response from the HTTP handler, unlike IE10 and Chrome which are not experiencing this

Here is my JavaScript code snippet: patients.prototype.GetPatient = function(patient_id,callback) { var xmlhttp; var fullpath; try { if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } else { ...

The presence of a backslash is preventing the state from transitioning to '/{username:[a-zA-Z0-9]{3,20}}' within the AngularJs UI-router

In my abstract root state named 'site', the empty URL ('') contains two child states: 'profile' and 'home'. The URL for home is '/', while the URL for profile is '/{username:[a-zA-Z0-9]{3,20}}'. I ...

Experiencing extended loading periods on the website while executing an R script

I am currently working on querying a MySQL database within a webpage using an R script. My script contains 4 different "query" functions and multiple calculations that generate statistical graphs based on a variable "N". To achieve this, I am utilizing PHP ...

Logo remains in place when scrolling halfway down the page

I have a logo that I want to stay halfway up the home page when scrolling, as if fixed in place until it reaches the footer. body { background-color: #fff; margin: 0; } nav { position: sticky; top: 0; width: 300px; height: 80px; margin:4 ...

Leveraging the power of angular's $asyncValidators by implementing a cache

I've created a validation directive that verifies a value against an endpoint App.directive('validate', function(fooService, $q) { return { restrict: "A", require: "ngModel", link: function(scope, elem, attrs, ngModel) { ...

How can the .pre() middleware function in Mongoose be utilized?

I'm curious about the use cases for mongoose .pre('validate') and .pre('save'). I understand their functionality, but I'm struggling to think of specific scenarios where I would need to utilize them. Can't all necessary a ...

Having trouble selecting the first element with cursor on Jquery TokenInput?

I'm currently using a Bootstrap (v5.1.3) card that features an autocomplete field powered by jQuery's TokenInput. Everything seems to be functioning properly, except for the fact that I'm unable to access the first element of the field usin ...

Error: Unable to interpret the URL provided in /api/posts/1

When working on my next.js 13 app, I encountered an issue while trying to fetch individual blog data from a local MySQL database. In the src/blog/[id]/page.js file, I have the following component: const BlogPost = async ({ params }) => { const data ...

Uh oh! We've encountered an issue: Unable to update headers once they have been sent

I am currently working with express and node.js My objective is to redirect users to /welcome when they visit /index and have a specific tracking code in the URL. The redirectBasedReferrer function handles the redirection based on the tracking code. inde ...

Creating a custom header in React for making AJAX requests

Need help setting header in Ajax Request using axios import React, { Component, PropTypes } from 'react' import { Link, browserHistory } from 'react-router' import { connect } from 'react-redux' import axios from 'axios& ...

The start "NaN" is not valid for the timeline in vis.js

Whenever I attempt to make a call, an error message pops up saying Error: Invalid start "NaN". I've looked everywhere online for a solution with no success. Below are the timeline options: timeline: { stack: true, start: new Date(), end: ...

Set the array back to its initial value of 1 using jQuery and

After making substantial edits to this question, I find myself in need of a reset button for the code. The current item needs to be reset back to 1 so that I can use it again, but the issue lies in the fact that only the current item is reset while the hig ...

Experience the power of dynamic site regeneration with GatsbyJS

Currently, I am working on a website built in GatsbyJS that deals with large datasets of dynamic content fetched using React fetch upon page load. The challenge here is to display semi-live data that updates every 5 minutes. I am curious about how I can m ...

Is it possible to convert nested CSS into Material-UI's CSS in JS method?

Here is the code for embedding an iframe: <style>.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } .embed-container iframe, .embed-container object, .embed-container embed { position: abso ...