Comment vérifier si une tâche est en cours d'exécution dans le céleri (en particulier, j'utilise céleri-Django)?
J'ai lu la documentation et j'ai cherché sur Google, mais je ne vois pas d'appel comme:
my_example_task.state() == RUNNING
Mon cas d'utilisation est que je dispose d'un service externe (Java) pour le transcodage. Lorsque j'envoie un document à transcoder, je souhaite vérifier si la tâche qui exécute ce service est en cours d'exécution et, dans le cas contraire, le (re) le démarrer.
J'utilise les versions stables actuelles - 2.4, je crois.
Chaque objet Task
a une propriété .request
, qui le contient AsyncRequest
. En conséquence, la ligne suivante donne l'état d'une tâche task
:
task.AsyncResult(task.request.id).state
Renvoie le task_id (qui provient de .delay ()) et interroge l'instance du céleri après sur l'état:
x = method.delay(1,2)
print x.task_id
Lorsque vous le demandez, obtenez un nouveau AsyncResult en utilisant cet ID_tâche:
from celery.result import AsyncResult
res = AsyncResult("your-task-id")
res.ready()
La création d'un objet AsyncResult
à partir de l'identifiant de tâche est recommandée dans le FAQ pour obtenir le statut de la tâche lorsque vous ne disposez que de l'identifiant de la tâche.
Cependant, à partir de Celery 3.x, il existe des réserves importantes qui pourraient piquer les gens s’ils ne leur prêtent pas attention. Cela dépend vraiment du scénario d'utilisation.
Pour que Celery puisse enregistrer qu'une tâche est en cours d'exécution, vous devez définir task_track_started
sur True
. Voici une tâche simple qui teste ceci:
@app.task(bind=True)
def test(self):
print self.AsyncResult(self.request.id).state
Lorsque task_track_started
est False
, la valeur par défaut, l'état d'affichage est PENDING
même si la tâche a démarré. Si vous définissez task_track_started
sur True
, l'état sera STARTED
.
PENDING
signifie "je ne sais pas".Une AsyncResult
avec l'état PENDING
ne veut rien dire de plus que Celery ne connaît pas le statut de la tâche. Cela pourrait être dû à un certain nombre de raisons.
D'une part, AsyncResult
peut être construit avec des identifiants de tâches non valides. Ces tâches seront considérées comme en suspens par le céleri:
>>> task.AsyncResult("invalid").status
'PENDING'
Ok, donc personne ne va alimenter évidemment identifiants invalides à AsyncResult
. Assez bien, mais cela a également pour effet que AsyncResult
considérera également une tâche exécutée avec succès mais que Celery a oublié comme étant PENDING
. Encore une fois, dans certains scénarios de cas d'utilisation un problème. Une partie du problème repose sur la façon dont Celery est configuré pour conserver les résultats des tâches, car cela dépend de la disponibilité des "pierres tombales" dans le backend des résultats. ("Tombstones" est le terme utilisé dans la documentation de Celery pour désigner les fragments de données qui enregistrent le déroulement de la tâche.) Utiliser AsyncResult
ne fonctionnera pas du tout si task_ignore_result
est True
. Un problème plus épineux est que Celery expire les pierres tombales par défaut. Le paramètre result_expires
par défaut est défini sur 24 heures. Ainsi, si vous lancez une tâche et enregistrez l'ID dans la mémoire de stockage à long terme, et plus de 24 heures plus tard, vous créez une AsyncResult
avec elle, le statut sera PENDING
.
Toutes les "tâches réelles" commencent dans l'état PENDING
. Donc, obtenir PENDING
sur une tâche peut signifier que la tâche a été demandée mais n'a jamais progressé plus loin que cela (pour une raison quelconque). Cela peut aussi signifier que la tâche est exécutée mais le céleri a oublié son état.
AsyncResult
ne fonctionnera pas pour moi. Que puis-je faire d'autre?Je préfère garder la trace de objectifs que de suivre les tâches elles-mêmes. Je conserve certaines informations sur les tâches, mais il s’agit en réalité d’une tâche secondaire. Les objectifs sont stockés indépendamment du céleri. Lorsqu'une demande doit effectuer un calcul, cela dépend de la réalisation de l'objectif. Elle vérifie si l'objectif a déjà été atteint. Dans l'affirmative, il utilise cet objectif mis en cache. Dans le cas contraire, il lance la tâche qui va atteindre l'objectif et l'envoie à le client qui a demandé à la requête HTTP une réponse indiquant qu'il devrait attendre un résultat.
Les noms de variable et les liens hypertexte ci-dessus concernent Celery 4.x. Dans 3.x, les variables et hyperliens correspondants sont les suivants: CELERY_TRACK_STARTED
, CELERY_IGNORE_RESULT
, CELERY_TASK_RESULT_EXPIRES
.
Vous pouvez également créer des états personnalisés et mettre à jour sa valeur en exécutant la tâche . Cet exemple est tiré de docs:
@app.task(bind=True)
def upload_files(self, filenames):
for i, file in enumerate(filenames):
if not self.request.called_directly:
self.update_state(state='PROGRESS',
meta={'current': i, 'total': len(filenames)})
http://celery.readthedocs.org/fr/latest/userguide/tasks.html#custom-states
Vieille question, mais j'ai récemment rencontré ce problème.
Si vous essayez d'obtenir le task_id, vous pouvez le faire comme ceci:
import celery
from celery_app import add
from celery import uuid
task_id = uuid()
result = add.apply_async((2, 2), task_id=task_id)
Maintenant vous savez exactement ce qu'est le task_id et vous pouvez maintenant l'utiliser pour obtenir AsyncResult
# grab the AsyncResult
result = celery.result.AsyncResult(task_id)
# print the task id
print result.task_id
09dad9cf-c9fa-4aee-933f-ff54dae39bdf
# print the AsyncResult's status
print result.status
SUCCESS
# print the result returned
print result.result
4
Il suffit d’utiliser cette API à partir de céleri FAQ
result = app.AsyncResult(task_id)
Cela fonctionne bien.
pour des tâches simples, nous pouvons utiliser http://flower.readthedocs.io/en/latest/screenshots.html et http://policystat.github.io/jobtastic/ pour effectuer la surveillance.
et pour les tâches compliquées, dites une tâche qui traite beaucoup d'autres modules. Nous vous recommandons d’enregistrer manuellement la progression et le message sur l’unité de tâche spécifique.
En dehors de l'approche ci-dessus par programmation Utilisation de Flower Le statut peut être facilement vu.
Surveillance en temps réel à l'aide d'événements de céleri . Flower est un outil Web de surveillance et d'administration des grappes de céleri.
Document officiel: Fleur - Outil de surveillance du céleri
Installation:
$ pip install flower
Usage:
http://localhost:5555
J'ai trouvé des informations utiles dans le
Guide des travailleurs du projet Celery inspecting-workers
En ce qui me concerne, je vérifie si le céleri fonctionne.
inspect_workers = task.app.control.inspect()
if inspect_workers.registered() is None:
state = 'FAILURE'
else:
state = str(task.state)
Vous pouvez jouer avec inspect pour obtenir vos besoins.