2016-08-03 29 views
-1

[Diese Frage ist ziemlich vage, ich entschuldige mich dafür. Ich versuche, meine verschiedenen Probleme zu adressieren, indem ich die Frage selbst beantworte]Eine Node.js-App ordnungsgemäß ohne Expressgerüst aufbauen (die App erhält keine Anfragen)

Ich baue eine Node.js App, die verschiedene Aufgaben in bestimmten Intervallen ausführen muss. Hier wird die globale Gerüst (betrifft die drossel Versprechungen und Mungo für DB-Wechselwirkungen):

var Promise = require("bluebird"); 
 
var mongoose = require('mongoose'); 
 
mongoose.Promise = require('bluebird'); 
 

 
// Personal modules 
 
var bootApp = require(...); 
 
var doStuffA = require(...); 
 
var doStuffB = require(...); 
 
var doStuffC = require(...); 
 

 
// running locally, but meant to be deployed at some point 
 
mongoose.connect('mongodb://localhost:27017/myDatabase'); 
 
var db = mongoose.connection; 
 

 
db.on('error',() => { 
 
    console.log("Error : lost connection !")); 
 
    process.exit(1); 
 
}); 
 

 
db.once('open',() => { 
 
\t 
 
    bootApp() // always start by booting 
 
    .then(() => { // then start the infinite loop of events 
 

 
    setInterval(doStuffA, 1000*60*60); // 1x/1h 
 
    setInterval(doStuffB, 1000*60*10); // 1x/10min 
 
    setInterval(doStuffC, 1000*60*3); // 1x/3min 
 

 
    }).catch((e) => { // errors are handled by doStuffX(), so we should never catch anything here 
 
    console.log(e.message); 
 
    process.exit(1); 
 
    }); 
 
});

Jedes Modul doStuffX ist eine Funktion, ein Versprechen der Rückkehr, seine eigene Fehlerbehandlung und sollte irgendwann beenden .

erwartetes Verhalten für die gesamte App:

  • Die App sollte immer laufen können
  • Die App doStuffX() bei dem gegebenen Intervall versuchen sollte, unabhängig davon, ob es erfolgreich war oder zuletzt gescheitert.
  • [Optional:] Die App sollte reibungslos schließen, ohne eine doStuff bei Empfang eines "Herunterfahren" -Signals erneut zu versuchen.

Meine Frage: Wie baue ich ein sauberes Gerüst für eine solche App? Kann ich setInterval loswerden und stattdessen Versprechen verwenden? Eines meiner Hauptanliegen ist es, sicherzustellen, dass die vorherige Instanz von doStuffX() fertig ist, bevor die nächste gestartet wird, auch wenn es dazu führt, dass sie irgendwie "zerstört" wird.

Ich bin offen für jeden Link über Scaffolding-Apps, aber bitte geben Sie mir keine Antwort/LINK INVOLVING EXPRESS: Ich brauche nicht Express, da meine App keine Anfrage erhält. (Alles, was ich bisher gefunden beginnt mit Express: /)

+1

Warum würden Sie 'setInterval()' loswerden? Sie benötigen einen Timer, um wiederkehrende Funktionsaufrufe auszuführen. Es gibt keinen Ersatz für 'setInterval()' mit Versprechungen, da die beiden ziemlich unterschiedliche Tiere sind, so dass die ganze Anfrage nur fehlgeleitet klingt. – jfriend00

+1

Was ist los mit dem Gerüst, das Sie haben? Es sieht so aus, als würde es gut funktionieren. – jfriend00

+1

Sind Sie sicher, dass Sie den Prozess bei einem Datenbankfehler beenden möchten, wenn Sie erwarten, dass dies für immer ausgeführt wird? Sollten Sie nicht die Fehler protokollieren und sich vielleicht die Art der Fehler ansehen, um zu entscheiden, welche Maßnahme angemessen ist? – jfriend00

Antwort

1

Wenn Sie die nächste doStuffX() nicht starten möchten, bis die vorherige fertig ist, können Sie Ihre setInterval() durch wiederholte setTimeout() Anrufe ersetzen.

function runA() { 
    setTimeout(function() { 
     doStuffA().then(runA).catch(function(err) { 
      // decide what to do differently if doStuffA has an error 
     }); 
    }, 1000*60*60); 
} 

runA(); 

Sie auch ein Timeout dies so könnte hinzufügen, dass, wenn doStuffA() nicht innerhalb einer bestimmten Zeit nicht reagiert, dann nehmen Sie eine andere Aktion. Dies würde die Verwendung eines anderen Timers und eines Timeout-Flags beinhalten.

+0

Ich habe gerade über doStuffA() gefunden. Timeout (10000) .then ("was auch immer"). Wenn ich sage, doStuffX() handle seine Fehler, ist es wahr, aber ich hatte noch keine Möglichkeit gefunden, den Prozess zu stoppen, wenn es richtig läuft, aber zu viel Zeit braucht (ich kann es nicht alles erklären, aber es kann passieren .. .). Ich denke, ich bin fast da, muss mehr darüber lesen, was Sie mir bewusst gemacht haben –

+1

@ KLôN - '.timeout()' ist kein ES6-Standard-Versprechen Funktionen. Es wird von einigen Versprechen Bibliotheken unterstützt.Sie hätten eine viel bessere Antwort von mir erhalten, wenn Ihre Frage tatsächlich die Dinge enthalten würde, gegen die Sie sich wirklich schützen wollen. Nach einem besseren Gerüst zu fragen sagt uns nicht, was Sie wollen. – jfriend00

+0

Sie sind völlig richtig. Fakt ist: Ich habe eine sehr schlecht formulierte Frage gestellt, weil ich nicht begreifen konnte, was ich wirklich wollte! Trotz allem, was Sie vielleicht denken, haben Ihre Kommentare und Antworten mir sehr geholfen. Ich akzeptiere deine Antwort, die hilfreich war. Könnten Sie sich bitte etwas Zeit nehmen, um die Antwort zu lesen, die ich geschrieben habe, und mir sagen, ob der aktualisierte Code gut aussieht? Vielen Dank für Ihre Zeit und Hilfe! –

0

[ich meine eigene Frage beantworten, versuchen, hier alles zu setzen ich später geändert, falls jemand in diese Seite irgendwann fällt ...]

Für die Mongoose Teil des Gerüsts, hier ist das, was ich für eine zuverlässige langfristige DB-Verbindung so weit gekommen:

  • die Mongoose documentation gibt eine andere Art um den Fahrer zu gewährleisten, geben nie auf den Versuch mit reconnectTries
  • zu verbinden
  • Ich verstehe nicht wirklich socketOptions und keepalive, die zu Repliken scheinen, so lasse ich sie aus meinem Code für jetzt
  • Da Mongoose autoreconnect immer wenn etwas schief geht, werde ich die db.once('open') als den Zugriff auf die App-Code selbst, obwohl ich don Ich verstehe wirklich noch den Unterschied mit db.on('connected')
  • Ich empfehle this lesen.

var Promise = require("bluebird"); 
 
var mongoose = require('mongoose'); 
 
mongoose.Promise = require('bluebird'); 
 

 
// Personal modules 
 
var bootApp = require(...); 
 
var doStuffA = require(...); 
 
var doStuffB = require(...); 
 
var doStuffC = require(...); 
 

 
// running locally, but meant to be deployed at some point 
 
var uri = 'mongodb://localhost:27017/myDatabase'; 
 
// the added option makes sure the app will always try to reconnect... 
 
mongoose.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } }); 
 
var db = mongoose.connection; 
 

 
db.on('error',() => { 
 
    console.log("Error with Mongoose connection.")); 
 
}); 
 

 
db.once('open',() => { 
 
\t 
 
    bootApp() // always start by booting 
 
    .then(() => { // then start the infinite loop of events 
 

 
    ////////////////////////////////// 
 
    /// Here goes the actual stuff /// 
 
    ////////////////////////////////// 
 

 
    }).catch((e) => { // errors are handled by doStuffX(), so we should never catch anything here 
 
    console.log(e.message); 
 
    }); 
 
});

nun für die eigentlichen wiederholenden Sachen, ist mein Ziel, dass alles reibungslos läuft zu machen, und dass kein Prozess stecken bleibt.Über die von mir vorgenommenen Änderungen:

  • Die verwendeten Methoden sind nicht native ES6, sondern spezifisch für Bluebird. Sie können über .timeout() und .delay() lesen, die ich sehr nützlich für die Verkettung Timeouts und Intervalle in einem sauberen Code finden.
  • In meinen Augen sollte .then(runA, runA) immer eine eindeutige Instanz runA starten, aber ich bin besorgt, ob ich tatsächlich könnte am Ende zwei parallele Instanzen starten ...

// Instead of using setInterval in a bluebird promised environment... 
 

 
setInterval(doStuffA, 1000*60*60); // 1x/1h 
 

 
// I would have liked a full promise chain, but as jfriend00 stated, 
 
// It will end up crashing because the initial promise is never resolved... 
 

 
function runA() { 
 
    return doStuffA() 
 
    .timeout(1000*60*30) // kill the running instance if it takes longer than 30min 
 
    .delay(1000*60*60) // wait 60min 
 
    .then(runA, runA); // whatever the outcome, restart the process 
 
} 
 
runA(); 
 

 
// Therefore, a solution like jfriend00's seems like the way to go : 
 

 
function runA() { 
 
    setTimeout(function() { 
 
     doStuffA() 
 
     .timeout(1000*60*30) 
 
     .then(runA, runA) 
 
    }, 1000*60*60); 
 
} 
 
runA();

+0

Dies ist noch keine gültige Antwort. Antworten, die keinen eigentlichen Inhalt außer einem externen Link enthalten, sind hier nicht gültig. – jfriend00

+0

@ jfriend00: Aktualisierten Code und Zeug hinzugefügt. Hilft mir, den Gedankenprozess zu verfolgen; Ich hoffe, es könnte einem anderen irgendwann helfen. –

+1

Da Sie Ihre Versprechen unendlich verketten, frage ich mich, ob Sie ein Problem mit der Speicherakkumulation haben werden, da das ursprüngliche Versprechen vom ersten Aufruf von 'runA()' niemals gelöst wird, da es ständig auf ein verkettetes Ergebnis wartet. – jfriend00