Search code examples
expressnginxvps

Express, run code on a seperate thread on server


My Issue
I have a form where when the user submits, I want the server to start a separate thread and run a function in that thread, then redirect the user back to the main page, where the connection can be closed and the code will still run.
Essentially the goal is that the user clicks a button, the form submits and the server runs the code without the user having to stay on the page.

app.get('/lockout/', async (req, res) => {
var nnumber = req.query.nnumber;
var time = req.query.time;

for (var i = 0; i < time; i++) {
    console.log(nnumber + " is locked out");
    sleep(1000);
}

res.send("Locked out");
});

Notes
Please excuse my inexperience with Node and express, I am new to this so please explain thoroughly, my main languages are C# and C++. I am running an Ubuntu VPS with nginx reverse proxy on DigitalOcean.


Solution

  • What you want to do is called "Asynchronus task processing" and needs some more things to it.

    I would use bull as a framework to work with your Queue based on Redis. This will let you store a form submit request in a queue and process it in a new process and the user can close the connection after submitting the form.

    In NodeJs it could look like

    npm install bull --save
    
    const Queue = require('bull');
    //....
    
    
    export class FormQueue{
      constructor(){
        // initialize queue
        this.queue = new Queue('formSubmits');
        // add a worker
        this.queue.process('forms', job => {
          this.sendEmail(job)
        })
      }
      addFormToQueue(data){
        this.queue.add('forms', data)
      }
      async sendEmail(job){
        const { to, from, subject, text, html} = job.data;
        const msg = {
          to,
          from,
          subject,
          text,
          html
        };
        try {
          await sgMail.send(msg)
          // mark the task as complete.
          job.moveToCompleted('done', true)
        } catch (error) {
          if (error.response) {
            job.moveToFailed({message: 'job failed'})
          }
        }
      }
    }
    

    Credits / More Information: https://blog.logrocket.com/asynchronous-task-processing-in-node-js-with-bull/