Bonjour,
Dans le cadre d’un projet utilisant Celery, j’aurais aimé tester l’exécution d’une tâche. Je sais que la documentation conseille d’utiliser du mocking, mais n’utilisant pas le client officiel je voudrais vérifier pour un test particulier que tout se déroule bien. Pour cela j’ai mis en place une tâche très simple qui reçoit en paramètres le nom d’une socket Unix et un message à écrire dessus : la tâche ouvre une connexion sur la socket, écrit le message et clôt la connexion.
Au sein des tests, le worker Celery est lancé à l’aide d’un subprocess : je l’instancie avant d’envoyer la tâche, lui transmets un SIGTERM
une fois le message reçu sur ma socket puis j’attends qu’il se termine proprement.
Tout se passe correctement au niveau des test : le message est bien reçu, correspond à ce qui était attendu et le worker s’arrête.
Cependant, j’ai constaté qu’une fois les tests terminés, un message restait présent dans la queue RabbitMQ, comme s’il n’y avait jamais d’acknowledge pour la tâche. C’est ce que j’ai confirmé en regardant l’interface graphique RabbitMQ : un « Deliver » apparaît bien suite à l’exécution de la tâche mais pas d’« Acknowledge ». Cela me semble étrange puisqu’utilisant la configuration par défaut, l'acknowledge devrait avoir lieu avant même l’exécution.
Continuant de chercher le problème, j’ai remarqué que si j’ajoutais un sleep
d’une fraction de seconde juste avant d’envoyer le SIGTERM
au worker, lacknowledge avait bien lieu.
J’ai tenté d’inspecter les exécutions avec et sans sleep
à l’aide de strace
dont voici les deux résultats.
La seule différence notable que je remarque est que dans le cas du sleep
, le worker a le temps d’entamer une nouvelle communication avec le broker. Il reçoit un EAGAIN
lors d’un recvfrom
et transmets une trame "\1\0\1\0\0\0\r\0<\0P\0\0\0\0\0\0\0\1\0\316"
.
Serait-ce l'acknowledge ? Pourquoi surviendrait-il aussi tard ?
Je vous donne aussi les paramètres avec lesquels j’instancie le worker Celery : celery worker --app tests.functional.tasks.app --concurrency 1 --pool solo --without-heartbeat
.
Le without-heartbeat
est simplement là pour amoindrir la différence entre les exécutions avec/sans sleep
, car sans le paramètre il y avait aussi une trame heartbeat qui apparaissant en plus avec le sleep
.
Merci.