2016-06-03 7 views
0

Ich habe die folgende .js-Datei, Teil einer node.js APP und 2 Fragen.Node.js mongodb Mehrere geplante Aufgaben

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 

Frage 1: Gibt es einen besseren Weg, um all diese Aktualisierungen zu handhaben, ich habe ziemlich viele Updates in einem kurzen Zeitraum, und ich bin 90% des Codes immer und immer wieder zu wiederholen. Auch leistungsmäßig ist das der richtige Weg oder ich mache einen großen Fehler?

Frage # 2: Wenn ich mehr geplante Aufgaben 1 jede Stunde und alle 25 Minuten brauche, sollte ich nur eine setInterval für jede von ihnen erstellen, weil IIRC Javascript nicht mehrere setIntervals behandelt. Wie soll ich damit umgehen?

P.S. Ich lerne immer noch Knoten/js, also hasst mich nicht, wenn das dumme Fragen sind. Danke für deine Geduld.

+1

für die Planung wiederholende Aufgaben, empfehle ich die Verwendung von [agenda] (https://github.com/rschmukler/agenda) – cdbajorin

Antwort

2

Die Updates sind in Ordnung. Wenn sie getan werden müssen, müssen sie getan werden. Da sie wiederholt, so stellen Sie sicher, dass Sie fügen Sie ein paar zusammengesetzte Indizes zwischen local.energy und jeder der anderen Felder, die Sie ausgeführt werden, werden die Abfrage von:

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. 

Das ich nur noch sehen, dass mir Sorgen über die Logik, dass die Updates ist laufen parallel ohne Beschränkung auf doppelte Updates. Stellen Sie sich vor Sie ein Dokument haben:

DocA = { 
    "local.energy": 9.85 
} 

Je nach Reihenfolge der Ausführung innerhalb der beiden „Energiegewinn/No Büro“ Abfragen können Sie unterschiedliche Ergebnisse haben.

Die Aktualisierungsabfrage von {"local.energy": {$lt: 9.9}} konnte DocA auf 9.935 erhöhen. Jetzt fällt es in die Update-Abfrage von {"local.energy": {$gte: 9.9, $lt: 10}}, die es auf 10 setzen wird. Ich würde empfehlen, das Hinzufügen eines "lastUpdatedAt": Date Feld auf das Schema (und Indizes) und Ihre Fragen mit ihm zu beschränken:

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) 
     } 
    } 
); 

Auf diese Weise können nur aktualisiert werden diejenigen, die nicht in diesem letzten Intervall aktualisiert haben.

+0

Danke, ein "lastUpdatedAt" hinzufügen: Datum Feld ist ein guter Rat wird das implementieren. Auch wenn es kein großes Problem ist, mag ich Dinge, die richtig funktionieren. – Trax

+0

Aus irgendeinem Grund konnte ich "lastUpdatedAt" nicht verwenden: new Date(), wegen einer Fehlermeldung: '\' $ set \ 'ist leer. Sie müssen ein Feld wie folgt angeben: {$ mod: {: ...}} ',. Wie auch immer ich herausgefunden habe, ich kann timeamps Option zu user.schema hinzufügen, und aktualisiert automatisch ein Feld namens updatedAt, wenn ein Feld aktualisiert wird. – Trax

+0

Das Zeitstempel-Plugin "updatedAt" wird nur beim Speichern, nicht beim Aktualisieren ausgeführt, sodass das Datum bei jedem Update nicht erhöht wird. Sie brauchen tatsächlich nicht einmal $ set, da mongoose es automatisch für Sie konvertiert. Das könnte das Problem sein. Ich gebe es nie ein, ich bin mir nicht sicher, warum ich das in der Antwort getan habe. Ich habe aktualisiert, wie ich es normalerweise verwenden würde. – cdbajorin