Refactor Stats notifications to spearate classes

[MAILPOET-1571]
This commit is contained in:
Pavel Dohnal
2019-01-09 10:28:50 +01:00
parent 6452e83476
commit 96f2f79d48
7 changed files with 120 additions and 43 deletions

View File

@@ -23,6 +23,7 @@ class Daemon {
$this->executeMigrationWorker(); $this->executeMigrationWorker();
$this->executeScheduleWorker(); $this->executeScheduleWorker();
$this->executeQueueWorker(); $this->executeQueueWorker();
$this->executeStatsNotificationsWorker();
$this->executeSendingServiceKeyCheckWorker(); $this->executeSendingServiceKeyCheckWorker();
$this->executePremiumKeyCheckWorker(); $this->executePremiumKeyCheckWorker();
$this->executeBounceWorker(); $this->executeBounceWorker();
@@ -43,6 +44,11 @@ class Daemon {
return $queue->process(); return $queue->process();
} }
function executeStatsNotificationsWorker() {
$worker = $this->workers_factory->createStatsNotificationsWorker($this->timer);
return $worker->process();
}
function executeSendingServiceKeyCheckWorker() { function executeSendingServiceKeyCheckWorker() {
$worker = $this->workers_factory->createSendingServiceKeyCheckWorker($this->timer); $worker = $this->workers_factory->createSendingServiceKeyCheckWorker($this->timer);
return $worker->process(); return $worker->process();

View File

@@ -5,7 +5,7 @@ use MailPoet\Cron\CronHelper;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Links; use MailPoet\Cron\Workers\SendingQueue\Tasks\Links;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask; use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterTask; use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterTask;
use MailPoet\Cron\Workers\StatsNotifications; use MailPoet\Cron\Workers\StatsNotifications\Scheduler as StatsNotificationsScheduler;
use MailPoet\Logging\Logger; use MailPoet\Logging\Logger;
use MailPoet\Mailer\MailerError; use MailPoet\Mailer\MailerError;
use MailPoet\Mailer\MailerLog; use MailPoet\Mailer\MailerLog;
@@ -26,15 +26,15 @@ class SendingQueue {
const BATCH_SIZE = 20; const BATCH_SIZE = 20;
const TASK_BATCH_SIZE = 5; const TASK_BATCH_SIZE = 5;
/** @var StatsNotifications */ /** @var StatsNotificationsScheduler */
public $stats_notifications_worker; public $stats_notifications_scheduler;
/** @var SendingErrorHandler */ /** @var SendingErrorHandler */
private $error_handler; private $error_handler;
function __construct(SendingErrorHandler $error_handler, StatsNotifications $stats_notifications_worker, $timer = false, $mailer_task = false, $newsletter_task = false) { function __construct(SendingErrorHandler $error_handler, StatsNotificationsScheduler $stats_notifications_scheduler, $timer = false, $mailer_task = false, $newsletter_task = false) {
$this->error_handler = $error_handler; $this->error_handler = $error_handler;
$this->stats_notifications_worker = $stats_notifications_worker; $this->stats_notifications_scheduler = $stats_notifications_scheduler;
$this->mailer_task = ($mailer_task) ? $mailer_task : new MailerTask(); $this->mailer_task = ($mailer_task) ? $mailer_task : new MailerTask();
$this->newsletter_task = ($newsletter_task) ? $newsletter_task : new NewsletterTask(); $this->newsletter_task = ($newsletter_task) ? $newsletter_task : new NewsletterTask();
$this->timer = ($timer) ? $timer : microtime(true); $this->timer = ($timer) ? $timer : microtime(true);
@@ -103,7 +103,7 @@ class SendingQueue {
); );
if($queue->status === ScheduledTaskModel::STATUS_COMPLETED) { if($queue->status === ScheduledTaskModel::STATUS_COMPLETED) {
$this->newsletter_task->markNewsletterAsSent($newsletter, $queue); $this->newsletter_task->markNewsletterAsSent($newsletter, $queue);
$this->stats_notifications_worker->schedule($newsletter); $this->stats_notifications_scheduler->schedule($newsletter);
} }
$this->enforceSendingAndExecutionLimits(); $this->enforceSendingAndExecutionLimits();
} }

View File

@@ -1,25 +1,14 @@
<?php <?php
namespace MailPoet\Cron\Workers; namespace MailPoet\Cron\Workers\StatsNotifications;
use Carbon\Carbon; use Carbon\Carbon;
use MailPoet\Models\Newsletter; use MailPoet\Models\Newsletter;
use MailPoet\Models\SendingQueue;
use MailPoet\Models\ScheduledTask; use MailPoet\Models\ScheduledTask;
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
use MailPoet\Models\StatsNotification; use MailPoet\Models\StatsNotification;
/** class Scheduler {
* TODO:
* - add processing of this task to Daemon
* - check JIRA what to do next and how to send the newsletter
* - see \MailPoet\Subscribers\NewSubscriberNotificationMailer how to send an email, now with DI everything should be easy
*/
class StatsNotifications {
const TASK_TYPE = 'stats_notification';
const SETTINGS_KEY = 'stats_notifications';
/** /**
* How many hours after the newsletter will be the stats notification sent * How many hours after the newsletter will be the stats notification sent
@@ -33,7 +22,7 @@ class StatsNotifications {
} }
$task = ScheduledTask::create(); $task = ScheduledTask::create();
$task->type = self::TASK_TYPE; $task->type = Worker::TASK_TYPE;
$task->status = ScheduledTask::STATUS_SCHEDULED; $task->status = ScheduledTask::STATUS_SCHEDULED;
$task->scheduled_at = $this->getNextRunDate(); $task->scheduled_at = $this->getNextRunDate();
$task->save(); $task->save();
@@ -44,10 +33,6 @@ class StatsNotifications {
$stats_notifications->save(); $stats_notifications->save();
} }
function process() {
}
private function shouldSchedule(Newsletter $newsletter) { private function shouldSchedule(Newsletter $newsletter) {
if($this->isDisabled()) { if($this->isDisabled()) {
return false; return false;
@@ -62,7 +47,7 @@ class StatsNotifications {
} }
private function isDisabled() { private function isDisabled() {
$settings = Setting::getValue(self::SETTINGS_KEY); $settings = Setting::getValue(Worker::SETTINGS_KEY);
if(!is_array($settings)) { if(!is_array($settings)) {
return true; return true;
} }
@@ -81,7 +66,7 @@ class StatsNotifications {
private function isTaskScheduled($newsletter_id) { private function isTaskScheduled($newsletter_id) {
$existing = ScheduledTask::table_alias('tasks') $existing = ScheduledTask::table_alias('tasks')
->join(StatsNotification::$_table, 'tasks.id = notification.task_id', 'notification') ->join(StatsNotification::$_table, 'tasks.id = notification.task_id', 'notification')
->where('tasks.type', self::TASK_TYPE) ->where('tasks.type', Worker::TASK_TYPE)
->where('notification.newsletter_id', $newsletter_id) ->where('notification.newsletter_id', $newsletter_id)
->findMany(); ->findMany();
return (bool)$existing; return (bool)$existing;

View File

@@ -0,0 +1,79 @@
<?php
namespace MailPoet\Cron\Workers\StatsNotifications;
use MailPoet\Config\Renderer;
use MailPoet\Cron\CronHelper;
use MailPoet\Mailer\Mailer;
use MailPoet\Models\Setting;
/**
* TODO:
* - add processing of this task to Daemon
* - check JIRA what to do next and how to send the newsletter
* - see \MailPoet\Subscribers\NewSubscriberNotificationMailer how to send an email, now with DI everything should be easy
*/
class Worker {
const TASK_TYPE = 'stats_notification';
const SETTINGS_KEY = 'stats_notifications';
const SENDER_EMAIL_PREFIX = 'wordpress@';
/** @var float */
public $timer;
/** @var Renderer */
private $renderer;
/** @var \MailPoet\Mailer\Mailer */
private $mailer;
function __construct(Mailer $mailer, Renderer $renderer, $timer = false) {
$this->timer = $timer ?: microtime(true);
$this->renderer = $renderer;
$this->mailer = $mailer;
}
/** @throws \Exception */
function process() {
$settings = Setting::getValue(self::SETTINGS_KEY);
try {
$this->mailer->getSenderNameAndAddress($this->constructSenderEmail());
$this->mailer->send($this->constructNewsletter(), $settings['address']);
} catch(\Exception $e) {
if(WP_DEBUG) {
throw $e;
}
}
CronHelper::enforceExecutionLimit($this->timer);
}
private function constructSenderEmail() {
$url_parts = parse_url(home_url());
$site_name = strtolower($url_parts['host']);
if(strpos($site_name, 'www.') === 0) {
$site_name = substr($site_name, 4);
}
return [
'address' => self::SENDER_EMAIL_PREFIX . $site_name,
'name' => self::SENDER_EMAIL_PREFIX . $site_name,
];
}
private function constructNewsletter() {
$context = [
'link_settings' => get_site_url(null, '/wp-admin/admin.php?page=mailpoet-settings'),
'link_premium' => get_site_url(null, '/wp-admin/admin.php?page=mailpoet-premium'),
];
return [
'subject' => sprintf(__('New subscriber to ', 'mailpoet')),
'body' => [
'html' => $this->renderer->render('emails/newSubscriberNotification.html', $context),
'text' => $this->renderer->render('emails/newSubscriberNotification.txt', $context),
],
];
}
}

View File

@@ -2,9 +2,11 @@
namespace MailPoet\Cron\Workers; namespace MailPoet\Cron\Workers;
use MailPoet\Config\Renderer;
use MailPoet\Cron\Workers\Scheduler as SchedulerWorker; use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker; use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
use MailPoet\Cron\Workers\SendingQueue\Migration as MigrationWorker; use MailPoet\Cron\Workers\SendingQueue\Migration as MigrationWorker;
use MailPoet\Cron\Workers\StatsNotifications\Worker as StatsNotificationsWorker;
use MailPoet\Cron\Workers\Bounce as BounceWorker; use MailPoet\Cron\Workers\Bounce as BounceWorker;
use MailPoet\Cron\Workers\KeyCheck\PremiumKeyCheck as PremiumKeyCheckWorker; use MailPoet\Cron\Workers\KeyCheck\PremiumKeyCheck as PremiumKeyCheckWorker;
use MailPoet\Cron\Workers\KeyCheck\SendingServiceKeyCheck as SendingServiceKeyCheckWorker; use MailPoet\Cron\Workers\KeyCheck\SendingServiceKeyCheck as SendingServiceKeyCheckWorker;
@@ -26,11 +28,17 @@ class WorkersFactory {
/** @return SendingQueueWorker */ /** @return SendingQueueWorker */
function createQueueWorker($timer) { function createQueueWorker($timer) {
return new SendingQueueWorker($this->sending_error_handler, $this->createStatsNotificationsWorker(), $timer); return new SendingQueueWorker($this->sending_error_handler, $this->createStatsNotificationsWorker($timer), $timer);
} }
function createStatsNotificationsWorker() { function createStatsNotificationsWorker($timer) {
return new StatsNotifications(); //TODO get those from DI
$caching = !WP_DEBUG;
$debugging = WP_DEBUG;
$this->renderer = new Renderer($caching, $debugging);
$this->mailer = new \MailPoet\Mailer\Mailer();
return new StatsNotificationsWorker($this->mailer, $this->renderer, $timer);
} }
/** @return SendingServiceKeyCheckWorker */ /** @return SendingServiceKeyCheckWorker */

View File

@@ -12,7 +12,7 @@ use MailPoet\Cron\Workers\SendingQueue\SendingErrorHandler;
use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker; use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask; use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterTask; use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterTask;
use MailPoet\Cron\Workers\StatsNotifications; use MailPoet\Cron\Workers\StatsNotifications\Scheduler as StatsNotificationsScheduler;
use MailPoet\Mailer\MailerLog; use MailPoet\Mailer\MailerLog;
use MailPoet\Models\Newsletter; use MailPoet\Models\Newsletter;
use MailPoet\Models\NewsletterLink; use MailPoet\Models\NewsletterLink;
@@ -37,7 +37,7 @@ class SendingQueueTest extends \MailPoetTest {
/** @var SendingErrorHandler */ /** @var SendingErrorHandler */
private $sending_error_handler; private $sending_error_handler;
/** @var StatsNotifications */ /** @var Scheduler */
private $stats_notifications_worker; private $stats_notifications_worker;
function _before() { function _before() {
@@ -80,7 +80,7 @@ class SendingQueueTest extends \MailPoetTest {
$this->newsletter_link->hash = 'abcde'; $this->newsletter_link->hash = 'abcde';
$this->newsletter_link->save(); $this->newsletter_link->save();
$this->sending_error_handler = new SendingErrorHandler(); $this->sending_error_handler = new SendingErrorHandler();
$this->stats_notifications_worker = new StatsNotifications(); $this->stats_notifications_worker = new StatsNotificationsScheduler();
$this->sending_queue_worker = new SendingQueueWorker($this->sending_error_handler, $this->stats_notifications_worker); $this->sending_queue_worker = new SendingQueueWorker($this->sending_error_handler, $this->stats_notifications_worker);
} }

View File

@@ -1,21 +1,20 @@
<?php <?php
namespace MailPoet\Test\Cron\Workers; namespace MailPoet\Cron\Workers\StatsNotifications;
use MailPoet\Cron\Workers\StatsNotifications;
use MailPoet\Models\Newsletter; use MailPoet\Models\Newsletter;
use MailPoet\Models\ScheduledTask; use MailPoet\Models\ScheduledTask;
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
use MailPoet\Models\StatsNotification; use MailPoet\Models\StatsNotification;
class StatsNotificationsTest extends \MailPoetTest { class SchedulerTest extends \MailPoetTest {
/** @var StatsNotifications */ /** @var Scheduler */
private $stats_notifications; private $stats_notifications;
function _before() { function _before() {
$this->stats_notifications = new StatsNotifications(); $this->stats_notifications = new Scheduler();
Setting::setValue(StatsNotifications::SETTINGS_KEY, [ Setting::setValue(Worker::SETTINGS_KEY, [
'enabled' => true, 'enabled' => true,
'address' => 'email@example.com' 'address' => 'email@example.com'
]); ]);
@@ -33,7 +32,7 @@ class StatsNotificationsTest extends \MailPoetTest {
function testShouldNotScheduleIfDisabled() { function testShouldNotScheduleIfDisabled() {
$newsletter_id = 6; $newsletter_id = 6;
Setting::setValue(StatsNotifications::SETTINGS_KEY, [ Setting::setValue(Worker::SETTINGS_KEY, [
'enabled' => false, 'enabled' => false,
'address' => 'email@example.com' 'address' => 'email@example.com'
]); ]);
@@ -45,7 +44,7 @@ class StatsNotificationsTest extends \MailPoetTest {
function testShouldNotScheduleIfSettingsMissing() { function testShouldNotScheduleIfSettingsMissing() {
$newsletter_id = 7; $newsletter_id = 7;
Setting::setValue(StatsNotifications::SETTINGS_KEY, []); Setting::setValue(Worker::SETTINGS_KEY, []);
$newsletter = Newsletter::createOrUpdate(['id' => $newsletter_id, 'type' => Newsletter::TYPE_STANDARD]); $newsletter = Newsletter::createOrUpdate(['id' => $newsletter_id, 'type' => Newsletter::TYPE_STANDARD]);
$this->stats_notifications->schedule($newsletter); $this->stats_notifications->schedule($newsletter);
$notification = StatsNotification::where('newsletter_id', $newsletter_id)->findOne(); $notification = StatsNotification::where('newsletter_id', $newsletter_id)->findOne();
@@ -54,7 +53,7 @@ class StatsNotificationsTest extends \MailPoetTest {
function testShouldNotScheduleIfEmailIsMissing() { function testShouldNotScheduleIfEmailIsMissing() {
$newsletter_id = 8; $newsletter_id = 8;
Setting::setValue(StatsNotifications::SETTINGS_KEY, [ Setting::setValue(Worker::SETTINGS_KEY, [
'enabled' => true, 'enabled' => true,
]); ]);
$newsletter = Newsletter::createOrUpdate(['id' => $newsletter_id, 'type' => Newsletter::TYPE_STANDARD]); $newsletter = Newsletter::createOrUpdate(['id' => $newsletter_id, 'type' => Newsletter::TYPE_STANDARD]);
@@ -65,7 +64,7 @@ class StatsNotificationsTest extends \MailPoetTest {
function testShouldNotScheduleIfEmailIsEmpty() { function testShouldNotScheduleIfEmailIsEmpty() {
$newsletter_id = 9; $newsletter_id = 9;
Setting::setValue(StatsNotifications::SETTINGS_KEY, [ Setting::setValue(Worker::SETTINGS_KEY, [
'enabled' => true, 'enabled' => true,
'address' => ' ' 'address' => ' '
]); ]);
@@ -78,7 +77,7 @@ class StatsNotificationsTest extends \MailPoetTest {
function testShouldNotScheduleIfAlreadyScheduled() { function testShouldNotScheduleIfAlreadyScheduled() {
$newsletter_id = 10; $newsletter_id = 10;
$existing_task = ScheduledTask::createOrUpdate([ $existing_task = ScheduledTask::createOrUpdate([
'type' => StatsNotifications::TASK_TYPE, 'type' => Worker::TASK_TYPE,
'status' => ScheduledTask::STATUS_SCHEDULED, 'status' => ScheduledTask::STATUS_SCHEDULED,
'scheduled_at' => '2017-01-02 12:13:14', 'scheduled_at' => '2017-01-02 12:13:14',
]); ]);