Trigger function with a delay longer than an hour in a Node/Express app












1














I would like to trigger a function in my express app with a delay of 1 hour or 5 hours after a specific endpoint was called.



I've tried using a simple setTimeout in the then chain of my enpoint with something like this in my controller:



function(req, res, next) {

return mailer.sendEmail(req.user, 'firstEmail') // returns a promise
.then(function(emailResult) {
if (emailResult == 'ok') {
res.sendStatus(200).json({ message: 'You will receive an email in 1 hour' }) // set positive API json response
} else {
res.sendStatus(200).json({ message: 'You will receive an email in 5 hour' }) // set negative API json response
}
return emailResult
})
.then(function(emailResult){
return new Promise((resolve, reject) => {
setTimeout(function(){
return return mailer.sendEmail(req.user, 'secondEmail')
}, emailResult == 'ok' ? 60 * 60 * 1000 : 5 * 60 * 60 * 1000) // 1 hour or 5 hours
})
})
})


and seems to work but I have two main dubts:




  • If I restart the pm2 process of my application with (pm2 startOrReload prod.json), all the timeouts are cancelled?

  • If I have something like 600 timeouts scheduled with this system can I have any performance issues?


Any experience with something like this?










share|improve this question


















  • 1




    You should probably consider some sort of dedicated queue for this, like kue.
    – robertklep
    Nov 19 '18 at 13:06










  • seems a good choice, thanks for the suggestion
    – lellefood
    Nov 19 '18 at 14:22










  • At the end I decided to use kue to manage jobs and delay them
    – lellefood
    Dec 4 '18 at 9:18
















1














I would like to trigger a function in my express app with a delay of 1 hour or 5 hours after a specific endpoint was called.



I've tried using a simple setTimeout in the then chain of my enpoint with something like this in my controller:



function(req, res, next) {

return mailer.sendEmail(req.user, 'firstEmail') // returns a promise
.then(function(emailResult) {
if (emailResult == 'ok') {
res.sendStatus(200).json({ message: 'You will receive an email in 1 hour' }) // set positive API json response
} else {
res.sendStatus(200).json({ message: 'You will receive an email in 5 hour' }) // set negative API json response
}
return emailResult
})
.then(function(emailResult){
return new Promise((resolve, reject) => {
setTimeout(function(){
return return mailer.sendEmail(req.user, 'secondEmail')
}, emailResult == 'ok' ? 60 * 60 * 1000 : 5 * 60 * 60 * 1000) // 1 hour or 5 hours
})
})
})


and seems to work but I have two main dubts:




  • If I restart the pm2 process of my application with (pm2 startOrReload prod.json), all the timeouts are cancelled?

  • If I have something like 600 timeouts scheduled with this system can I have any performance issues?


Any experience with something like this?










share|improve this question


















  • 1




    You should probably consider some sort of dedicated queue for this, like kue.
    – robertklep
    Nov 19 '18 at 13:06










  • seems a good choice, thanks for the suggestion
    – lellefood
    Nov 19 '18 at 14:22










  • At the end I decided to use kue to manage jobs and delay them
    – lellefood
    Dec 4 '18 at 9:18














1












1








1







I would like to trigger a function in my express app with a delay of 1 hour or 5 hours after a specific endpoint was called.



I've tried using a simple setTimeout in the then chain of my enpoint with something like this in my controller:



function(req, res, next) {

return mailer.sendEmail(req.user, 'firstEmail') // returns a promise
.then(function(emailResult) {
if (emailResult == 'ok') {
res.sendStatus(200).json({ message: 'You will receive an email in 1 hour' }) // set positive API json response
} else {
res.sendStatus(200).json({ message: 'You will receive an email in 5 hour' }) // set negative API json response
}
return emailResult
})
.then(function(emailResult){
return new Promise((resolve, reject) => {
setTimeout(function(){
return return mailer.sendEmail(req.user, 'secondEmail')
}, emailResult == 'ok' ? 60 * 60 * 1000 : 5 * 60 * 60 * 1000) // 1 hour or 5 hours
})
})
})


and seems to work but I have two main dubts:




  • If I restart the pm2 process of my application with (pm2 startOrReload prod.json), all the timeouts are cancelled?

  • If I have something like 600 timeouts scheduled with this system can I have any performance issues?


Any experience with something like this?










share|improve this question













I would like to trigger a function in my express app with a delay of 1 hour or 5 hours after a specific endpoint was called.



I've tried using a simple setTimeout in the then chain of my enpoint with something like this in my controller:



function(req, res, next) {

return mailer.sendEmail(req.user, 'firstEmail') // returns a promise
.then(function(emailResult) {
if (emailResult == 'ok') {
res.sendStatus(200).json({ message: 'You will receive an email in 1 hour' }) // set positive API json response
} else {
res.sendStatus(200).json({ message: 'You will receive an email in 5 hour' }) // set negative API json response
}
return emailResult
})
.then(function(emailResult){
return new Promise((resolve, reject) => {
setTimeout(function(){
return return mailer.sendEmail(req.user, 'secondEmail')
}, emailResult == 'ok' ? 60 * 60 * 1000 : 5 * 60 * 60 * 1000) // 1 hour or 5 hours
})
})
})


and seems to work but I have two main dubts:




  • If I restart the pm2 process of my application with (pm2 startOrReload prod.json), all the timeouts are cancelled?

  • If I have something like 600 timeouts scheduled with this system can I have any performance issues?


Any experience with something like this?







node.js express promise settimeout






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 19 '18 at 12:58









lellefood

127121




127121








  • 1




    You should probably consider some sort of dedicated queue for this, like kue.
    – robertklep
    Nov 19 '18 at 13:06










  • seems a good choice, thanks for the suggestion
    – lellefood
    Nov 19 '18 at 14:22










  • At the end I decided to use kue to manage jobs and delay them
    – lellefood
    Dec 4 '18 at 9:18














  • 1




    You should probably consider some sort of dedicated queue for this, like kue.
    – robertklep
    Nov 19 '18 at 13:06










  • seems a good choice, thanks for the suggestion
    – lellefood
    Nov 19 '18 at 14:22










  • At the end I decided to use kue to manage jobs and delay them
    – lellefood
    Dec 4 '18 at 9:18








1




1




You should probably consider some sort of dedicated queue for this, like kue.
– robertklep
Nov 19 '18 at 13:06




You should probably consider some sort of dedicated queue for this, like kue.
– robertklep
Nov 19 '18 at 13:06












seems a good choice, thanks for the suggestion
– lellefood
Nov 19 '18 at 14:22




seems a good choice, thanks for the suggestion
– lellefood
Nov 19 '18 at 14:22












At the end I decided to use kue to manage jobs and delay them
– lellefood
Dec 4 '18 at 9:18




At the end I decided to use kue to manage jobs and delay them
– lellefood
Dec 4 '18 at 9:18












3 Answers
3






active

oldest

votes


















1














Timeout like this might be a solution but not the very best kind.



If timeouts are instantly adding to your memory, like every hour, when you restart your Node.js process the timers yet to trigger are lost, and that means you can not restart your App even when you are trying to update the new code if you don't want to lose any of them. Losing emails or never restart, a little bit of confusion, right?



The most frequently implemented approach for such a case is Message Queue.
You can take Message Queue as timers that stored and consumed in a database, so you don't have to worry about whether timers are canceled or called multiple times when you don't want that happen.



RabbitMQ is a standalone MQ that is friendly to Node.js.



Kue is an MQ-like NPM package that relies on Redis.



Hope you like'em. ;)






share|improve this answer





























    1














    I already faced this issue.



    The solution I found is to use my database as the time register.
    Basically, if you are using SQL or Document oriented database:




    1. Insert a scheduled action into the database.

    2. Check every x seconds (depend on the accuracy you need) if there is an entry which need to be popped. If so, delete the item, take it, execute it.


    You could also use cron package to do the check, but... since this is simple to be implemented, you should do it by yourself.



    EDIT: Why this solution?



    First, this is RAM saver for server, when you have like 5000 entries, you don't have to store it in the memory.






    share|improve this answer





























      1















      • Yes all your timeout will be cancelled as they are memory stored

      • i don't think having 600 timeout might be an issue but you may find better suitable method like having an array with all your timeouts sorted and a setInterval to check if there's a need to execute something.






      share|improve this answer





















        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53375170%2ftrigger-function-with-a-delay-longer-than-an-hour-in-a-node-express-app%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        1














        Timeout like this might be a solution but not the very best kind.



        If timeouts are instantly adding to your memory, like every hour, when you restart your Node.js process the timers yet to trigger are lost, and that means you can not restart your App even when you are trying to update the new code if you don't want to lose any of them. Losing emails or never restart, a little bit of confusion, right?



        The most frequently implemented approach for such a case is Message Queue.
        You can take Message Queue as timers that stored and consumed in a database, so you don't have to worry about whether timers are canceled or called multiple times when you don't want that happen.



        RabbitMQ is a standalone MQ that is friendly to Node.js.



        Kue is an MQ-like NPM package that relies on Redis.



        Hope you like'em. ;)






        share|improve this answer


























          1














          Timeout like this might be a solution but not the very best kind.



          If timeouts are instantly adding to your memory, like every hour, when you restart your Node.js process the timers yet to trigger are lost, and that means you can not restart your App even when you are trying to update the new code if you don't want to lose any of them. Losing emails or never restart, a little bit of confusion, right?



          The most frequently implemented approach for such a case is Message Queue.
          You can take Message Queue as timers that stored and consumed in a database, so you don't have to worry about whether timers are canceled or called multiple times when you don't want that happen.



          RabbitMQ is a standalone MQ that is friendly to Node.js.



          Kue is an MQ-like NPM package that relies on Redis.



          Hope you like'em. ;)






          share|improve this answer
























            1












            1








            1






            Timeout like this might be a solution but not the very best kind.



            If timeouts are instantly adding to your memory, like every hour, when you restart your Node.js process the timers yet to trigger are lost, and that means you can not restart your App even when you are trying to update the new code if you don't want to lose any of them. Losing emails or never restart, a little bit of confusion, right?



            The most frequently implemented approach for such a case is Message Queue.
            You can take Message Queue as timers that stored and consumed in a database, so you don't have to worry about whether timers are canceled or called multiple times when you don't want that happen.



            RabbitMQ is a standalone MQ that is friendly to Node.js.



            Kue is an MQ-like NPM package that relies on Redis.



            Hope you like'em. ;)






            share|improve this answer












            Timeout like this might be a solution but not the very best kind.



            If timeouts are instantly adding to your memory, like every hour, when you restart your Node.js process the timers yet to trigger are lost, and that means you can not restart your App even when you are trying to update the new code if you don't want to lose any of them. Losing emails or never restart, a little bit of confusion, right?



            The most frequently implemented approach for such a case is Message Queue.
            You can take Message Queue as timers that stored and consumed in a database, so you don't have to worry about whether timers are canceled or called multiple times when you don't want that happen.



            RabbitMQ is a standalone MQ that is friendly to Node.js.



            Kue is an MQ-like NPM package that relies on Redis.



            Hope you like'em. ;)







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 19 '18 at 13:54









            YLS

            57038




            57038

























                1














                I already faced this issue.



                The solution I found is to use my database as the time register.
                Basically, if you are using SQL or Document oriented database:




                1. Insert a scheduled action into the database.

                2. Check every x seconds (depend on the accuracy you need) if there is an entry which need to be popped. If so, delete the item, take it, execute it.


                You could also use cron package to do the check, but... since this is simple to be implemented, you should do it by yourself.



                EDIT: Why this solution?



                First, this is RAM saver for server, when you have like 5000 entries, you don't have to store it in the memory.






                share|improve this answer


























                  1














                  I already faced this issue.



                  The solution I found is to use my database as the time register.
                  Basically, if you are using SQL or Document oriented database:




                  1. Insert a scheduled action into the database.

                  2. Check every x seconds (depend on the accuracy you need) if there is an entry which need to be popped. If so, delete the item, take it, execute it.


                  You could also use cron package to do the check, but... since this is simple to be implemented, you should do it by yourself.



                  EDIT: Why this solution?



                  First, this is RAM saver for server, when you have like 5000 entries, you don't have to store it in the memory.






                  share|improve this answer
























                    1












                    1








                    1






                    I already faced this issue.



                    The solution I found is to use my database as the time register.
                    Basically, if you are using SQL or Document oriented database:




                    1. Insert a scheduled action into the database.

                    2. Check every x seconds (depend on the accuracy you need) if there is an entry which need to be popped. If so, delete the item, take it, execute it.


                    You could also use cron package to do the check, but... since this is simple to be implemented, you should do it by yourself.



                    EDIT: Why this solution?



                    First, this is RAM saver for server, when you have like 5000 entries, you don't have to store it in the memory.






                    share|improve this answer












                    I already faced this issue.



                    The solution I found is to use my database as the time register.
                    Basically, if you are using SQL or Document oriented database:




                    1. Insert a scheduled action into the database.

                    2. Check every x seconds (depend on the accuracy you need) if there is an entry which need to be popped. If so, delete the item, take it, execute it.


                    You could also use cron package to do the check, but... since this is simple to be implemented, you should do it by yourself.



                    EDIT: Why this solution?



                    First, this is RAM saver for server, when you have like 5000 entries, you don't have to store it in the memory.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 19 '18 at 13:06









                    Izio

                    1949




                    1949























                        1















                        • Yes all your timeout will be cancelled as they are memory stored

                        • i don't think having 600 timeout might be an issue but you may find better suitable method like having an array with all your timeouts sorted and a setInterval to check if there's a need to execute something.






                        share|improve this answer


























                          1















                          • Yes all your timeout will be cancelled as they are memory stored

                          • i don't think having 600 timeout might be an issue but you may find better suitable method like having an array with all your timeouts sorted and a setInterval to check if there's a need to execute something.






                          share|improve this answer
























                            1












                            1








                            1







                            • Yes all your timeout will be cancelled as they are memory stored

                            • i don't think having 600 timeout might be an issue but you may find better suitable method like having an array with all your timeouts sorted and a setInterval to check if there's a need to execute something.






                            share|improve this answer













                            • Yes all your timeout will be cancelled as they are memory stored

                            • i don't think having 600 timeout might be an issue but you may find better suitable method like having an array with all your timeouts sorted and a setInterval to check if there's a need to execute something.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 19 '18 at 13:09









                            davidonet

                            574314




                            574314






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.





                                Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                Please pay close attention to the following guidance:


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53375170%2ftrigger-function-with-a-delay-longer-than-an-hour-in-a-node-express-app%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                MongoDB - Not Authorized To Execute Command

                                How to fix TextFormField cause rebuild widget in Flutter

                                in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith