web-dev-qa-db-fra.com

Différence entre le travail d'action / Mailer `delivery_now` et` delivery_later`

Le modèle courant d'interfaçage avec ActionJob dans Rails consiste à configurer un Job avec une méthode perform() qui est appelée de manière asynchrone via perform_now ou perform_later

Dans le cas particulier des Mailers, vous pouvez appeler directement deliver_now Ou deliver_later Car ActionJob est bien intégré à ActionMailer.

Le documentation Rails a les commentaires suivants -

# If you want to send the email now use #deliver_now
UserMailer.welcome(@user).deliver_now

# If you want to send the email through Active Job use #deliver_later
UserMailer.welcome(@user).deliver_later

Le libellé donne l'impression que deliver_now n'utilisera pas ActiveJob pour envoyer le courrier. Est-ce exact, et si oui, quelle est la vraie différence entre deliver_now Et deliver_later? N'est-on pas asynchrone?

De même, la même différence s'applique-t-elle à perform_now Et perform_later?

Merci!

19
user2490003

Comme vous le dites dans votre question, deliver_now n'utilise pas ActiveJob.

Fondamentalement, deliver_later est asynchrone. Lorsque vous utilisez cette méthode, l'e-mail n'est pas envoyé pour le moment, mais est plutôt poussé dans la file d'attente d'un travail. Si le travail n'est pas en cours d'exécution, l'e-mail ne sera pas envoyé. deliver_now enverra l'e-mail pour le moment, quel que soit l'état de la tâche. Ici vous pouvez voir la documentation des méthodes deliver.

Selon votre deuxième question, perform_now traitera le travail immédiatement sans l'envoyer à la file d'attente. perform_later, cependant, ajoutera le travail à la file d'attente, et dès que la file d'attente du travail sera libre, exécutera le travail. Ici vous pouvez voir la documentation des méthodes perform.

21
Daniel Batalla

En plus de ce que Daniel Batalla a écrit, voici une autre observation que j'ai faite: deliver_later semble effectuer une évaluation paresseuse, tandis que deliver_now ne fait pas.

J'ai un modèle ActiveRecord avec un attribut supplémentaire reset_token qui n'est pas stocké dans la base de données (ceci provient de railstutorial.org de Michael Hartl; le modèle stocke une version hachée du jeton dans le reset_digest colonne).

Lors de l'exécution de deliver_now, accéder à @model's reset_token l'attribut à l'intérieur de la vue de l'expéditeur produit le jeton de réinitialisation comme prévu. Cependant, lors de l'exécution de deliver_later, @model.reset_token est toujours nil. Il semble que deliver_later met à jour le modèle avec les données de la base de données et parce que reset_token est un attribut supplémentaire qui n'est pas soutenu par la base de données, il sera nil à ce stade. (La documentation du code est trop profondément imbriquée pour que je puisse vérifier cela dans la source.)

Michael utilise deliver_now dans le didacticiel. Je ne sais pas s'il le fait pour éviter une évaluation paresseuse. Mais il m'a fallu un certain temps pour réaliser que je devais juste changer deliver_later à deliver_now pour réussir mes tests.

5
bovender