2017-10-13 24 views
0

Une tâche relativement longue est déléguée aux opérateurs céleri, qui s'exécutent séparément, sur un autre serveur.Effectuer une tâche de céleri après une validation réussie dans Flask?

Cependant, les résultats sont réintégrés dans la base de données relationnelle (table mise à jour selon une task_descr.id en tant que clé, voir ci-dessous), le travailleur utilise ignore_result.

tâche demandée à l'application Flask:

task = app.celery.send_task('tasks.mytask', [task_descr.id, attachments]) 

Le problème est que les tâches sont demandées alors que la transaction n'a pas encore été fermée du côté Flask. Cela provoque des conditions de concurrence, car parfois céleri travailleur termine la tâche avant la fin de la transaction dans l'application Flask.

Quelle est la bonne façon d'envoyer des tâches après une transaction réussie seulement?

Ou le travailleur doit-il vérifier la disponibilité de task_descr.id avant de tenter une mise sous conditions UPDATE et réessayer la tâche (cela semble être un arrangement trop complexe)? La réponse à Run function after a certain type of model is committed traite d'une situation similaire, mais ici l'envoi de tâche est explicite, donc pas besoin d'écouter les mises à jour/insertions dans certains modèles.

Répondre

0

Une des façons est Per-Request After-Request Callbacks, grâce à Armin Ronacher:

from flask import g 

def after_this_request(func): 
    if not hasattr(g, 'call_after_request'): 
     g.call_after_request = [] 
    g.call_after_request.append(func) 
    return func 


@app.after_request 
def per_request_callbacks(response): 
    for func in getattr(g, 'call_after_request',()): 
     response = func(response) 
    return response 

Dans mon cas, l'utilisation est:

@after_this_request 
    def send_mytask(response): 
     if response.status_code in {200, 302}: 
      task = app.celery.send_task('tasks.mytask', [task_descr.id, attachments]) 
     return response 

Pas idéal, mais semble fonctionner. Mes tâches sont uniquement pour une demande avec succès, donc je ne me soucie pas de 500 ou d'autres conditions d'erreur.