A modern webes alkalmazások és szolgáltatások világában gyakran van szükség arra, hogy bizonyos feladatok automatikusan, előre meghatározott időközönként fussanak le. Gondoljunk csak adatbázis-tisztításra, jelentések generálására, e-mail értesítések kiküldésére, vagy épp külső API-k lekérdezésére. Ezeket a háttérfeladatokat ütemezni és megbízhatóan futtatni elengedhetetlen a robusztus és karbantartható rendszerekhez. A Node.js ökoszisztémája számos eszközt kínál erre, és az egyik legnépszerűbb és leginkább elterjedt megoldás a node-cron
modul.
Ez a cikk mélyrehatóan bemutatja, hogyan használhatjuk a node-cron
-t a feladatütemezés megvalósítására Node.js alkalmazásainkban. Megismerkedünk a telepítéstől kezdve a bonyolultabb ütemezési mintákig mindennel, ami ahhoz szükséges, hogy hatékonyan automatizáljuk ismétlődő feladatainkat.
Miért fontos a feladatütemezés?
A feladatütemezés (vagy angolul task scheduling) az alkalmazások egy alapvető képessége, amely lehetővé teszi, hogy a rendszer automatikusan hajtson végre bizonyos műveleteket felhasználói beavatkozás nélkül. Nézzünk néhány tipikus felhasználási esetet, ahol a Node.js és a node-cron
ragyogóan megállja a helyét:
- Adatbázis-karbantartás: Időszakos archiválás, régi adatok törlése, indexek optimalizálása.
- Jelentéskészítés: Napi, heti vagy havi statisztikai jelentések generálása és elküldése.
- E-mail és értesítési rendszerek: Időzíthető marketing e-mailek, emlékeztetők vagy rendszerüzenetek kiküldése.
- Adat szinkronizáció: Külső szolgáltatásokból származó adatok rendszeres frissítése vagy importálása.
- Cache érvénytelenítés: Elavult gyorsítótár bejegyzések törlése vagy frissítése.
- Rendszerellenőrzés: A szolgáltatások állapotának rendszeres ellenőrzése és riasztások küldése hiba esetén.
Ezen feladatok manuális végrehajtása nem csak időigényes, de hibalehetőségeket is rejt. Az automatizált ütemezés növeli a rendszer megbízhatóságát, hatékonyságát és csökkenti a manuális beavatkozás szükségességét.
A node-cron
bemutatása
A node-cron
egy népszerű Node.js modul, amely lehetővé teszi a Cron formátumú ütemezések definiálását és futtatását az alkalmazáson belül. A Cron egy szabványos Unix/Linux segédprogram, amelyet parancsok ütemezésére használnak, és a node-cron
ezt a jól ismert, rugalmas szintaxist hozza el a Node.js világába.
Főbb jellemzői:
- Egyszerű API: Könnyen használható és intuitív.
- Ismerős Cron szintaxis: Ha már ismeri a Cron-t, azonnal otthonosan fogja érezni magát.
- Könnyűsúlyú: Minimális függőségekkel rendelkezik, nem terheli le az alkalmazást.
- Aszinkron feladatok kezelése: Gond nélkül futtathatók aszinkron műveletek az ütemezett jobokban.
- Feladatok kezelése: Leállíthatók, elindíthatók és megsemmisíthetők a jobok futás közben.
Telepítés és Alapok
A node-cron
telepítése rendkívül egyszerű a Node.js csomagkezelőjével, az npm-mel:
npm install node-cron
A telepítés után máris elkezdhetjük használni. Íme egy alapvető „Hello World” példa, amely másodpercenként kiír egy üzenetet a konzolra:
// app.js
const cron = require('node-cron');
console.log('Alkalmazás elindult, ütemezés inicializálva...');
// Egy feladat ütemezése, ami minden másodpercben lefut
cron.schedule('* * * * * *', () => {
console.log('Ez a feladat minden másodpercben fut!');
});
// A fenti Cron szintaxis az alábbi mezőket jelöli:
// * * * * * *
// ┬ ┬ ┬ ┬ ┬ ┬
// │ │ │ │ │ │
// │ │ │ │ │ └─ másodperc (0 - 59)
// │ │ │ │ └─ perc (0 - 59)
// │ │ │ └─ óra (0 - 23)
// │ │ └─ a hónap napja (1 - 31)
// │ └─ hónap (1 - 12 vagy JAN-DEC)
// └─ a hét napja (0 - 7 vagy SUN-SAT, 0 és 7 is vasárnap)
Futtassuk a fenti kódot a node app.js
paranccsal, és látni fogjuk, ahogy a konzol másodpercenként kiírja az üzenetet.
A Cron Szintaxis Részletesen
A node-cron
a szabványos Cron szintaxist használja a feladatok ütemezésére. Ez általában öt, néha hat mezőből áll, amelyek mindegyike egy időegységet (másodperc, perc, óra, stb.) reprezentál. A node-cron
támogatja a hat mezős változatot, ahol az első mező a másodpercet jelöli.
A mezők sorrendje és értékhatárai:
- Másodperc (0-59)
- Perc (0-59)
- Óra (0-23)
- A hónap napja (1-31)
- Hónap (1-12 vagy JAN-DEC)
- A hét napja (0-7 vagy SUN-SAT, ahol 0 és 7 is vasárnap)
Speciális karakterek:
*
: Minden lehetséges értéket jelent. Pl.:*
a perc mezőben azt jelenti, hogy „minden percben”.,
: Felsorolás. Pl.:1,5,10
a perc mezőben azt jelenti, hogy „az 1., 5. és 10. percben”.-
: Tartomány. Pl.:9-17
az óra mezőben azt jelenti, hogy „9 órától 17 óráig”./
: Lépésköz. Pl.:*/5
a perc mezőben azt jelenti, hogy „minden 5. percben”.?
: Csak a „hónap napja” vagy a „hét napja” mezőben használható, ha nem akarjuk specifikálni az adott mező értékét (mert a másik már specifikálva van). Anode-cron
általában nem igényli, a*
használata elegendő.
Példák Cron ütemezésekre:
* * * * * *
: Minden másodpercben. (A legelső példánk)0 * * * * *
: Minden perc elején (azaz a 0. másodpercben).0 0 * * * *
: Minden óra elején (azaz 0 perc, 0 másodperc).0 30 9 * * *
: Minden nap 9:30:00-kor.0 0 0 * * *
: Minden nap éjfélkor.0 0 12 1 * *
: Minden hónap 1. napján, délben.0 0 10 * * 1-5
: Hétköznap (hétfőtől péntekig) minden nap 10:00:00-kor.0 0 0 */7 * *
: Minden 7. nap éjfélkor.0 0 0 * * SUN
: Minden vasárnap éjfélkor (a SUN, MON, stb. rövidítések is használhatók).
Feladatok Definiálása és Futtatása
A cron.schedule()
függvény két fő argumentumot vár:
- Az ütemezési sztring (Cron szintaxis).
- Egy függvény (callback), amely a futtatandó feladatot tartalmazza.
A callback függvénybe bármilyen Node.js kódot írhatunk, beleértve az aszinkron műveleteket is.
const cron = require('node-cron');
const axios = require('axios'); // Példa külső API híváshoz
// Egy szinkron feladat, ami minden percben lefut
cron.schedule('0 * * * * *', () => {
console.log(`[${new Date().toLocaleTimeString()}] Adatbázis-tisztítás elindult...`);
// Itt végezhetünk adatbázis-műveleteket, pl. régi session-ök törlése
console.log('Adatbázis-tisztítás befejeződött.');
});
// Egy aszinkron feladat, ami minden óra 5. percében lefut
cron.schedule('0 5 * * * *', async () => {
console.log(`[${new Date().toLocaleTimeString()}] Külső API lekérdezése indult...`);
try {
const response = await axios.get('https://api.example.com/data');
console.log('API adatok sikeresen lekérdezve:', response.data.length, 'byte.');
// Feldolgozzuk az adatokat
} catch (error) {
console.error('Hiba az API lekérdezésekor:', error.message);
}
});
// Egy feladat, ami csak egyszer fog lefutni a megadott időpontban
// Pl.: Ma 17:00:00-kor
const specificTime = new Date();
specificTime.setHours(17, 0, 0, 0); // Beállítjuk a mai nap 17:00:00-ra
// Ellenőrizzük, hogy a megadott idő még a jövőben van-e
if (specificTime > new Date()) {
const cronExpressionForSpecificTime = `${specificTime.getSeconds()} ${specificTime.getMinutes()} ${specificTime.getHours()} ${specificTime.getDate()} ${specificTime.getMonth() + 1} *`;
console.log(`Ütemezés beállítva ${specificTime.toLocaleTimeString()}-ra: "${cronExpressionForSpecificTime}"`);
cron.schedule(cronExpressionForSpecificTime, () => {
console.log(`[${new Date().toLocaleTimeString()}] Ez a feladat egyszer fut le, ma 17:00-kor.`);
// Ez a job csak egyszer fut le, utána leáll.
});
} else {
console.log('Az 17:00 órás ütemezés már elmúlt, kihagyva.');
}
console.log('Minden ütemezés beállítva. Az alkalmazás fut.');
Feladatok Kezelése (Stop, Start, Destroy)
Amikor a cron.schedule()
függvényt meghívjuk, az egy CronJob
objektumot ad vissza. Ezzel az objektummal tudjuk kontrollálni az ütemezett feladatot futás közben.
job.start()
: Elindítja az ütemezést. Alapértelmezetten a jobok a definíció után azonnal elindulnak. Ezt akkor használjuk, ha előzőleg leállítottuk.job.stop()
: Leállítja az ütemezést. A feladat nem fog többször lefutni, amíg újra el nem indítjuk.job.destroy()
: Teljesen megsemmisíti az ütemezést. Eltávolítja a schedulerből, és nem futtatható újra (csak ha újra létrehozzuk).
const cron = require('node-cron');
let jobCounter = 0;
const myJob = cron.schedule('*/2 * * * * *', () => { // Minden 2. másodpercben
jobCounter++;
console.log(`[${new Date().toLocaleTimeString()}] Feladat fut: ${jobCounter}. alkalom.`);
if (jobCounter === 5) {
console.log('5 futás után leállítjuk a feladatot...');
myJob.stop(); // Leállítja a feladatot
console.log('A feladat leállítva.');
}
});
setTimeout(() => {
if (myJob.getStatus() === 'stopped') { // A getStatus() egy nem hivatalos módszer, de néha hasznos
console.log('10 másodperc múlva újraindítjuk a feladatot...');
myJob.start(); // Újraindítja a feladatot
}
}, 10000);
setTimeout(() => {
console.log('20 másodperc múlva teljesen megsemmisítjük a feladatot.');
myJob.destroy(); // Megsemmisíti a feladatot
console.log('A feladat megsemmisítve. Többé nem fog futni.');
}, 20000);
Fontos megjegyezni, hogy a node-cron
alapértelmezetten a jobokat azonnal elindítja. Ha nem szeretnénk, hogy rögtön fussanak, megadhatjuk a { scheduled: false }
opciót:
const jobNotStartedYet = cron.schedule('* * * * * *', () => {
console.log('Ez a job nem indul el automatikusan.');
}, {
scheduled: false // Nem indul el azonnal
});
// Később, amikor akarjuk, elindíthatjuk:
// jobNotStartedYet.start();
Hiba Kezelés és Naplózás
A robusztus Node.js alkalmazások fejlesztésekor kiemelten fontos a hibakezelés és a naplózás. Ez különösen igaz az ütemezett háttérfeladatokra, amelyek felhasználói interakció nélkül futnak. Ha egy job hibásan fut le, azonnal tudnunk kell róla.
try-catch
blokkok: Mindig használjunktry-catch
blokkokat az aszinkron feladatok körül, hogy elkapjuk a lehetséges hibákat.- Naplózás (Logging): Használjunk egy dedikált naplózó könyvtárat (pl. Winston, Pino) a
console.log
helyett, amely lehetővé teszi a naplók szűrését, szintjeinek beállítását (info, warn, error) és fájlba vagy külső szolgáltatásba történő írását. - Értesítések: Komolyabb hibák esetén küldjünk értesítést (pl. e-mail, Slack, SMS) a fejlesztőknek.
const cron = require('node-cron');
const winston = require('winston'); // Egy népszerű naplózó modul
// Winston logger konfigurálása
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'cron.log' })
]
});
cron.schedule('*/10 * * * * *', async () => {
logger.info('Adatfeldolgozó feladat indult.');
try {
// Képzeljünk el egy műveletet, ami hibát dobhat
if (Math.random() < 0.2) { // 20% eséllyel hiba történik
throw new Error('Véletlen hiba történt az adatfeldolgozás során!');
}
// Valós feldolgozási logika
await new Promise(resolve => setTimeout(resolve, 1000)); // Szimulálunk egy aszinkron műveletet
logger.info('Adatfeldolgozó feladat sikeresen befejeződött.');
} catch (error) {
logger.error(`Adatfeldolgozó feladat hiba: ${error.message}`, { stack: error.stack });
// Itt küldhetünk értesítést is a fejlesztőknek
}
});
Gyakorlati Tippek és Megfontolások
- Hosszú ideig futó feladatok: Ha egy feladat tovább tart, mint az ütemezett intervallum, az problémákat okozhat (pl. több példány futása egyszerre). Fontoljuk meg a feladatok idempotenssé tételét, vagy használjunk mechanizmusokat (pl. mutex, Redis lock), hogy egy adott feladatból egyszerre csak egy példány fusson.
- Időzítés pontossága: A
node-cron
a Node.js processzen belül fut. Ha a Node.js processz leáll vagy újraindul, az ütemezések elvesznek (kivéve, ha újra definiáljuk őket az induláskor). A Cron nem garantálja a milliszekundumos pontosságot, de a másodperces/perces ütemezésekhez általában elegendő. - Moduláris felépítés: Különítsük el az egyes cron jobok logikáját saját modulokba. Ez növeli az olvashatóságot és a karbantarthatóságot.
- Környezeti változók: Az ütemezések konfigurációját (pl. intervallumok) célszerű környezeti változókon keresztül kezelni, hogy könnyen módosíthatók legyenek a különböző környezetekben (fejlesztés, staging, produkció).
- Időzónák: A
node-cron
alapértelmezetten a szerver időzónáját használja. Ha specifikus időzónában szeretnénk ütemezni, megadhatjuk atimezone
opciót:cron.schedule('0 0 9 * * *', () => { console.log('Ez a feladat reggel 9-kor fut, a megadott időzóna szerint.'); }, { timezone: "Europe/Budapest" // Példa Budapest időzónára });
- Tesztelés: Alaposan teszteljük az ütemezéseket, különösen a bonyolultabb Cron kifejezéseket. Használjunk valós idejű órákat (pl. crontab.guru) a Cron kifejezések ellenőrzésére.
Alternatívák és Mikor Válasszuk a node-cron
-t?
Bár a node-cron
egy kiváló eszköz, fontos tudni, hogy mikor érdemes más megoldás után nézni. Íme néhány alternatíva és a hozzájuk kapcsolódó forgatókönyvek:
node-schedule
: Egy másik népszerű Node.js ütemező, amely még rugalmasabb konfigurációs lehetőségeket kínál, például dátumobjektumokat vagy rekurzív szabályokat is elfogad a Cron szintaxis mellett. Kicsit komplexebb lehet, de nagyobb szabadságot ad.- Redis-alapú üzenetsorok (pl. BullMQ, Agenda): Elosztott rendszerekben, ahol a feladatok futását több szerver példányon keresztül kell koordinálni, vagy ha perzisztenciára, újrapróbálkozásokra, prioritásokra, vagy bonyolultabb munkafolyamatokra van szükség, egy üzenetsor rendszer sokkal jobb választás. Ezek robusztusabbak és hibatűrőbbek.
- Rendszerszintű Cron: Ha a Node.js alkalmazásunk csak egy háttérfolyamat, ami egy szkriptet futtat, gondolhatunk arra is, hogy a rendszerszintű Cron-t használjuk a szkript futtatásának ütemezésére (pl.
cron -e
Linuxon). Ez egyszerű lehet, de a feladatkezelés és a logolás szempontjából kevésbé integrált a Node.js alkalmazással. - Felhő alapú ütemezők (pl. AWS EventBridge, Google Cloud Scheduler): Szerver nélküli vagy felhő alapú architektúrákban gyakran érdemesebb a felhőszolgáltató által biztosított ütemezőket használni, amelyek skálázhatóbbak és integráltabbak a felhős infrastruktúrával.
Mikor válasszuk a node-cron
-t?
A node-cron
ideális választás a következő esetekben:
- Egyszerű, single-instance alkalmazások: Ha az alkalmazás egyetlen Node.js processzként fut, és nincs szükség elosztott feladatkezelésre.
- Ismerős Cron szintaxis: Ha a fejlesztőcsapat jártas a Cron szintaxisban, gyorsan és hatékonyan tudnak ütemezéseket létrehozni.
- Gyors beállítás: Amikor gyorsan szeretnénk bevezetni az ütemezési funkciókat minimális overhead-del.
- Kisebb és közepes projektek: Ahol a robusztus üzenetsor rendszerek bonyolultsága indokolatlan lenne.
Összefoglalás
A feladatütemezés kulcsfontosságú a modern, hatékony Node.js alkalmazásokban. A node-cron
modul egy kiváló, könnyen használható és rugalmas megoldást kínál az ismétlődő jobok futtatására, kihasználva a jól ismert Cron szintaxis erejét.
Legyen szó adatbázis-karbantartásról, jelentések generálásáról vagy külső rendszerek szinkronizálásáról, a node-cron
segítségével megbízhatóan automatizálhatja ezeket a műveleteket. A megfelelő hibakezeléssel, naplózással és moduláris felépítéssel robusztus és könnyen karbantartható Node.js háttérfeladatokat hozhatunk létre.
Ne habozzon beépíteni a node-cron
-t a következő Node.js projektjébe, és tapasztalja meg, milyen egyszerűvé teszi az automatizált feladatok kezelését!
Leave a Reply