In my extensive Nodejs development practice, I have found that rollback is a very serious topic that should be taken seriously. We can’t just pray that the divine program doesn’t go wrong and ignore the error handler.

For example, in the process of developing a publishing system, we have a series of operations, including database CRUD and FS to operate project files and gitLab API. At this point our order might look something like this:

  1. The database inserts an item and returns an item ID
  2. Using the project ID, name the project folder as the FS operationproject_${id}
  3. Upload the project folder and all the following files to an FTP file
  4. Then work on the details of the project in GitLab

Let’s imagine the scenario:

  1. If we make a mistake at step 1, we have a database insert problem, maybe our database suddenly hangs, then our program will throw an error, and of course it doesn’t matter, because we didn’t do anything else.
  2. If we had made an error in step 2 and the folder was the same name, we might have thrown an error, but we didn’t use rollback at that time, so the database was inserted, but the folder contents didn’t match what we wanted.
  3. If we get it wrong in step 3, the database has been inserted, the folder has been named, and FTP suddenly hangs, then the database has invalid data, and the file has invalid data.
  4. If we fail in step 4 and everything else is correct, do we fail to synchronize data, files, and API operations due to the operations that occurred in step 3

Then how embarrassed we would be. Of course, we can catch errors and handle them accordingly. But we don’t know at which step we will roll back the corresponding behavior. After my summary, I propose three rollback modes:

  1. Transaction rollback (mysql, Redis, MSSQL, etc.)
  2. Physical rollback (mainly FS operations, etc.)
  3. API rollback

We need to build a task mechanism on which two concepts are implemented:

  1. Task: Resolve The task succeeds
  2. Task :reject Indicates the callback of a task failure

Let’s take a look at the following.

The general idea

When it comes to quest mechanics, we naturally think of the following patterns:

const task = new Tasker();
task.add(async() = > {await mysql.add({
        a: 1.b: 2})}); task.add(async () => {
    fs.writeFileSync('/a'.'aaaaaa'.'utf8');
});

/ /...

await task.run();
Copy the code

Yes, in fact, the idea is very correct, combined with the concept we put forward, it becomes the following:

task.add(async function resolve() {
    fs.writeFileSync('/a'.'aaaaaa'.'utf8');
}, async function reject() {
    fs.unlinkSync('/a');
})
Copy the code

It’s true that we implemented simple mission mechanics. But if we find it too cumbersome to write this way, then we will introduce our key module for today, YS-DBO

Use YS-DBO to solve rollback problems

Let’s start with a piece of code:

const DBO = require('ys-dbo');
const dbo = new DBO();
// We assume that the mysql module is already installed
dbo.until(async thread => {
    // Let's implement the previous code
    const file = '/tmp/test.txt';
    await mysql.begin();
    await mysql.insert('table', {
        a: 1.b: 2
    });
    fs.writeFileSync(file, 'aaaaaa'.'utf8');
    thread.on('beforeRollback'.async () => fs.unlinkSync(file));
    gitlab.fork('project');
    thread.on('beforeRollback'.async () => gitlab.deleteProject('project')); }).then(...) .catch(...)Copy the code

We can see from the above code that there is no trace of task.add, but instead beforeRollback or afterRollback. We simplify the task mechanism by using the Action + Event pattern.

So we can look at a graph:

The rollback mechanism is clearly described in the figure above. We manage the task queue through a one-to-one registration pattern.

Now I find that many students do not like to use rollback, may dislike the more troublesome writing method, such written code compatibility is not good. But it’s important to remember that rollback is an important way to keep data in a consistent state. We should focus on rolling back, not praying to god for mistakes.

In our company, I also asked a lot of Java development students, few people use rollback, I wonder, as a development engineer, do not consider rigorous mode, this is not qualified, rollback can also show an engineer’s code literacy.

What is YS-DBO?

You do not need to care about this module deliberately, after all, it is the module out of personal development practice, and the degree of perfection may not be very high, but I will always maintain it, because after all, I also use it in my work.

Project address: github.com/yskit/ys-db…

npm i ys-dbo
Copy the code

If you like it, please give it a thumbs up. Thank you!