[IMP] mass_mailing: use cron trigger to send "now"

The "launch" button of an email campaign mark the current campaign ready
to be processed. As sending all the mails is a pretty heavy operation,
it is done asynchronously in a cron. The cron was running every hour, it
means the cron was running even if there was no active campaign and it
has a best precision of 1 hour.

We now use the new mechanism of cron triggers (4b28f11) to schedule the
con execution at the time the campaign is configured to be sent. It
achieves a better precision and ensures the cron only runs when there are
stuff to process.

We still let the cron run once a day as a security until the cron
mechanisme proves reliable.

closes odoo/odoo#65124

Task: 2416741
Signed-off-by: Julien Castiaux <Julien00859@users.noreply.github.com>
This commit is contained in:
Julien Castiaux
2021-03-09 09:31:24 +00:00
parent 2b73e09ba8
commit 2ba1e83253
3 changed files with 48 additions and 2 deletions
@@ -8,8 +8,8 @@
<field name="state">code</field>
<field name="code">model._process_mass_mailing_queue()</field>
<field name="user_id" ref="base.user_root" />
<field name="interval_number">60</field>
<field name="interval_type">minutes</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
</record>
+5
View File
@@ -358,6 +358,11 @@ class MassMailing(models.Model):
def action_put_in_queue(self):
self.write({'state': 'in_queue'})
cron = self.env.ref('mass_mailing.ir_cron_mass_mailing_queue')
cron._trigger(
schedule_date or fields.Datetime.now()
for schedule_date in self.mapped('schedule_date')
)
def action_cancel(self):
self.write({'state': 'draft', 'schedule_date': False, 'schedule_type': 'now', 'next_departure': False})
@@ -2,6 +2,9 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from ast import literal_eval
from datetime import datetime
from freezegun import freeze_time
from odoo.addons.mass_mailing.tests.common import MassMailCommon
from odoo.tests.common import users, Form
@@ -173,6 +176,44 @@ class TestMassMailFeatures(MassMailCommon):
'email_to incorrect. Should be equal to "%s"' % (
formataddr((test_partner.name, test_partner.email))))
@users('user_marketing')
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_mailing_cron_trigger(self):
""" Technical test to ensure the cron is triggered at the correct
time """
ir_cron_triggers = self.env['ir.cron.trigger'].sudo()
partner = self.env['res.partner'].create({
'name': 'Jean-Alphonce',
'email': 'jeanalph@example.com',
})
common_mailing_values = {
'name': 'Knock knock',
'subject': "Who's there?",
'mailing_model_id': self.env['ir.model']._get('res.partner').id,
'mailing_domain': [('id', '=', partner.id)],
'body_html': 'The marketing mailing test.',
'schedule_type': 'scheduled',
}
now = datetime(2021, 2, 5, 16, 43, 20)
then = datetime(2021, 2, 7, 12, 0, 0)
with freeze_time(now):
for (test, truth) in [(False, now), (then, then)]:
with self.subTest(schedule_date=test):
triggers_before = ir_cron_triggers.search([])
mailing = self.env['mailing.mailing'].create({
**common_mailing_values,
'schedule_date': test,
})
mailing.action_put_in_queue()
triggers_after = ir_cron_triggers.search([])
new_triggers = triggers_after - triggers_before
new_triggers.ensure_one()
self.assertLessEqual(new_triggers.call_at, truth)
@users('user_marketing')
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_mailing_on_res_partner(self):