2011-03-08 5 views
0

Dans mon application rails, j'utilise l'API d'analyse SendGrid qui poste le courrier sur mon serveur. De temps en temps, l'API Parse de SendGrid soumet deux fois le même e-mail.Heroku - Problème dû à plusieurs Dynos

Lorsque je reçois un courrier posté, je le place dans le modèle IncomingMail. Donc, afin d'éviter ce double problème de soumission, je regarde chaque IncomingMail lors du traitement pour voir s'il y a un doublon dans la table dans la dernière minute. Cela a bien marché sur le développement, il a attrapé tous les doubles soumissions.

Maintenant, j'ai poussé ce live à heroku, où j'ai plus de 2 dynos et cela n'a pas fonctionné. Ma conjecture étant que cela a quelque chose à voir avec la réplication. Cela étant le cas, comment les sites évolutifs avec plusieurs serveurs peuvent-ils traiter quelque chose comme ça?

Merci

Répondre

2

Vous devriez envisager d'utiliser une file d'attente de travail d'arrière-plan. Heroku a "Workers" (ce qui était Delayed Job). Plutôt que d'envoyer l'e-mail immédiatement, vous le placez dans la file d'attente. Ensuite, un ou plusieurs «travailleurs» de Heroku doivent être ajoutés à votre compte, et chacun d'entre eux tirera les travaux en séquence. Cela signifie qu'il peut y avoir un court délai (en fonction de la charge) avant que le courrier électronique ne soit envoyé, mais ce délai n'est pas présenté à l'utilisateur, et s'il y a beaucoup de courrier électronique à envoyer, ajoutez simplement plus de travailleurs. Attente d'un service externe comme un fournisseur de messagerie sur chaque action de l'utilisateur est dangereux car tout problème de réseau mettra hors service votre site car plusieurs utilisateurs doivent attendre que leurs demandes HTTP soient traitées alors qu'Heroku est bloqué avec ces appels de tiers.

Dans cette situation avec les travailleurs, chaque travail échouerait mais serait retenté et finalement réussir.

+0

Merci Stef, mais j'utilise déjà 1 worker sur heroku. Pensées? – AnApprentice

+0

Je me demande si la base de données n'est pas assez rapidement répliquée? – AnApprentice

0

Cela semble être un problème de transaction. Si plusieurs travailleurs sont en cours d'exécution simultanément, leur opération peut être «entrelacée». Par exemple, cette séquence d'événements entraînerait l'envoi de 2 mails.

travailleur A: Les chèques pour un enregistrement existant et ne trouve pas un travailleurs B: Les chèques pour un enregistrement existant et ne trouve pas un travailleur A: Poste à SendGrid travailleur B: Envoyer à SendGrid

Vous pouvez envelopper tout dans une transaction pour éviter que cela ne se produise. Quelque chose comme ça devrait le faire.

class IncomingMail < ActiveRecord::Base 

    def check_and_send(email_address) 
    transaction do 
     # your existing code for preventing duplicates and sending 
    end 
    end 

end 
Questions connexes