简体   繁体   English

Node.js mongodb多个计划任务

[英]Node.js mongodb Multiple Scheduled Tasks

I have the following .js file, part of a node.js APP, and 2 questions. 我有以下.js文件,是node.js APP的一部分,还有2个问题。

var User = require('../app/models/user');   
var Agenda = require('agenda');

var mongoConnectionString = "mongodb://localhost/agenda";
var agenda = new Agenda({db: {address: mongoConnectionString}});


agenda.define('handle energy', function(job, done) {
    let lastUpdateRun = new Date(Date.now() - 50*1000); // 50 seconds ago for some buffer room


    /****** Energy Loss Per Minute ******/
    User.update( // Over 85 -> ~ 40 loss / hour
        {'local.energy' : { "$gt" : 85}, "local.energyUpdatedAt": {"$lt": lastUpdateRun}}, // query
        {"$inc": { "local.energy": -0.66 }, "local.energyUpdatedAt": new Date() } , // update
        {"multi": true}, // Options
        function(err, result) { // Callback
            if(err) {
                console.log(err)
            }
        }
    );
    User.update( // Over Under 80 -> ~ 25 loss / hour
        {'local.energy' : { "$gt": 50, "$lte" : 85 }, "local.energyUpdatedAt": {"$lt": lastUpdateRun}}, // query
        {"$inc": { "local.energy": -0.42 }, "local.energyUpdatedAt": new Date() } , // update
        {"multi": true}, // Options
        function(err, result) { // Callback
            if(err) {
                console.log(err)
            }
        }
    );
    User.update( // Under 50 -> ~ 15 loss / hour
        {'local.energy' : { "$gt": 25, "$lte" : 50}, "local.energyUpdatedAt": {"$lt": lastUpdateRun}}, // query
        {"$inc": { "local.energy": -0.25 }, "local.energyUpdatedAt": new Date() }, // update
        {"multi": true}, // Options
        function(err, result) { // Callback
            if(err) {
                console.log(err)
            }
        }
    );
    User.update( // Under 25 -> ~ 10 loss / hour
        {'local.energy' : { "$gt": 10, "$lte" : 25}, "$or" :[{'local.estate.owned.movedIn' : false}, {'local.estate.rented.movedIn' : false}], "local.energyUpdatedAt": {"$lt": lastUpdateRun} }, // query
        {"$inc": { "local.energy": -0.167 }, "local.energyUpdatedAt": new Date()} , // update
        {"multi": true}, // Options
        function(err, result) { // Callback
            if(err) {
                console.log(err)
            }
        }
    );  


    /******* Energy Gain Per Minute, No Office *******/

    User.update( // Set Energy to Ten if over 9.5 and under 10
        {'local.energy' : { "$lt": 10, "$gte" : 9.9}, "$or" : [{'local.estate.movedIn' : false}, {'local.estate.rented.movedIn' : false}], "local.energyUpdatedAt": {"$lt": lastUpdateRun}   }, // query
        {"$set": { "local.energy": 10 }, "local.energyUpdatedAt": new Date() } , // update
        {"multi": true}, // Options
        function(err, result) { // Callback
            if(err) {
                console.log(err)
            }
        }
    );  
    User.update( // Under 10 -> ~ 5 gain / hour
        {'local.energy' : { "$lt": 9.9}, "$or" : [{'local.estate.movedIn' : false}, {'local.estate.rented.movedIn' : false}], "local.energyUpdatedAt": {"$lt": lastUpdateRun}  }, // query
        {"$inc": { "local.energy": 0.085 }, "local.energyUpdatedAt": new Date() } , // update
        {"multi": true}, // Options
        function(err, result) { // Callback
            if(err) {
                console.log(err)
            }
        }
    );  


    /******* Energy Gain Per Minute, With Office *******/

    User.update( // Set Energy to 25 if over 24.5 and under 10
        {'local.energy' : { "$lt": 10, "$gte" : 24.5}, "$or" : [{'local.estate.movedIn' : true}, {'local.estate.rented.movedIn' : true}], "local.energyUpdatedAt": {"$lt": lastUpdateRun}   }, // query
        {"$set": { "local.energy": 10 }, "local.energyUpdatedAt": new Date() } , // update
        {"multi": true}, // Options
        function(err, result) { // Callback
            if(err) {
                console.log(err)
            }
        }
    );  
    User.update( // Under 25 -> ~ 15 gain / hour
        {'local.energy' : { "$lt": 24.5 } ,  "$or" : [{'local.estate.movedIn' : true}, {'local.estate.rented.movedIn' : true}], "local.energyUpdatedAt": {"$lt": lastUpdateRun}}, // query      
        {"$inc": { "local.energy": 0.250 }, "local.energyUpdatedAt": new Date() } , // update
        {"multi": true}, // Options
        function(err, result) { // Callback
            if(err) {
                console.log(err)
            }
        }
    );      

    done()
});


agenda.on('ready', function() {
    agenda.every('one minute', 'handle energy');
    agenda.start();
});



   // Handle Office Rent Expiration Every Hour
   //Handle A Few other things at different times

Question #1: Is there a better way to handle all those updates, I have quite a few updates in a short interval and I'm repeating 90% of the code over and over again. 问题1:是否有更好的方法来处理所有这些更新,我在很短的间隔内进行了很多更新,因此我会一遍又一遍地重复90%的代码。 Also performance wise is this the way to go or I'm doing a big mistake ? 还是性能明智的选择呢?还是我犯了个大错误?

Question #2: If I need more scheduled tasks 1 every hour and one every 25 minutes should I just create a setInterval for each of them, because iirc javascript doesn't handle multiple setIntervals. 问题2:如果我每小时需要更多计划任务,而每25分钟需要1个任务,那么我应该为每个任务创建一个setInterval,因为iirc javascript无法处理多个setIntervals。 So how should I handle it ? 那么我该如何处理呢?

PS I'm still learning node/js so don't hate me if these are dumb questions. PS我仍在学习node / js,因此如果这些问题很愚蠢,请不要讨厌我。 Thanks for you patience. 多谢您的耐心配合。

The updates are fine. 更新很好。 If they need to be done, they need to be done. 如果需要完成,就必须完成。 Given that they are running repetitively, just make sure you add a few compound indexes between local.energy and each of other fields you are querying by: 假设它们重复运行,只需确保在local.energy和要查询的每个其他字段之间添加一些复合索引local.energy

UserSchema.index({"local.energy": 1});
UserSchema.index({"local.energy": 1, "local.estate.owned.movedIn": 1});
UserSchema.index({"local.energy": 1, "local.estate.rented.movedIn": 1});
//etc.

The only thing I see that concerns me about the logic is that your updates are running in parallel with no restriction on duplicate updates. 我看到的唯一与逻辑有关的问题是您的更新并行运行,没有重复更新的限制。 Imagine you have a document: 假设您有一个文档:

DocA = {
    "local.energy": 9.85
}

Depending on order of execution within the two "Energy Gain/No Office" queries, you can have different results. 根据两个“能源收益/无办公室”查询中的执行顺序,您可以得到不同的结果。

The update querying by {"local.energy": {$lt: 9.9}} could increment DocA to 9.935. 通过{"local.energy": {$lt: 9.9}}查询的更新可能会将DocA递增到9.935。 Now it falls into the update querying by {"local.energy": {$gte: 9.9, $lt: 10}} , which will set it to 10 . 现在,它属于通过{"local.energy": {$gte: 9.9, $lt: 10}}的更新查询,它将设置为10 I'd recommend adding a "lastUpdatedAt": Date field to the schema (and indexes), and restricting your queries with it: 我建议向架构(和索引)添加一个"lastUpdatedAt": Date字段,并使用它限制查询:

let lastUpdateRun = new Date(Date.now() - 50*1000); // 50 seconds ago for some buffer room

User.update( // Over 85 -> ~ 40 loss / hour
    {'local.energy' : { "$gt" : 85}, "lastUpdatedAt": {"$lt": lastUpdateRun}}, // query
    {"$inc": { "local.energy": -0.66 }, "lastUpdatedAt": new Date()}, // update
    {"multi": true}, // Options
    function(err, result) { // Callback
        if(err) {
            console.log(err)
        }
    }
);

This way you'll only update ones that haven't been updated in this most recent interval. 这样,您将只更新在最近间隔中未更新的那些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM