Use CronHelper service in cron core classes [MAILPOET-2459]

This commit is contained in:
wxa
2019-10-30 16:23:22 +03:00
committed by Jack Kitterhing
parent ed7784d945
commit 3436fed6e7
11 changed files with 90 additions and 59 deletions

View File

@@ -10,14 +10,18 @@ class Daemon {
/** @var WorkersFactory */
private $workers_factory;
function __construct(WorkersFactory $workers_factory) {
/** @var CronHelper */
private $cron_helper;
function __construct(WorkersFactory $workers_factory, CronHelper $cron_helper) {
$this->timer = microtime(true);
$this->workers_factory = $workers_factory;
$this->cron_helper = $cron_helper;
}
function run($settings_daemon_data) {
$settings_daemon_data['run_started_at'] = time();
CronHelper::saveDaemon($settings_daemon_data);
$this->cron_helper->saveDaemon($settings_daemon_data);
$errors = [];
foreach ($this->getWorkers() as $worker) {
@@ -33,11 +37,11 @@ class Daemon {
}
if (!empty($errors)) {
CronHelper::saveDaemonLastError($errors);
$this->cron_helper->saveDaemonLastError($errors);
}
// Log successful execution
CronHelper::saveDaemonRunCompleted(time());
$this->cron_helper->saveDaemonRunCompleted(time());
}
private function getWorkers() {

View File

@@ -15,14 +15,18 @@ class DaemonHttpRunner {
/** @var Daemon */
private $daemon;
/** @var CronHelper */
private $cron_helper;
/** @var SettingsController */
private $settings;
const PING_SUCCESS_RESPONSE = 'pong';
function __construct(Daemon $daemon = null, SettingsController $settings) {
$this->settings_daemon_data = CronHelper::getDaemon();
$this->token = CronHelper::createToken();
function __construct(Daemon $daemon = null, CronHelper $cron_helper, SettingsController $settings) {
$this->cron_helper = $cron_helper;
$this->settings_daemon_data = $this->cron_helper->getDaemon();
$this->token = $this->cron_helper->createToken();
$this->timer = microtime(true);
$this->daemon = $daemon;
$this->settings = $settings;
@@ -74,12 +78,12 @@ class DaemonHttpRunner {
// if workers took less time to execute than the daemon execution limit,
// pause daemon execution to ensure that daemon runs only once every X seconds
$elapsed_time = microtime(true) - $this->timer;
if ($elapsed_time < CronHelper::getDaemonExecutionLimit()) {
$this->pauseExecution(CronHelper::getDaemonExecutionLimit() - $elapsed_time);
if ($elapsed_time < $this->cron_helper->getDaemonExecutionLimit()) {
$this->pauseExecution($this->cron_helper->getDaemonExecutionLimit() - $elapsed_time);
}
}
// after each execution, re-read daemon data in case it changed
$settings_daemon_data = CronHelper::getDaemon();
$settings_daemon_data = $this->cron_helper->getDaemon();
if ($this->shouldTerminateExecution($settings_daemon_data)) {
return $this->terminateRequest();
}
@@ -91,7 +95,7 @@ class DaemonHttpRunner {
}
function callSelf() {
CronHelper::accessDaemon($this->token);
$this->cron_helper->accessDaemon($this->token);
$this->terminateRequest();
}

View File

@@ -6,34 +6,41 @@ class Supervisor {
public $daemon;
public $token;
function __construct() {
$this->token = CronHelper::createToken();
/** @var CronHelper */
private $cron_helper;
function __construct(CronHelper $cron_helper) {
$this->cron_helper = $cron_helper;
}
function init() {
$this->token = $this->cron_helper->createToken();
$this->daemon = $this->getDaemon();
}
function checkDaemon() {
$daemon = $this->daemon;
$execution_timeout_exceeded =
(time() - (int)$daemon['updated_at']) >= CronHelper::getDaemonExecutionTimeout();
(time() - (int)$daemon['updated_at']) >= $this->cron_helper->getDaemonExecutionTimeout();
$daemon_is_inactive =
isset($daemon['status']) && $daemon['status'] === CronHelper::DAEMON_STATUS_INACTIVE;
if ($execution_timeout_exceeded || $daemon_is_inactive) {
CronHelper::restartDaemon($this->token);
$this->cron_helper->restartDaemon($this->token);
return $this->runDaemon();
}
return $daemon;
}
function runDaemon() {
CronHelper::accessDaemon($this->token);
$daemon = CronHelper::getDaemon();
$this->cron_helper->accessDaemon($this->token);
$daemon = $this->cron_helper->getDaemon();
return $daemon;
}
function getDaemon() {
$daemon = CronHelper::getDaemon();
$daemon = $this->cron_helper->getDaemon();
if (!$daemon) {
CronHelper::createDaemon($this->token);
$this->cron_helper->createDaemon($this->token);
return $this->runDaemon();
}
return $daemon;

View File

@@ -3,10 +3,12 @@
namespace MailPoet\Cron\Triggers;
use MailPoet\Cron\Supervisor;
use MailPoet\DI\ContainerWrapper;
class MailPoet {
static function run() {
$supervisor = new Supervisor();
$supervisor = ContainerWrapper::getInstance()->get(Supervisor::class);
$supervisor->init();
return $supervisor->checkDaemon();
}
}

View File

@@ -18,6 +18,7 @@ use MailPoet\Cron\Workers\SubscriberLinkTokens;
use MailPoet\Cron\Workers\UnsubscribeTokens;
use MailPoet\Cron\Workers\WooCommercePastOrders;
use MailPoet\Cron\Workers\WooCommerceSync as WooCommerceSyncWorker;
use MailPoet\DI\ContainerWrapper;
use MailPoet\Mailer\MailerLog;
use MailPoet\Models\ScheduledTask;
use MailPoet\Services\Bridge;
@@ -210,9 +211,10 @@ class WordPress {
}
static function stop() {
$cron_daemon = CronHelper::getDaemon();
$cron_helper = ContainerWrapper::getInstance()->get(CronHelper::class);
$cron_daemon = $cron_helper->getDaemon();
if ($cron_daemon) {
CronHelper::deactivateDaemon($cron_daemon);
$cron_helper->deactivateDaemon($cron_daemon);
}
}

View File

@@ -129,6 +129,7 @@ class ContainerConfigurator implements IContainerConfigurator {
$container->autowire(\MailPoet\Cron\CronTrigger::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\Daemon::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\DaemonHttpRunner::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\Supervisor::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\Workers\WorkersFactory::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\Workers\SendingQueue\SendingErrorHandler::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\Workers\StatsNotifications\Scheduler::class);

View File

@@ -24,8 +24,12 @@ class CronDaemon {
/** @var DaemonHttpRunner */
private $daemon_runner;
function __construct(DaemonHttpRunner $daemon_runner) {
/** @var CronHelper */
private $cron_helper;
function __construct(DaemonHttpRunner $daemon_runner, CronHelper $cron_helper) {
$this->daemon_runner = $daemon_runner;
$this->cron_helper = $cron_helper;
}
function run($data) {
@@ -33,7 +37,7 @@ class CronDaemon {
}
function ping() {
die(CronHelper::pingDaemon());
die($this->cron_helper->pingDaemon());
}
function pingResponse() {

View File

@@ -44,6 +44,7 @@ if ($settings->get('cron_trigger.method') !== \MailPoet\Cron\CronTrigger::METHOD
}
// Run Cron Daemon
$data = \MailPoet\Cron\CronHelper::createDaemon(null);
$cron_helper = $container->get(\MailPoet\Cron\CronHelper::class);
$data = $cron_helper->createDaemon(null);
$trigger = $container->get(\MailPoet\Cron\Daemon::class);
$trigger->run($data);

View File

@@ -22,6 +22,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
function _before() {
parent::_before();
$this->settings = new SettingsController();
$this->cron_helper = ContainerWrapper::getInstance()->get(CronHelper::class);
}
function testItConstructs() {
@@ -79,13 +80,13 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
]),
]);
$daemon = new Daemon($workers_factory_mock);
$daemon = new Daemon($workers_factory_mock, $this->cron_helper);
$daemon_http_runner = $this->make(DaemonHttpRunner::class, [
'pauseExecution' => null,
'callSelf' => null,
]);
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon_http_runner->__construct($daemon, new SettingsController());
$daemon_http_runner->__construct($daemon, $this->cron_helper, new SettingsController());
$daemon_http_runner->run($data);
$updated_daemon = $this->settings->get(CronHelper::DAEMON_SETTING);
expect($updated_daemon['last_error'][0]['message'])->equals('Message');
@@ -96,8 +97,8 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
$daemon = $this->makeEmpty(Daemon::class);
$daemon_http_runner = $this->make(DaemonHttpRunner::class, [
'pauseExecution' => Expected::exactly(1, function($pause_delay) {
expect($pause_delay)->lessThan(CronHelper::getDaemonExecutionLimit());
expect($pause_delay)->greaterThan(CronHelper::getDaemonExecutionLimit() - 1);
expect($pause_delay)->lessThan($this->cron_helper->getDaemonExecutionLimit());
expect($pause_delay)->greaterThan($this->cron_helper->getDaemonExecutionLimit() - 1);
}),
'callSelf' => null,
'terminateRequest' => null,
@@ -106,7 +107,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123,
];
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon_http_runner->__construct($daemon, new SettingsController());
$daemon_http_runner->__construct($daemon, $this->cron_helper, new SettingsController());
$daemon_http_runner->run($data);
}
@@ -128,7 +129,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123,
];
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon->__construct(new Daemon($workers_factory_mock), new SettingsController());
$daemon->__construct(new Daemon($workers_factory_mock, $this->cron_helper), $this->cron_helper, new SettingsController());
$daemon->run($data);
}
@@ -152,7 +153,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123,
];
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon->__construct(new Daemon($workers_factory_mock), new SettingsController());
$daemon->__construct(new Daemon($workers_factory_mock, $this->cron_helper), $this->cron_helper, new SettingsController());
$daemon->run($data);
$data_after_run = $this->settings->get(CronHelper::DAEMON_SETTING);
expect($data_after_run['token'])->equals(567);
@@ -169,13 +170,13 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'status' => CronHelper::DAEMON_STATUS_INACTIVE,
];
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon->__construct($this->makeEmpty(Daemon::class), new SettingsController());
$daemon->__construct($this->makeEmpty(Daemon::class), $this->cron_helper, new SettingsController());
$daemon->run($data);
}
function testItTerminatesExecutionWhenWPTriggerStopsCron() {
$workers_factory_mock = $this->createWorkersFactoryMock();
$daemon = new Daemon($workers_factory_mock);
$daemon = new Daemon($workers_factory_mock, $this->cron_helper);
$daemon_http_runner = $this->make(DaemonHttpRunner::class, [
'checkWPTriggerExecutionRequirements' => false,
'pauseExecution' => null,
@@ -188,7 +189,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$this->settings->set(CronTrigger::SETTING_NAME . '.method', 'WordPress');
WPFunctions::get()->addFilter('mailpoet_cron_enable_self_deactivation', '__return_true');
$daemon_http_runner->__construct($daemon, new SettingsController());
$daemon_http_runner->__construct($daemon, $this->cron_helper, new SettingsController());
$daemon_http_runner->run($data);
WPFunctions::get()->removeAllFilters('mailpoet_cron_enable_self_deactivation');
}
@@ -203,7 +204,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123,
];
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon_http_runner->__construct(new Daemon($this->createWorkersFactoryMock()), new SettingsController());
$daemon_http_runner->__construct(new Daemon($this->createWorkersFactoryMock(), $this->cron_helper), $this->cron_helper, new SettingsController());
$daemon_http_runner->run($data);
$updated_daemon = $this->settings->get(CronHelper::DAEMON_SETTING);
expect($updated_daemon['token'])->equals($daemon_http_runner->token);
@@ -223,7 +224,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
]),
]);
$daemon = new Daemon($workers_factory_mock);
$daemon = new Daemon($workers_factory_mock, $this->cron_helper);
$daemon_http_runner = $this->make(DaemonHttpRunner::class, [
'pauseExecution' => null,
'callSelf' => null,
@@ -233,7 +234,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
];
$now = time();
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon_http_runner->__construct($daemon, new SettingsController());
$daemon_http_runner->__construct($daemon, $this->cron_helper, new SettingsController());
$daemon_http_runner->run($data);
$updated_daemon = $this->settings->get(CronHelper::DAEMON_SETTING);
expect($updated_daemon['run_started_at'])->greaterOrEquals($now);
@@ -255,7 +256,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123,
];
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon->__construct(new Daemon($this->createWorkersFactoryMock()), new SettingsController());
$daemon->__construct(new Daemon($this->createWorkersFactoryMock(), $this->cron_helper), $this->cron_helper, new SettingsController());
$daemon->run($data);
expect(ignore_user_abort())->equals(1);
}

View File

@@ -7,6 +7,7 @@ use MailPoet\Cron\CronHelper;
use MailPoet\Cron\Daemon;
use MailPoet\Cron\Workers\SimpleWorker;
use MailPoet\Cron\Workers\WorkersFactory;
use MailPoet\DI\ContainerWrapper;
use MailPoet\Models\Setting;
use MailPoet\Settings\SettingsController;
@@ -18,6 +19,7 @@ class DaemonTest extends \MailPoetTest {
public function _before() {
parent::_before();
$this->settings = new SettingsController();
$this->cron_helper = ContainerWrapper::getInstance()->get(CronHelper::class);
}
function testItCanRun() {
@@ -25,7 +27,7 @@ class DaemonTest extends \MailPoetTest {
'token' => 123,
];
$this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon = new Daemon($this->createWorkersFactoryMock());
$daemon = new Daemon($this->createWorkersFactoryMock(), $this->cron_helper);
$daemon->run($data);
}

View File

@@ -4,6 +4,7 @@ namespace MailPoet\Test\Cron;
use MailPoet\Cron\CronHelper;
use MailPoet\Cron\Supervisor;
use MailPoet\DI\ContainerWrapper;
use MailPoet\Models\Setting;
use MailPoet\Settings\SettingsController;
@@ -21,51 +22,53 @@ class SupervisorTest extends \MailPoetTest {
$this->settings->set('cron_trigger', [
'method' => 'none',
]);
$this->cron_helper = ContainerWrapper::getInstance()->get(CronHelper::class);
$this->supervisor = ContainerWrapper::getInstance()->get(Supervisor::class);
}
function testItCanConstruct() {
function testItCanBeInitialized() {
if (getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') $this->markTestSkipped();
$supervisor = new Supervisor();
expect($supervisor->token)->notEmpty();
expect($supervisor->daemon)->notEmpty();
$this->supervisor->init();
expect($this->supervisor->token)->notEmpty();
expect($this->supervisor->daemon)->notEmpty();
}
function testItCreatesDaemonWhenOneDoesNotExist() {
if (getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') $this->markTestSkipped();
expect($this->settings->get(CronHelper::DAEMON_SETTING))->null();
$supervisor = new Supervisor();
expect($supervisor->getDaemon())->notEmpty();
$this->supervisor->init();
expect($this->supervisor->getDaemon())->notEmpty();
}
function testItReturnsDaemonWhenOneExists() {
if (getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') $this->markTestSkipped();
$supervisor = new Supervisor();
expect($supervisor->getDaemon())->equals($supervisor->daemon);
$this->supervisor->init();
expect($this->supervisor->getDaemon())->equals($this->supervisor->daemon);
}
function testItDoesNothingWhenDaemonExecutionDurationIsBelowLimit() {
if (getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') $this->markTestSkipped();
$supervisor = new Supervisor();
expect($supervisor->checkDaemon())
->equals($supervisor->daemon);
$this->supervisor->init();
expect($this->supervisor->checkDaemon())
->equals($this->supervisor->daemon);
}
function testRestartsDaemonWhenExecutionDurationIsAboveLimit() {
if (getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') $this->markTestSkipped();
$supervisor = new Supervisor();
$supervisor->daemon['updated_at'] = time() - CronHelper::getDaemonExecutionTimeout();
$daemon = $supervisor->checkDaemon();
$this->supervisor->init();
$this->supervisor->daemon['updated_at'] = time() - $this->cron_helper->getDaemonExecutionTimeout();
$daemon = $this->supervisor->checkDaemon();
expect(is_int($daemon['updated_at']))->true();
expect($daemon['updated_at'])->notEquals($supervisor->daemon['updated_at']);
expect($daemon['updated_at'])->notEquals($this->supervisor->daemon['updated_at']);
expect($daemon['status'])->equals(CronHelper::DAEMON_STATUS_ACTIVE);
}
function testRestartsDaemonWhenItIsInactive() {
if (getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') $this->markTestSkipped();
$supervisor = new Supervisor();
$supervisor->daemon['updated_at'] = time();
$supervisor->daemon['status'] = CronHelper::DAEMON_STATUS_INACTIVE;
$daemon = $supervisor->checkDaemon();
$this->supervisor->init();
$this->supervisor->daemon['updated_at'] = time();
$this->supervisor->daemon['status'] = CronHelper::DAEMON_STATUS_INACTIVE;
$daemon = $this->supervisor->checkDaemon();
expect($daemon['status'])->equals(CronHelper::DAEMON_STATUS_ACTIVE);
}