Wissen

KNOW-HOW FÜR FORTSCHRITT

Im folgenden Artikel wird gezeigt, wie auch unter NodeJS professionell mit CronJobs gearbeitet werden kann. Dabei kommt das Node Module Agenda zum Einsatz.

Voraussetzung

Erfahrungen in folgenden Bereichen:

  • Aufbau einer NodeJS-App
  • Funktionsweise von CronJobs
  • Einrichtung und Verwendung von MongoDB

Agenda

Dieses NodeJS-Module bietet ein durchdachtes Werkzeug, um CronJobs flexibel zu verwalten und zu gruppieren. Der große Vorteil liegt vor allem darin, dass erstellte Jobs auch nach einem App-Neustart oder Server-Crash nicht verloren gehen, wofür jedoch MongoDB benötigt wird. Wie der Name schon sagt, ist hier ein CronJob als eine Art Agenda zu verstehen, die abgearbeitet wird. Dabei kann folgendes Vorgehensweise genutzt werden:

  1. Agenda-Instanz: Konfiguration
  2. Agenda: Definition
  3. Job: Erstellen
  4. Agenda-Instanz: Ausführung starten

Es können sogenannte Jobs zu einer Agenda erstellt werden, die dann anhand der Agenda-Definition ausgeführt werden.

Installation

Wie alle NodeJS Module kann auch Agenda schnell und einfach über npm installiert werden.

npm install agenda

Agenda-Instanz: Konfiguration

Damit mit Agenda gearbeitet werden kann, muss es in einer NodeJS App geladen werden.

var Agenda = require('agenda');

Mit der Erzeugung einer Agenda-Instanz sollten auch die MongoDB-Verbindungsdaten übergeben werden. Zusätzlich können auch Standardkonfigurationen überschrieben und ein Name übergeben werden.

var Agenda = require('agenda'),
agenda = new Agenda({
name: 'Name',
db: {
address: 'MongoDBAdresse/DatenbankName'
}
});

Im Normalfall heißt die MongoDB-Collection für Agenda „agendaJobs“, welche jedoch auch durch einen eigenen Namen ersetzt werden kann.

var Agenda = require('agenda'),
agenda = new Agenda({
name: 'Name',
db: {
address: 'MongoDBAdresse/DatenbankName',
collection: 'CollectionName'
}
});

Eine kürze Schreibweise dafür wird auch angeboten.

var agenda = new Agenda();
agenda.database('MongoDBAdresse/DatabaseName', 'CollectionName');

Achtung Stolperstein Wer seinen Mongo-Prozess mit dem „–auth“ Parameter startet, muss natürlich auch bei der Erzeugung der Agenda-Instanz die Zugangs-Daten mitschicken. Leider findet man nur recht mühselig heraus, dass auch die Benutzer-Datenbank gesetzt werden muss! Die Standard-Benutzerdatenbank von MongoDB ist „admin„.

var Agenda = require('agenda'),
agenda = new Agenda({
name: 'Name',
db: {
address: 'BenutzerName:Password@MongoDBAdresse/DatenbankName?authSource=admin',
collection: 'CollectionName'
}
});

Weitere überschreibbare Optionen können auf der GitHub-Seite nachgelesen werden.

Agenda: Definition

Kurz und schmerzlos zeigt die Überschrift schon, wie eine Agenda definiert wird.

// Asynchron
agenda.define('agendaName', function (job, done) {
// Man erhält beim Ausführen der Agenda das jeweilige Job Objekt
// done() - ist eine Funktion, um die asynchrone Ausführung zu beenden
tueEtwas(function () {
done();
});
});
//Synchron
agenda.define('agendaName', function (job) {
// Man erhält beim Ausführen der Agenda das jeweilige Job Objekt
// Hier könnte etwas stehen
});

Eine Agenda ist also eine Kombination aus einem Namen und einer Funktion, die ausgeführt wird, falls es einen Job für diese Agenda gibt.

Job: Erstellen

Ein Job kann implizit oder explizit erzeugt werden. implizit Es gibt folgende Funktionen, um implizit einen Job anzulegen.

  • agenda.every – erzeugt alle XXX einen neuen Job und führt die Agenda Definition dafür aus
  • agenda.schedule – erzeugt nur einen Job, der zu einem festgelegten Zeitpunkt ausgeführt wird
  • agenda.now – erzeugt jetzt einen Job zur Agenda und führt ihn aus

Alle drei Methoden werden mit zwei Pflicht und einem optionalen Parameter aufgerufen.

agenda.schedule(WANN, WAS, data);
// WANN = in CronJob Schreibweise (* * * *) oder als aussagekräftiger String ('tomorrow at noon', 'in 15 minutes')
// WO = Agenda-Definition
// data = optionale/zusätzliche Daten in einem Javascript Objekt

Auf Data kann dann einfach über job.attrs.data zugegriffen werden. explizit Über die Methode agenda.create kann explizit ein Job angelegt werden. Alle Änderungen an diesem Job werden aber nicht automatisch in der Datenbank gespeichert. Die Änderungen müssen über job.save manuell gesichert werden.

var job = agenda.create('Agenda-Definition', data);
job.save(function (err) {
// optionaler Callback
});

Wann dieser Job ausgeführt wird, kann wieder über verschiedene Funktionen gesteuert werden.

  • job.repeatEvery: führt den Job im angegebenen Intervall aus
  • job.repeatAt: führt den Job immer am angegebenen Zeitpunkt aus
  • job.schedule: führt den Job nur einmal zum angegebenen Zeitpunkt aus
  • job.run: führt den Job jetzt aus

Agenda-Instanz: Ausführung starten

Auch das geschieht recht einfach: agenda.start(); Genauso einfach kann die Ausführung auch beendet werden: agenda.stop();

Suchen und Finden von Jobs

Natürlich ist es auch sehr sinnvoll in der Datenbank bestehende Jobs durchsuchen zu können. Da im Hintergrund MongoDB läuft, ist dies elegant möglich.

agenda.jobs({name: 'Agenda-Definition'}, function (err, jobs) {
// err -> Error-Objekt falls die Datenbankabfrage fehlgeschlagen ist
// jobs -> Liste von gefundenen Jobs
});

Löschen von Jobs

Das löschen ist ähnlich dem MongoDB-Befehl „remove„.

agenda.cancel({name: 'Agenda-Definition'}, function (err, numOfRemoved) {
// err -> Error-Objekt falls die Datenbankabfrage fehlgeschlagen ist
// numOfRemoved -> Anzahl entfernter Jobs
});

Es können allerdings auch einzelene Jobs gelöscht werden. Dies bietet sich an, wenn man mehrere Jobs zu einer Agenda-Definition erstellt hat, aber nur Jobs mit bestimmten zusätzlichen Daten löschen will (jobs.attrs.data).

job.remove(function (err) {
// err -> Error-Objekt, wenn die Datenabfrage fehlgeschlagen ist
});

Fazit

Agenda bietet einen sehr produktiven und modularen Ansatz zur Umsetzung von CronJobs oder Schedulern mit NodeJS. Über die im Artikel beschrieben Funktionen hinaus besitzt Agenda auch ein ausgereiftes Event-System und unterstützt Clustering, sowie konkurrierende Job-Ausführungen.

Wir freuen uns über eine Bewertung, um ein Feedback zu erhalten:

Durchschnittlich 4 Sterne aus 6 Meinungen.