Μετάβαση στο περιεχόμενο

Ορισμός εργασιών

Μια εργασία έχει ένα όνομα, ένα πρόγραμμα και έναν handler. Υπάρχουν τρία είδη προγραμματισμού, το καθένα με τη δική του μέθοδο. Και οι τρεις επιστρέφουν τον scheduler, επιτρέποντας την αλυσιδωτή κλήση τους (chaining).

scheduler
.every('sync', '10s', syncCustomers) // ένα μεσοδιάστημα
.cron('digest', '0 8 * * 1-5', sendDigest) // μια έκφραση cron
.at('launch', '2026-12-01T09:00:00Z', announce); // μία φορά
scheduler.every(name, interval, handler, options?)

Το μεσοδιάστημα (interval) είναι ένας αριθμός χιλιοστών του δευτερολέπτου (milliseconds) ή ένα string διάρκειας.

Γράφεται ως Σημαίνει
10_000 10 δευτερόλεπτα
'10s' 10 δευτερόλεπτα
'35m' 35 λεπτά
'1h30m' 1 ώρα και 30 λεπτά
'2d' 2 ημέρες
'1.5h' 1 ώρα και 30 λεπτά

Οι μονάδες μέτρησης είναι ms, s, m, h και d. Το μικρότερο δυνατό μεσοδιάστημα είναι 1 δευτερόλεπτο.

Οι εκτελέσεις τοποθετούνται σε ένα σταθερό πλέγμα

Ενότητα με τίτλο «Οι εκτελέσεις τοποθετούνται σε ένα σταθερό πλέγμα»

Το every('10s') δεν σημαίνει «10 δευτερόλεπτα μετά την εκκίνηση της διεργασίας». Σημαίνει κάθε πολλαπλάσιο των 10 δευτερολέπτων μετρώντας από 1970-01-01 UTC: :00, :10, :20 και ούτω καθεξής.

Αυτό είναι σημαντικό για δύο λόγους:

  • Κάθε instance υπολογίζει τις ίδιες χρονικές στιγμές, ανεξάρτητα από το πότε ξεκίνησε. Αυτό είναι που τους επιτρέπει να ανταγωνίζονται για την ίδια εκτέλεση.
  • Μια επανεκκίνηση δεν μετατοπίζει το πρόγραμμα.
every('10s') 12:00:00 12:00:10 12:00:20 12:00:30
every('1h') 12:00:00 13:00:00 14:00:00
every('1d') 00:00:00 UTC κάθε μέρα

Δύο ωριαίες εργασίες θα ξεκινούσαν και οι δύο στην αρχή της ώρας. Το offsetMs μετατοπίζει μία από αυτές:

scheduler.every('rates', '1h', fetchRates); // 12:00, 13:00, ...
scheduler.every('invoices', '1h', buildInvoices, { offsetMs: 30 * 60_000 }); // 12:30, 13:30, ...

Το offset πρέπει να είναι το ίδιο σε κάθε instance.

scheduler.cron(name, expression, handler, options?)

Μια έκφραση cron έχει πέντε πεδία, ή έξι όταν το πρώτο πεδίο είναι δευτερόλεπτα:

┌──────── δευτερόλεπτο (προαιρετικό, 0-59)
│ ┌────── λεπτό (0-59)
│ │ ┌──── ώρα (0-23)
│ │ │ ┌── ημέρα του μήνα (1-31)
│ │ │ │ ┌ μήνας (1-12)
│ │ │ │ │ ┌ ημέρα της εβδομάδας (0-7, η Κυριακή είναι 0 ή 7)
* * * * * *
Έκφραση Εκτελείται
0 8 * * 1-5 08:00, Δευτέρα έως Παρασκευή
30 3 * * * 03:30 κάθε μέρα
0 */2 * * * Κάθε 2 ώρες, στην αρχή της ώρας
0 0 1 * * Μεσάνυχτα την 1η κάθε μήνα
*/15 * * * * * Κάθε 15 δευτερόλεπτα (έξι πεδία)

Η ανάλυση των εκφράσεων γίνεται από το croner, επομένως ισχύει η σύνταξή του.

Από προεπιλογή, μια έκφραση cron διαβάζεται στην τοπική ζώνη ώρας του διακομιστή. Αυτό μπορεί να διαφέρει μεταξύ των μηχανημάτων, οπότε ορίστε το ρητά:

// Ανά εργασία
scheduler.cron('open-market', '30 9 * * 1-5', open, { timezone: 'America/New_York' });
// Ή μία φορά για όλες τις εργασίες cron
const scheduler = new Scheduler({ timezone: 'Europe/Athens' });

Χρησιμοποιήστε ονόματα IANA όπως Europe/Athens ή UTC. Οι αλλαγές θερινής/χειμερινής ώρας διαχειρίζονται από τη βιβλιοθήκη cron: η ώρα «08:00 ώρα Αθήνας» παραμένει 08:00 τοπική ώρα όλο το χρόνο.

scheduler.at(name, when, handler, options?)

Εκτελείται μία φορά, σε ένα instance. Το when είναι ένα Date, χιλιοστά του δευτερολέπτου από το 1970, ή ένα ISO string:

scheduler.at('launch', '2026-12-01T09:00:00Z', announce);
scheduler.at('reminder', new Date(Date.now() + 60 * 60_000), remind); // σε μία ώρα
scheduler.at('cutover', 1796115600000, cutOver);

Κάθε instance καταχωρίζει την εργασία, και ένα από αυτά την εκτελεί, όπως συμβαίνει με οποιαδήποτε άλλη εκτέλεση.

Μια εφάπαξ εργασία της οποίας η ώρα έχει ήδη παρέλθει δεν εκτελείται όταν την καταχωρίζετε, με μία εξαίρεση: σε ένα backend μίσθωσης (lease backend), αν η εκτέλεσή της αναμενόταν πριν από λιγότερο από catchUpMs (5 λεπτά από προεπιλογή) και κανένα instance δεν την εκτέλεσε, το πρώτο instance που θα εκκινήσει την εκτελεί. Αυτός είναι ο ίδιος κανόνας ανάκτησης (catch-up) όπως και για τις υπόλοιπες εργασίες.

  • Πρέπει να είναι μοναδικά μέσα σε έναν scheduler. Η καταχώριση του ίδιου ονόματος δύο φορές προκαλεί σφάλμα (throws).
  • Το όνομα αποτελεί μέρος των κλειδιών ή των εγγραφών στο store. Η μετονομασία μιας εργασίας ξεκινά ένα νέο ιστορικό.
  • Στο RabbitMQ και στο NATS, τα ονόματα επιτρέπεται να περιέχουν μόνο γράμματα, ψηφία, _ και -, επειδή μετατρέπονται σε ονόματα ουρών (queue names) και subjects.

Προσθήκη και αφαίρεση εργασιών κατά τον χρόνο εκτέλεσης

Ενότητα με τίτλο «Προσθήκη και αφαίρεση εργασιών κατά τον χρόνο εκτέλεσης»

Οι εργασίες μπορούν να προστεθούν πριν ή μετά το start().

await scheduler.start();
scheduler.every('late-addition', '1m', work); // προγραμματίζεται αμέσως

Η μέθοδος remove(name) σταματά τον προγραμματισμό μιας εργασίας σε αυτό το instance. Επιστρέφει false αν δεν υπάρχει τέτοια εργασία.

scheduler.remove('sync');
scheduler.every('sync', '30s', syncCustomers); // το ίδιο όνομα με νέο πρόγραμμα

Η αφαίρεση μιας εργασίας επηρεάζει μόνο αυτό το instance. Τα υπόλοιπα instances συνεχίζουν να την εκτελούν, το ιστορικό της διατηρείται, και μια εκτέλεση που βρίσκεται ήδη σε εξέλιξη εδώ ολοκληρώνεται κανονικά.

Θέλετε Χρησιμοποιήστε
«Κάθε N δευτερόλεπτα/λεπτά/ώρες», η ώρα της ημέρας δεν έχει σημασία every()
Μια συγκεκριμένη ώρα ρολογιού, καθημερινές ή συγκεκριμένη ζώνη ώρας cron()
Κάτι που συμβαίνει μία μόνο φορά at()