Make cron able to stop itself if the cron trigger is WordPress [MAILPOET-2181]

This commit is contained in:
wxa
2019-07-30 12:06:57 +03:00
committed by M. Shull
parent c4f2be2edf
commit cd3cfbe1ab
2 changed files with 68 additions and 17 deletions

View File

@ -1,6 +1,8 @@
<?php <?php
namespace MailPoet\Cron; namespace MailPoet\Cron;
use MailPoet\Cron\Triggers\WordPress;
use MailPoet\Settings\SettingsController;
use MailPoet\WP\Functions as WPFunctions; use MailPoet\WP\Functions as WPFunctions;
if (!defined('ABSPATH')) exit; if (!defined('ABSPATH')) exit;
@ -14,13 +16,17 @@ class DaemonHttpRunner {
/** @var Daemon */ /** @var Daemon */
private $daemon; private $daemon;
/** @var SettingsController */
private $settings;
const PING_SUCCESS_RESPONSE = 'pong'; const PING_SUCCESS_RESPONSE = 'pong';
function __construct(Daemon $daemon = null) { function __construct(Daemon $daemon = null, SettingsController $settings) {
$this->settings_daemon_data = CronHelper::getDaemon(); $this->settings_daemon_data = CronHelper::getDaemon();
$this->token = CronHelper::createToken(); $this->token = CronHelper::createToken();
$this->timer = microtime(true); $this->timer = microtime(true);
$this->daemon = $daemon; $this->daemon = $daemon;
$this->settings = $settings;
} }
function ping() { function ping() {
@ -52,12 +58,21 @@ class DaemonHttpRunner {
} }
$this->settings_daemon_data['token'] = $this->token; $this->settings_daemon_data['token'] = $this->token;
$this->daemon->run($this->settings_daemon_data); $this->daemon->run($this->settings_daemon_data);
// If we're using the WordPress trigger, check the conditions to stop cron if necessary
$enable_cron_self_deactivation = WPFunctions::get()->applyFilters('mailpoet_cron_enable_self_deactivation', false);
if ($enable_cron_self_deactivation
&& $this->isCronTriggerMethodWordPress()
&& !$this->checkWPTriggerExecutionRequirements()
) {
$this->stopCron();
} else {
// if workers took less time to execute than the daemon execution limit, // 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 // pause daemon execution to ensure that daemon runs only once every X seconds
$elapsed_time = microtime(true) - $this->timer; $elapsed_time = microtime(true) - $this->timer;
if ($elapsed_time < CronHelper::DAEMON_EXECUTION_LIMIT) { if ($elapsed_time < CronHelper::DAEMON_EXECUTION_LIMIT) {
$this->pauseExecution(CronHelper::DAEMON_EXECUTION_LIMIT - $elapsed_time); $this->pauseExecution(CronHelper::DAEMON_EXECUTION_LIMIT - $elapsed_time);
} }
}
// after each execution, re-read daemon data in case it changed // after each execution, re-read daemon data in case it changed
$settings_daemon_data = CronHelper::getDaemon(); $settings_daemon_data = CronHelper::getDaemon();
if ($this->shouldTerminateExecution($settings_daemon_data)) { if ($this->shouldTerminateExecution($settings_daemon_data)) {
@ -84,6 +99,19 @@ class DaemonHttpRunner {
die($message); die($message);
} }
function isCronTriggerMethodWordPress() {
$available_methods = CronTrigger::getAvailableMethods();
return $this->settings->get(CronTrigger::SETTING_NAME . '.method') === $available_methods['wordpress'];
}
function checkWPTriggerExecutionRequirements() {
return WordPress::checkExecutionRequirements();
}
function stopCron() {
return WordPress::stop();
}
/** /**
* @param array|null $settings_daemon_data * @param array|null $settings_daemon_data
* *

View File

@ -3,12 +3,15 @@ namespace MailPoet\Test\Cron;
use Codeception\Stub\Expected; use Codeception\Stub\Expected;
use MailPoet\Cron\CronHelper; use MailPoet\Cron\CronHelper;
use MailPoet\Cron\CronTrigger;
use MailPoet\Cron\Daemon; use MailPoet\Cron\Daemon;
use MailPoet\Cron\DaemonHttpRunner; use MailPoet\Cron\DaemonHttpRunner;
use MailPoet\Cron\Workers\SimpleWorker; use MailPoet\Cron\Workers\SimpleWorker;
use MailPoet\Cron\Workers\WorkersFactory; use MailPoet\Cron\Workers\WorkersFactory;
use MailPoet\DI\ContainerWrapper;
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
use MailPoet\Settings\SettingsController; use MailPoet\Settings\SettingsController;
use MailPoet\WP\Functions as WPFunctions;
class DaemonHttpRunnerTest extends \MailPoetTest { class DaemonHttpRunnerTest extends \MailPoetTest {
@ -25,7 +28,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
CronHelper::DAEMON_SETTING, CronHelper::DAEMON_SETTING,
[] []
); );
$daemon = new DaemonHttpRunner(); $daemon = ContainerWrapper::getInstance()->get(DaemonHttpRunner::class);
expect(strlen($daemon->timer))->greaterOrEquals(5); expect(strlen($daemon->timer))->greaterOrEquals(5);
expect(strlen($daemon->token))->greaterOrEquals(5); expect(strlen($daemon->token))->greaterOrEquals(5);
} }
@ -76,12 +79,12 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
]); ]);
$daemon = new Daemon($workers_factory_mock); $daemon = new Daemon($workers_factory_mock);
$daemon_http_runner = $this->make(new DaemonHttpRunner($daemon), [ $daemon_http_runner = $this->make(DaemonHttpRunner::class, [
'pauseExecution' => null, 'pauseExecution' => null,
'callSelf' => null, 'callSelf' => null,
]); ]);
$this->settings->set(CronHelper::DAEMON_SETTING, $data); $this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon_http_runner->__construct($daemon); $daemon_http_runner->__construct($daemon, new SettingsController());
$daemon_http_runner->run($data); $daemon_http_runner->run($data);
$updated_daemon = $this->settings->get(CronHelper::DAEMON_SETTING); $updated_daemon = $this->settings->get(CronHelper::DAEMON_SETTING);
expect($updated_daemon['last_error'][0]['message'])->equals('Message'); expect($updated_daemon['last_error'][0]['message'])->equals('Message');
@ -102,7 +105,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123, 'token' => 123,
]; ];
$this->settings->set(CronHelper::DAEMON_SETTING, $data); $this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon_http_runner->__construct($daemon); $daemon_http_runner->__construct($daemon, new SettingsController());
$daemon_http_runner->run($data); $daemon_http_runner->run($data);
} }
@ -124,7 +127,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123, 'token' => 123,
]; ];
$this->settings->set(CronHelper::DAEMON_SETTING, $data); $this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon->__construct(new Daemon($workers_factory_mock)); $daemon->__construct(new Daemon($workers_factory_mock), new SettingsController());
$daemon->run($data); $daemon->run($data);
} }
@ -148,7 +151,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123, 'token' => 123,
]; ];
$this->settings->set(CronHelper::DAEMON_SETTING, $data); $this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon->__construct(new Daemon($workers_factory_mock)); $daemon->__construct(new Daemon($workers_factory_mock), new SettingsController());
$daemon->run($data); $daemon->run($data);
$data_after_run = $this->settings->get(CronHelper::DAEMON_SETTING); $data_after_run = $this->settings->get(CronHelper::DAEMON_SETTING);
expect($data_after_run['token'])->equals(567); expect($data_after_run['token'])->equals(567);
@ -165,10 +168,30 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'status' => CronHelper::DAEMON_STATUS_INACTIVE, 'status' => CronHelper::DAEMON_STATUS_INACTIVE,
]; ];
$this->settings->set(CronHelper::DAEMON_SETTING, $data); $this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon->__construct($this->makeEmpty(Daemon::class)); $daemon->__construct($this->makeEmpty(Daemon::class), new SettingsController());
$daemon->run($data); $daemon->run($data);
} }
function testItTerminatesExecutionWhenWPTriggerStopsCron() {
$workers_factory_mock = $this->createWorkersFactoryMock();
$daemon = new Daemon($workers_factory_mock);
$daemon_http_runner = $this->make(DaemonHttpRunner::class, [
'checkWPTriggerExecutionRequirements' => false,
'pauseExecution' => null,
'terminateRequest' => Expected::exactly(1),
'callSelf' => Expected::never(),
]);
$data = [
'token' => 123,
];
$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->run($data);
WPFunctions::get()->removeAllFilters('mailpoet_cron_enable_self_deactivation');
}
function testItUpdatesDaemonTokenDuringExecution() { function testItUpdatesDaemonTokenDuringExecution() {
$daemon_http_runner = $this->make(DaemonHttpRunner::class, [ $daemon_http_runner = $this->make(DaemonHttpRunner::class, [
'pauseExecution' => null, 'pauseExecution' => null,
@ -179,7 +202,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123, 'token' => 123,
]; ];
$this->settings->set(CronHelper::DAEMON_SETTING, $data); $this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon_http_runner->__construct(new Daemon($this->createWorkersFactoryMock())); $daemon_http_runner->__construct(new Daemon($this->createWorkersFactoryMock()), new SettingsController());
$daemon_http_runner->run($data); $daemon_http_runner->run($data);
$updated_daemon = $this->settings->get(CronHelper::DAEMON_SETTING); $updated_daemon = $this->settings->get(CronHelper::DAEMON_SETTING);
expect($updated_daemon['token'])->equals($daemon_http_runner->token); expect($updated_daemon['token'])->equals($daemon_http_runner->token);
@ -200,7 +223,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
]); ]);
$daemon = new Daemon($workers_factory_mock); $daemon = new Daemon($workers_factory_mock);
$daemon_http_runner = $this->make(new DaemonHttpRunner($daemon), [ $daemon_http_runner = $this->make(DaemonHttpRunner::class, [
'pauseExecution' => null, 'pauseExecution' => null,
'callSelf' => null, 'callSelf' => null,
]); ]);
@ -209,7 +232,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
]; ];
$now = time(); $now = time();
$this->settings->set(CronHelper::DAEMON_SETTING, $data); $this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon_http_runner->__construct($daemon); $daemon_http_runner->__construct($daemon, new SettingsController());
$daemon_http_runner->run($data); $daemon_http_runner->run($data);
$updated_daemon = $this->settings->get(CronHelper::DAEMON_SETTING); $updated_daemon = $this->settings->get(CronHelper::DAEMON_SETTING);
expect($updated_daemon['run_started_at'])->greaterOrEquals($now); expect($updated_daemon['run_started_at'])->greaterOrEquals($now);
@ -231,7 +254,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
'token' => 123, 'token' => 123,
]; ];
$this->settings->set(CronHelper::DAEMON_SETTING, $data); $this->settings->set(CronHelper::DAEMON_SETTING, $data);
$daemon->__construct(new Daemon($this->createWorkersFactoryMock())); $daemon->__construct(new Daemon($this->createWorkersFactoryMock()), new SettingsController());
$daemon->run($data); $daemon->run($data);
expect(ignore_user_abort())->equals(1); expect(ignore_user_abort())->equals(1);
} }