Ma situation …
J’ai un ensemble de travailleurs qui doivent être exécutés périodiquement, chacun à des intervalles différents, et j’aimerais trouver une bonne implémentation pour gérer leur exécution.
Exemple: supposons qu’un ouvrier se rende au magasin et m’achète du lait une fois par semaine. Je voudrais stocker ce travail et sa configuration dans une table mysql. Cependant, il semble être une très mauvaise idée de consulter la table (toutes les secondes?) Et de voir quels travaux sont prêts à être placés dans le pipeline d’exécution.
Tous mes travailleurs sont écrits en javascript, j’utilise donc node.js pour l’exécution et beanstalkd en tant que pipeline.
Si de nouveaux travaux (par exemple, la planification de l’exécution d’un travailleur à une heure donnée) sont créés de manière asynchrone et que je dois stocker le résultat du travail et la configuration de manière permanente, comment puis-je éviter d’interroger une table?
Merci!
Je conviens que cela semble inélégant, mais compte tenu de la façon dont les ordinateurs fonctionnent, quelque chose * quelque part * va devoir procéder à des sondages afin de déterminer les tâches à exécuter quand. Alors, passons en revue certaines de vos options:
Interrogez la table de firebase database. Ce n’est pas une mauvaise idée du tout. C’est probablement l’option la plus simple si vous stockez les travaux dans MySQL. Un taux d’une requête par seconde n’est rien. Essayez-le et vous remarquerez que votre système ne le sent même pas.
Quelques idées pour vous aider à réduire ce nombre à éventuellement des centaines de requêtes par seconde, ou tout simplement à réduire les besoins en ressources système:
Si vous devez redimensionner davantage, conservez la table principale des travaux dans la firebase database et utilisez la deuxième plus petite table que je suggère, mettez cette table dans la RAM: sous forme de table mémoire dans le moteur de firebase database ou dans une file genre dans votre programme. Si vous en avez également, interrogez la queue à intervalles extrêmement rapprochés – il faudra des cas d’utilisation extrêmes pour causer des problèmes de performances ici.
Le principal problème de cette option est que vous devez garder une trace des tâches en mémoire qui n’ont pas été exécutées, par exemple en raison d’une panne système – plus de code pour vous …
Créez un thread pour chacune des tâches (par exemple, toutes les tâches devant être exécutées dans la minute qui suit) et appelez thread.sleep (millis_until_execution_time) (ou peu importe, je ne connais pas très bien node.js).
Cette option a le même problème que non. 2 – où vous devez suivre l’exécution des travaux pour la reprise sur incident. C’est aussi l’imo qui génère le plus de gaspillage – chaque thread de travail en veille nécessite toujours des ressources système.
Bien sûr, il peut y avoir des options supplémentaires – j’espère que d’autres répondront avec plus d’idées.
Il suffit de réaliser que l’interrogation de la firebase database toutes les secondes n’est pas une mauvaise idée. C’est le moyen le plus simple imo (souvenez-vous de KISS), et à ce rythme, vous ne devriez pas avoir de problèmes de performances, évitez donc les optimisations prématurées.
Pourquoi ne pas avoir un object Job
dans node.js qui soit enregistré dans la firebase database.
var Job = { id: long, task: Ssortingng, configuration: JSON, dueDate: Date, finished: bit };
Je suggérerais que vous stockiez uniquement l’identifiant dans la RAM et que vous laissiez toutes les autres données de Job
dans la firebase database. Lorsque votre fonction timeout est .id
il suffit de connaître le .id
pour obtenir les autres données.
var job = createJob(...); // create from async data somewhere. job.save(); // save the job. var id = job.id // only store the id in RAM // ask the job to be run in the future. setTimeout(Date.now - job.dueDate, function() { // load the job when you want to run it db.load(id, function(job) { // run it. run(job); // mark as finished job.finished = true; // save your finished = true state job.save(); }); }); // remove job from RAM now. job = null;
Si le serveur se bloque, tout ce que vous avez à faire est d’interroger tous les travaux comportant [finished=false]
, de les charger dans la RAM et de relancer setTimeouts.
Si quelque chose ne va pas, vous devriez pouvoir redémarrer proprement comme ceci:
db.find("job", { finished: false }, function(jobs) { each(jobs, function(job) { var id = job.id; setTimeout(Date.now - job.dueDate, function() { // load the job when you want to run it db.load(id, function(job) { // run it. run(job); // mark as finished job.finished = true; // save your finished = true state job.save(); }); }); job = null; }); });