interrogation avec delayed_job
J'ai un processus qui prend généralement quelques secondes pour terminer donc, je suis en train d'utiliser delayed_job pour gérer de manière asynchrone. Le travail en lui-même fonctionne très bien, ma question est de savoir comment aller à ce sujet de l'interrogation du travail pour savoir si c'est fait.
Je peux obtenir un id de delayed_job simplement de l'affecter à une variable:
travail = Disponible.retard.dosomething(:var => 1234)
+------+----------+----------+------------+------------+-------------+-----------+-----------+-----------+------------+-------------+
| id | priority | attempts | handler | last_error | run_at | locked_at | failed_at | locked_by | created_at | updated_at |
+------+----------+----------+------------+------------+-------------+-----------+-----------+-----------+------------+-------------+
| 4037 | 0 | 0 | --- !ru... | | 2011-04-... | | | | 2011-04... | 2011-04-... |
+------+----------+----------+------------+------------+-------------+-----------+-----------+-----------+------------+-------------+
Mais dès qu'il a terminé le travail, il le supprime et à la recherche pour les enregistrements renvoie une erreur:
@job=Delayed::Job.find(4037)
ActiveRecord::RecordNotFound: Couldn't find Delayed::Backend::ActiveRecord::Job with ID=4037
@job= Delayed::Job.exists?(params[:id])
Dois-je la peine de changer cela, et peut-être de reporter la suppression de dossiers complets? Je ne suis pas sûr de la façon que je peux obtenir une notification de son statut. Ou est l'interrogation d'une mort enregistrement comme preuve de l'accomplissement ok? Quelqu'un d'autre face à quelque chose de similaire?
- Un autre problème ou un obstacle, je fais face est, je suis à la compensation du travail parce qu'il est d'attacher mon serveur autrement. Je demande à la base de données si certaines données avec dates existent, s'ils ne sont pas ou ne sont pas à jour, j'extrais de nouvelles, mais comme une tâche distincte, j'utilise AJAX et j'sondage jusqu'à ce qu'il termine... et puis exécutez la requête pour les nouvelles données de nouveau. De le faire, espérons-le, plus rapide, mais aussi plus compliqué.
- Serait-il plus depuis utiliser quelque chose comme resque & redis et, essentiellement, le cache de l'objet retourné, épargne moi le supplément aller-retour à la DB et de rendre les bureaux plus vite? Je n'ai jamais touché redis ou resque, donc je pensais que je jette ce sort là.
Vous devez vous connecter pour publier un commentaire.
Commençons avec l'API. J'aimerais avoir quelque chose comme ce qui suit.
Maintenant, nous allons écrire le travail.
So far So good. Nous avons un emploi. Maintenant, nous allons écrire une logique qui place en file d'attente il. Depuis Disponible est le modèle de la responsable de ce travail, nous allons l'enseigner comment démarrer ce travail.
Alors, comment savons-nous si le travail est travail ou pas? Il y a un peu de moyens, mais dans les rails, il se sent juste raison, quand mon modèle crée quelque chose, il est généralement associé avec quelque chose. Comment pouvons-nous associer? L'utilisation d'identifiants dans la base de données. Nous allons ajouter un
job_id
sur les modèles Disponibles.Pendant que nous y sommes, comment savons-nous que le travail n'est pas de travail parce que c'est déjà fini, ou parce qu'il n'a pas commencé encore? Une façon est de vérifier pour ce que le travail fait. Si il a créé un fichier, vérifier si le fichier existe. Si elle calculée une valeur, vérifier que le résultat est écrit. Certains emplois ne sont pas faciles à vérifier si, puisqu'il peut ne pas être clair vérifiables résultat de leur travail. Dans de tels cas, vous pouvez utiliser un drapeau ou un timestamp dans votre modèle. En supposant que c'est notre cas, nous allons ajouter un
job_finished_at
horodatage de distinguer un pas encore couru travail à partir d'un déjà fini un.Bien. Alors maintenant, nous allons réellement associer
Available
avec son travail, dès que nous mettre en file d'attente le travail, par la modification de lastart_working!
méthode.Grande. À ce point, j'aurais pu écrire
belongs_to :job
, mais nous n'avons pas vraiment besoin de ça.Alors maintenant, nous savons comment écrire le
working?
méthode, si facile.Mais comment marquer le travail terminé? Personne ne connait un travail a fini de mieux que le travail lui-même. Donc, nous allons passer
available_id
dans le travail (comme l'une des options) et de l'utiliser dans le travail. Pour cela nous avons besoin de modifier lastart_working!
méthode pour transmettre l'id.Et il convient d'ajouter la logique dans le travail de mise à jour de notre
job_finished_at
horodatage quand c'est fait.Avec ce code à la place, nous savons comment écrire notre
finished?
méthode.Et nous y sommes. Maintenant, nous pouvons simplement sondage contre
@available.working?
et@available.finished?
Aussi, vous bénéficiez de la commodité de le savoir exact travail a été créé pour votre Disponible en vérifiant@available.job_id
. Vous pouvez facilement le transformer en véritable association en disantbelongs_to :job
.J'ai fini par utiliser une combinaison de Delayed_Job après(de travail) de rappel qui remplit un memcached objet avec le même ID que l'emploi créé. De cette façon, je minimiser le nombre de fois que j'ai frappé à la base de données de demander le statut de l'emploi, au lieu de l'interrogation du memcached objet. Et il contient la totalité de l'objet j'ai besoin de le travail terminé, donc je n'ai même pas un aller-retour de la demande. J'ai eu l'idée d'un article par le github gars qui fait à peu près la même chose.
https://github.com/blog/467-smart-js-polling
et utilisé un plugin jquery pour l'interrogation, ce qui les sondages, moins fréquemment, et après un certain nombre de tentatives
https://github.com/jeremyw/jquery-smart-poll
Semble fonctionner à merveille.
Je pense que le meilleur moyen serait d'utiliser les callbacks disponibles dans la delayed_job.
Ce sont:
:le succès, l' :erreur et :after.
ainsi, vous pouvez mettre un peu de code dans votre modèle avec le après:
Parce que si vous insistez de l'aide de l'obj.retardée.méthode, alors vous aurez à monkey patch Différés::PerformableMethod et ajouter le
after
méthode là.À mon humble avis c'est beaucoup mieux que l'interrogation de la valeur qui pourrait être encore backend spécifique (ActiveRecord vs Mongoid, par exemple).
La méthode la plus simple d'y parvenir est de changer votre interrogation sera quelque chose de semblable à la suivante:
Pourquoi ce travail? Lorsque
Delayed::Job
exécute un travail dans la file d'attente, il la supprime de la base de données en cas de succès. Si la tâche échoue, le dossier reste dans la file d'attente pour être couru de nouveau plus tard, et lelast_error
attribut est défini à l'erreur rencontrée. À l'aide de deux morceaux de la fonctionnalité ci-dessus, vous peut vérifier les enregistrements supprimés pour voir si ils ont réussi.Les avantages de la méthode ci-dessus sont:
Vous pouvez encapsuler cette fonctionnalité dans un modèle de méthode, en faisant quelque chose comme ce qui suit:
Je proposerais que s'il est important d'obtenir notification que le travail est terminé, puis d'écrire un personnalisé objet de la tâche et de la file d'attente que plutôt que de compter sur le travail par défaut qui obtient en file d'attente lorsque vous appelez
Available.delay.dosomething
. Créer un objet, quelque chose comme:et mettre en file d'attente avec:
La delayed_jobs table dans votre application est destinée à fournir de l'état d'exécution et les travaux en file d'attente seulement. Ce n'est pas une persistance de la table, et vraiment devrait être aussi petite que possible pour des raisons de performances. C'est pourquoi les emplois sont supprimés immédiatement après l'achèvement.
Au lieu de cela, vous devez ajouter un champ à votre
Available
modèle qui signifie que le travail est fait. Depuis que je suis généralement intéressés dans combien de temps le boulot nécessaire pour traiter, j'ajoute start_time et end_time champs. Puis mondosomething
méthode ressemblerait à quelque chose comme ceci:Le début! et finir! méthodes il vous suffit d'enregistrer l'heure actuelle et enregistrer le modèle. Ensuite, j'aurais une
completed?
méthode que votre AJAX sondage pour voir si le travail est terminé.Il y a beaucoup de façons de le faire, mais je trouve cette méthode simple et qui fonctionne bien pour moi.