From 3d70db9eb5d052a8eff5b7c8f5e85b19e12a72cd Mon Sep 17 00:00:00 2001 From: epriestley <git@epriestley.com> Date: Wed, 14 Jun 2017 12:10:39 -0700 Subject: [PATCH] Queue a worker task to send mail only after committing the mail transaction Summary: Fixes T12844. This code is misleading: the daemon insert is happening on a different connection, and is not inside the transaction on the Mail connection. What actually happens is this: - (Connection A) `BEGIN` - (Connection A) `INSERT INTO mail ...` - (Connection B) `INSERT INTO worker ...` <-- This is a different connection, and it is NOT in a transaction! - There's a race window here: the worker row is globally visible but the mail row is still isolated inside the transaction. - (Connection A) `COMMIT` - Now we're clear: the mail row is globally visible. Change this code to reflect what's actually happening. This means that if the worker row insert fails for some reason, we'll now throw with a mail row written to the database. But this is fine: it doesn't send on its own (so it can't cause mail loops or anything) and it can be re-queued with `bin/mail resend` if necessary without too much trouble. Test Plan: See T12844 for particulars. Made some comments on tasks, saw the daemons send mail. Reviewers: chad, amckinley, jmeador Reviewed By: jmeador Maniphest Tasks: T12844 Differential Revision: https://secure.phabricator.com/D18124 --- .../metamta/storage/PhabricatorMetaMTAMail.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php index f2ed8c7721..20b1482036 100644 --- a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php +++ b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php @@ -372,16 +372,16 @@ final class PhabricatorMetaMTAMail } $editor->save(); - // Queue a task to send this mail. - $mailer_task = PhabricatorWorker::scheduleTask( - 'PhabricatorMetaMTAWorker', - $this->getID(), - array( - 'priority' => PhabricatorWorker::PRIORITY_ALERTS, - )); - $this->saveTransaction(); + // Queue a task to send this mail. + $mailer_task = PhabricatorWorker::scheduleTask( + 'PhabricatorMetaMTAWorker', + $this->getID(), + array( + 'priority' => PhabricatorWorker::PRIORITY_ALERTS, + )); + return $result; }