Split cron daemon into 2 classes
[MAILPOET-1538]
This commit is contained in:
68
lib/Cron/Daemon.php
Normal file
68
lib/Cron/Daemon.php
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Cron;
|
||||||
|
use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
|
||||||
|
use MailPoet\Cron\Workers\SendingQueue\Migration as MigrationWorker;
|
||||||
|
use MailPoet\Cron\Workers\SendingQueue\SendingErrorHandler;
|
||||||
|
use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
|
||||||
|
use MailPoet\Cron\Workers\Bounce as BounceWorker;
|
||||||
|
use MailPoet\Cron\Workers\KeyCheck\PremiumKeyCheck as PremiumKeyCheckWorker;
|
||||||
|
use MailPoet\Cron\Workers\KeyCheck\SendingServiceKeyCheck as SendingServiceKeyCheckWorker;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
|
class Daemon {
|
||||||
|
public $timer;
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
$this->timer = microtime(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run($settings_daemon_data) {
|
||||||
|
$settings_daemon_data['run_started_at'] = time();
|
||||||
|
CronHelper::saveDaemon($settings_daemon_data);
|
||||||
|
try {
|
||||||
|
$this->executeMigrationWorker();
|
||||||
|
$this->executeScheduleWorker();
|
||||||
|
$this->executeQueueWorker();
|
||||||
|
$this->executeSendingServiceKeyCheckWorker();
|
||||||
|
$this->executePremiumKeyCheckWorker();
|
||||||
|
$this->executeBounceWorker();
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
CronHelper::saveDaemonLastError($e->getMessage());
|
||||||
|
}
|
||||||
|
// Log successful execution
|
||||||
|
CronHelper::saveDaemonRunCompleted(time());
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeScheduleWorker() {
|
||||||
|
$scheduler = new SchedulerWorker($this->timer);
|
||||||
|
return $scheduler->process();
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeQueueWorker() {
|
||||||
|
$queue = new SendingQueueWorker(new SendingErrorHandler(), $this->timer);
|
||||||
|
return $queue->process();
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeSendingServiceKeyCheckWorker() {
|
||||||
|
$worker = new SendingServiceKeyCheckWorker($this->timer);
|
||||||
|
return $worker->process();
|
||||||
|
}
|
||||||
|
|
||||||
|
function executePremiumKeyCheckWorker() {
|
||||||
|
$worker = new PremiumKeyCheckWorker($this->timer);
|
||||||
|
return $worker->process();
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeBounceWorker() {
|
||||||
|
$bounce = new BounceWorker($this->timer);
|
||||||
|
return $bounce->process();
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeMigrationWorker() {
|
||||||
|
$migration = new MigrationWorker($this->timer);
|
||||||
|
return $migration->process();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,28 +1,29 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Cron;
|
namespace MailPoet\Cron;
|
||||||
use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
|
|
||||||
use MailPoet\Cron\Workers\SendingQueue\Migration as MigrationWorker;
|
|
||||||
use MailPoet\Cron\Workers\SendingQueue\SendingErrorHandler;
|
|
||||||
use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
|
|
||||||
use MailPoet\Cron\Workers\Bounce as BounceWorker;
|
|
||||||
use MailPoet\Cron\Workers\KeyCheck\PremiumKeyCheck as PremiumKeyCheckWorker;
|
|
||||||
use MailPoet\Cron\Workers\KeyCheck\SendingServiceKeyCheck as SendingServiceKeyCheckWorker;
|
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
class DaemonHttpRunner {
|
class DaemonHttpRunner {
|
||||||
public $daemon;
|
public $settings_daemon_data;
|
||||||
public $request_data;
|
public $request_data;
|
||||||
public $timer;
|
public $timer;
|
||||||
|
public $token;
|
||||||
|
|
||||||
|
/** @var Daemon */
|
||||||
|
private $daemon;
|
||||||
|
|
||||||
const PING_SUCCESS_RESPONSE = 'pong';
|
const PING_SUCCESS_RESPONSE = 'pong';
|
||||||
|
|
||||||
function __construct($request_data = false) {
|
function __construct($request_data = false, $daemon = null) {
|
||||||
$this->request_data = $request_data;
|
$this->request_data = $request_data;
|
||||||
$this->daemon = 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;
|
||||||
|
if(!$daemon) {
|
||||||
|
$this->daemon = new Daemon($this->settings_daemon_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ping() {
|
function ping() {
|
||||||
@@ -39,11 +40,11 @@ class DaemonHttpRunner {
|
|||||||
if(!$this->request_data) {
|
if(!$this->request_data) {
|
||||||
$error = __('Invalid or missing request data.', 'mailpoet');
|
$error = __('Invalid or missing request data.', 'mailpoet');
|
||||||
} else {
|
} else {
|
||||||
if(!$this->daemon) {
|
if(!$this->settings_daemon_data) {
|
||||||
$error = __('Daemon does not exist.', 'mailpoet');
|
$error = __('Daemon does not exist.', 'mailpoet');
|
||||||
} else {
|
} else {
|
||||||
if(!isset($this->request_data['token']) ||
|
if(!isset($this->request_data['token']) ||
|
||||||
$this->request_data['token'] !== $this->daemon['token']
|
$this->request_data['token'] !== $this->settings_daemon_data['token']
|
||||||
) {
|
) {
|
||||||
$error = 'Invalid or missing token.';
|
$error = 'Invalid or missing token.';
|
||||||
}
|
}
|
||||||
@@ -52,22 +53,8 @@ class DaemonHttpRunner {
|
|||||||
if(!empty($error)) {
|
if(!empty($error)) {
|
||||||
return $this->abortWithError($error);
|
return $this->abortWithError($error);
|
||||||
}
|
}
|
||||||
$daemon = $this->daemon;
|
$this->settings_daemon_data['token'] = $this->token;
|
||||||
$daemon['token'] = $this->token;
|
$this->daemon->run($this->settings_daemon_data);
|
||||||
$daemon['run_started_at'] = time();
|
|
||||||
CronHelper::saveDaemon($daemon);
|
|
||||||
try {
|
|
||||||
$this->executeMigrationWorker();
|
|
||||||
$this->executeScheduleWorker();
|
|
||||||
$this->executeQueueWorker();
|
|
||||||
$this->executeSendingServiceKeyCheckWorker();
|
|
||||||
$this->executePremiumKeyCheckWorker();
|
|
||||||
$this->executeBounceWorker();
|
|
||||||
} catch(\Exception $e) {
|
|
||||||
CronHelper::saveDaemonLastError($e->getMessage());
|
|
||||||
}
|
|
||||||
// Log successful execution
|
|
||||||
CronHelper::saveDaemonRunCompleted(time());
|
|
||||||
// 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;
|
||||||
@@ -75,8 +62,8 @@ class DaemonHttpRunner {
|
|||||||
$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
|
||||||
$daemon = CronHelper::getDaemon();
|
$settings_daemon_data = CronHelper::getDaemon();
|
||||||
if($this->shouldTerminateExecution($daemon)) {
|
if($this->shouldTerminateExecution($settings_daemon_data)) {
|
||||||
return $this->terminateRequest();
|
return $this->terminateRequest();
|
||||||
}
|
}
|
||||||
return $this->callSelf();
|
return $this->callSelf();
|
||||||
@@ -86,39 +73,9 @@ class DaemonHttpRunner {
|
|||||||
return sleep($pause_time);
|
return sleep($pause_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
function executeScheduleWorker() {
|
|
||||||
$scheduler = new SchedulerWorker($this->timer);
|
|
||||||
return $scheduler->process();
|
|
||||||
}
|
|
||||||
|
|
||||||
function executeQueueWorker() {
|
|
||||||
$queue = new SendingQueueWorker(new SendingErrorHandler(), $this->timer);
|
|
||||||
return $queue->process();
|
|
||||||
}
|
|
||||||
|
|
||||||
function executeSendingServiceKeyCheckWorker() {
|
|
||||||
$worker = new SendingServiceKeyCheckWorker($this->timer);
|
|
||||||
return $worker->process();
|
|
||||||
}
|
|
||||||
|
|
||||||
function executePremiumKeyCheckWorker() {
|
|
||||||
$worker = new PremiumKeyCheckWorker($this->timer);
|
|
||||||
return $worker->process();
|
|
||||||
}
|
|
||||||
|
|
||||||
function executeBounceWorker() {
|
|
||||||
$bounce = new BounceWorker($this->timer);
|
|
||||||
return $bounce->process();
|
|
||||||
}
|
|
||||||
|
|
||||||
function executeMigrationWorker() {
|
|
||||||
$migration = new MigrationWorker($this->timer);
|
|
||||||
return $migration->process();
|
|
||||||
}
|
|
||||||
|
|
||||||
function callSelf() {
|
function callSelf() {
|
||||||
CronHelper::accessDaemon($this->token);
|
CronHelper::accessDaemon($this->token);
|
||||||
return $this->terminateRequest();
|
$this->terminateRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
function abortWithError($message) {
|
function abortWithError($message) {
|
||||||
@@ -131,12 +88,14 @@ class DaemonHttpRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param array|null $settings_daemon_data
|
||||||
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
private function shouldTerminateExecution(array $daemon = null) {
|
private function shouldTerminateExecution(array $settings_daemon_data = null) {
|
||||||
return !$daemon ||
|
return !$settings_daemon_data ||
|
||||||
$daemon['token'] !== $this->token ||
|
$settings_daemon_data['token'] !== $this->token ||
|
||||||
(isset($daemon['status']) && $daemon['status'] !== CronHelper::DAEMON_STATUS_ACTIVE);
|
(isset($settings_daemon_data['status']) && $settings_daemon_data['status'] !== CronHelper::DAEMON_STATUS_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function addCacheHeaders() {
|
private function addCacheHeaders() {
|
||||||
|
@@ -30,5 +30,10 @@ if(version_compare(phpversion(), '5.5.0', '<')) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$trigger = new \MailPoet\Cron\Triggers\MailPoet();
|
if(strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
|
||||||
$trigger->run();
|
set_time_limit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = \MailPoet\Cron\CronHelper::createDaemon(null);
|
||||||
|
$trigger = new \MailPoet\Cron\Daemon();
|
||||||
|
$trigger->run($data);
|
||||||
|
227
tests/unit/Cron/DaemonHttpRunnerTest.php
Normal file
227
tests/unit/Cron/DaemonHttpRunnerTest.php
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Test\Cron;
|
||||||
|
|
||||||
|
use Codeception\Stub;
|
||||||
|
use Codeception\Stub\Expected;
|
||||||
|
use MailPoet\Cron\CronHelper;
|
||||||
|
use MailPoet\Cron\Daemon;
|
||||||
|
use MailPoet\Cron\DaemonHttpRunner;
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
|
||||||
|
class DaemonHttpRunnerTest extends \MailPoetTest {
|
||||||
|
function testItConstructs() {
|
||||||
|
Setting::setValue(
|
||||||
|
CronHelper::DAEMON_SETTING,
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
$daemon = new DaemonHttpRunner($request_data = 'request data');
|
||||||
|
expect($daemon->request_data)->equals('request data');
|
||||||
|
expect(strlen($daemon->timer))->greaterOrEquals(5);
|
||||||
|
expect(strlen($daemon->token))->greaterOrEquals(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItDoesNotRunWithoutRequestData() {
|
||||||
|
$daemon = Stub::construct(
|
||||||
|
new DaemonHttpRunner(),
|
||||||
|
array(),
|
||||||
|
array(
|
||||||
|
'abortWithError' => function($message) {
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$daemon->request_data = false;
|
||||||
|
expect($daemon->run())->equals('Invalid or missing request data.');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItDoesNotRunWhenThereIsInvalidOrMissingToken() {
|
||||||
|
$daemon = Stub::construct(
|
||||||
|
new DaemonHttpRunner(),
|
||||||
|
array(),
|
||||||
|
array(
|
||||||
|
'abortWithError' => function($message) {
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$daemon->settings_daemon_data = array(
|
||||||
|
'token' => 123
|
||||||
|
);
|
||||||
|
$daemon->request_data = array('token' => 456);
|
||||||
|
expect($daemon->run())->equals('Invalid or missing token.');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItStoresErrorMessageAndContinuesExecutionWhenWorkersThrowException() {
|
||||||
|
$data = array(
|
||||||
|
'token' => 123
|
||||||
|
);
|
||||||
|
$daemon = Stub::make(new Daemon(), array(
|
||||||
|
'executeScheduleWorker' => function() {
|
||||||
|
throw new \Exception('Message');
|
||||||
|
},
|
||||||
|
'executeQueueWorker' => function() {
|
||||||
|
throw new \Exception();
|
||||||
|
},
|
||||||
|
), $this);
|
||||||
|
$daemon_http_runner = Stub::make(new DaemonHttpRunner($data, $daemon), array(
|
||||||
|
'pauseExecution' => null,
|
||||||
|
'callSelf' => null
|
||||||
|
), $this);
|
||||||
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
|
$daemon_http_runner->__construct($data, $daemon);
|
||||||
|
$daemon_http_runner->run();
|
||||||
|
$updated_daemon = Setting::getValue(CronHelper::DAEMON_SETTING);
|
||||||
|
expect($updated_daemon['last_error'])->greaterOrEquals('Message');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItCanPauseExecution() {
|
||||||
|
$daemon = Stub::make(new Daemon(), array(
|
||||||
|
'executeScheduleWorker' => null,
|
||||||
|
'executeQueueWorker' => null,
|
||||||
|
), $this);
|
||||||
|
$daemon_http_runner = Stub::make(new DaemonHttpRunner(true, $daemon), array(
|
||||||
|
'pauseExecution' => Expected::exactly(1, function($pause_delay) {
|
||||||
|
expect($pause_delay)->lessThan(CronHelper::DAEMON_EXECUTION_LIMIT);
|
||||||
|
expect($pause_delay)->greaterThan(CronHelper::DAEMON_EXECUTION_LIMIT - 1);
|
||||||
|
}),
|
||||||
|
'callSelf' => null
|
||||||
|
), $this);
|
||||||
|
$data = array(
|
||||||
|
'token' => 123
|
||||||
|
);
|
||||||
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
|
$daemon_http_runner->__construct($data, $daemon);
|
||||||
|
$daemon_http_runner->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function testItTerminatesExecutionWhenDaemonIsDeleted() {
|
||||||
|
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
||||||
|
'executeScheduleWorker' => function() {
|
||||||
|
Setting::deleteValue(CronHelper::DAEMON_SETTING);
|
||||||
|
},
|
||||||
|
'executeQueueWorker' => null,
|
||||||
|
'pauseExecution' => null,
|
||||||
|
'terminateRequest' => Expected::exactly(1)
|
||||||
|
), $this);
|
||||||
|
$data = array(
|
||||||
|
'token' => 123
|
||||||
|
);
|
||||||
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
|
$daemon->__construct($data);
|
||||||
|
$daemon->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItTerminatesExecutionWhenDaemonTokenChangesAndKeepsChangedToken() {
|
||||||
|
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
||||||
|
'executeScheduleWorker' => function() {
|
||||||
|
Setting::setValue(
|
||||||
|
CronHelper::DAEMON_SETTING,
|
||||||
|
array('token' => 567)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'executeQueueWorker' => null,
|
||||||
|
'pauseExecution' => null,
|
||||||
|
'terminateRequest' => Expected::exactly(1)
|
||||||
|
), $this);
|
||||||
|
$data = array(
|
||||||
|
'token' => 123
|
||||||
|
);
|
||||||
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
|
$daemon->__construct($data);
|
||||||
|
$daemon->run();
|
||||||
|
$data_after_run = Setting::getValue(CronHelper::DAEMON_SETTING);
|
||||||
|
expect($data_after_run['token'], 567);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItTerminatesExecutionWhenDaemonIsDeactivated() {
|
||||||
|
$daemon = Stub::make(new DaemonHttpRunner(true), [
|
||||||
|
'executeScheduleWorker' => null,
|
||||||
|
'executeQueueWorker' => null,
|
||||||
|
'pauseExecution' => null,
|
||||||
|
'terminateRequest' => Expected::exactly(1)
|
||||||
|
], $this);
|
||||||
|
$data = [
|
||||||
|
'token' => 123,
|
||||||
|
'status' => CronHelper::DAEMON_STATUS_INACTIVE,
|
||||||
|
];
|
||||||
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
|
$daemon->__construct($data);
|
||||||
|
$daemon->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItUpdatesDaemonTokenDuringExecution() {
|
||||||
|
$daemon_http_runner = Stub::make(new DaemonHttpRunner(true), array(
|
||||||
|
'executeScheduleWorker' => null,
|
||||||
|
'executeQueueWorker' => null,
|
||||||
|
'pauseExecution' => null,
|
||||||
|
'callSelf' => null
|
||||||
|
), $this);
|
||||||
|
$data = array(
|
||||||
|
'token' => 123
|
||||||
|
);
|
||||||
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
|
$daemon_http_runner->__construct($data);
|
||||||
|
$daemon_http_runner->run();
|
||||||
|
$updated_daemon = Setting::getValue(CronHelper::DAEMON_SETTING);
|
||||||
|
expect($updated_daemon['token'])->equals($daemon_http_runner->token);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItUpdatesTimestampsDuringExecution() {
|
||||||
|
$daemon = Stub::make(new Daemon(), array(
|
||||||
|
'executeScheduleWorker' => function() {
|
||||||
|
sleep(2);
|
||||||
|
},
|
||||||
|
'executeQueueWorker' => null,
|
||||||
|
), $this);
|
||||||
|
$daemon_http_runner = Stub::make(new DaemonHttpRunner(true, $daemon), array(
|
||||||
|
'pauseExecution' => null,
|
||||||
|
'callSelf' => null
|
||||||
|
), $this);
|
||||||
|
$data = array(
|
||||||
|
'token' => 123,
|
||||||
|
);
|
||||||
|
$now = time();
|
||||||
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
|
$daemon_http_runner->__construct($data, $daemon);
|
||||||
|
$daemon_http_runner->run();
|
||||||
|
$updated_daemon = Setting::getValue(CronHelper::DAEMON_SETTING);
|
||||||
|
expect($updated_daemon['run_started_at'])->greaterOrEquals($now);
|
||||||
|
expect($updated_daemon['run_started_at'])->lessThan($now + 2);
|
||||||
|
expect($updated_daemon['run_completed_at'])->greaterOrEquals($now + 2);
|
||||||
|
expect($updated_daemon['run_completed_at'])->lessThan($now + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItCanRun() {
|
||||||
|
ignore_user_abort(0);
|
||||||
|
expect(ignore_user_abort())->equals(0);
|
||||||
|
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
||||||
|
'pauseExecution' => null,
|
||||||
|
// workers should be executed
|
||||||
|
'executeScheduleWorker' => Expected::exactly(1),
|
||||||
|
'executeQueueWorker' => Expected::exactly(1),
|
||||||
|
// daemon should call itself
|
||||||
|
'callSelf' => Expected::exactly(1),
|
||||||
|
), $this);
|
||||||
|
$data = array(
|
||||||
|
'token' => 123
|
||||||
|
);
|
||||||
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
|
$daemon->__construct($data);
|
||||||
|
$daemon->run();
|
||||||
|
expect(ignore_user_abort())->equals(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItRespondsToPingRequest() {
|
||||||
|
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
||||||
|
'terminateRequest' => Expected::exactly(1, function($message) {
|
||||||
|
expect($message)->equals('pong');
|
||||||
|
})
|
||||||
|
), $this);
|
||||||
|
$daemon->ping();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _after() {
|
||||||
|
\ORM::raw_execute('TRUNCATE ' . Setting::$_table);
|
||||||
|
}
|
||||||
|
}
|
@@ -5,68 +5,13 @@ use Codeception\Stub;
|
|||||||
use Codeception\Stub\Expected;
|
use Codeception\Stub\Expected;
|
||||||
use MailPoet\Cron\CronHelper;
|
use MailPoet\Cron\CronHelper;
|
||||||
use MailPoet\Cron\DaemonHttpRunner;
|
use MailPoet\Cron\DaemonHttpRunner;
|
||||||
|
use MailPoet\Cron\Daemon;
|
||||||
use MailPoet\Models\Setting;
|
use MailPoet\Models\Setting;
|
||||||
|
|
||||||
class DaemonHttpRunnerTest extends \MailPoetTest {
|
class DaemonTest extends \MailPoetTest {
|
||||||
function testItConstructs() {
|
|
||||||
Setting::setValue(
|
|
||||||
CronHelper::DAEMON_SETTING,
|
|
||||||
'daemon object'
|
|
||||||
);
|
|
||||||
$daemon = new DaemonHttpRunner($request_data = 'request data');
|
|
||||||
expect($daemon->daemon)->equals('daemon object');
|
|
||||||
expect($daemon->request_data)->equals('request data');
|
|
||||||
expect(strlen($daemon->timer))->greaterOrEquals(5);
|
|
||||||
expect(strlen($daemon->token))->greaterOrEquals(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItDoesNotRunWithoutRequestData() {
|
|
||||||
$daemon = Stub::construct(
|
|
||||||
new DaemonHttpRunner(),
|
|
||||||
array(),
|
|
||||||
array(
|
|
||||||
'abortWithError' => function($message) {
|
|
||||||
return $message;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$daemon->request_data = false;
|
|
||||||
expect($daemon->run())->equals('Invalid or missing request data.');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItDoesNotRunWhenDaemonIsNotFound() {
|
|
||||||
$daemon = Stub::construct(
|
|
||||||
new DaemonHttpRunner(),
|
|
||||||
array(),
|
|
||||||
array(
|
|
||||||
'abortWithError' => function($message) {
|
|
||||||
return $message;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$daemon->request_data = true;
|
|
||||||
expect($daemon->run())->equals('Daemon does not exist.');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItDoesNotRunWhenThereIsInvalidOrMissingToken() {
|
|
||||||
$daemon = Stub::construct(
|
|
||||||
new DaemonHttpRunner(),
|
|
||||||
array(),
|
|
||||||
array(
|
|
||||||
'abortWithError' => function($message) {
|
|
||||||
return $message;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$daemon->daemon = array(
|
|
||||||
'token' => 123
|
|
||||||
);
|
|
||||||
$daemon->request_data = array('token' => 456);
|
|
||||||
expect($daemon->run())->equals('Invalid or missing token.');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItCanExecuteWorkers() {
|
function testItCanExecuteWorkers() {
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
$daemon = Stub::make(new Daemon(), array(
|
||||||
'executeScheduleWorker' => Expected::exactly(1),
|
'executeScheduleWorker' => Expected::exactly(1),
|
||||||
'executeQueueWorker' => Expected::exactly(1),
|
'executeQueueWorker' => Expected::exactly(1),
|
||||||
'pauseExecution' => null,
|
'pauseExecution' => null,
|
||||||
@@ -77,148 +22,11 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
|
|||||||
);
|
);
|
||||||
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
$daemon->__construct($data);
|
$daemon->__construct($data);
|
||||||
$daemon->run();
|
$daemon->run([]);
|
||||||
}
|
|
||||||
|
|
||||||
function testItStoresErrorMessageAndContinuesExecutionWhenWorkersThrowException() {
|
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
|
||||||
'executeScheduleWorker' => function() {
|
|
||||||
throw new \Exception('Message');
|
|
||||||
},
|
|
||||||
'executeQueueWorker' => function() {
|
|
||||||
throw new \Exception();
|
|
||||||
},
|
|
||||||
'pauseExecution' => null,
|
|
||||||
'callSelf' => null
|
|
||||||
), $this);
|
|
||||||
$data = array(
|
|
||||||
'token' => 123
|
|
||||||
);
|
|
||||||
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
|
||||||
$daemon->__construct($data);
|
|
||||||
$daemon->run();
|
|
||||||
$updated_daemon = Setting::getValue(CronHelper::DAEMON_SETTING);
|
|
||||||
expect($updated_daemon['last_error'])->greaterOrEquals('Message');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItCanPauseExecution() {
|
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
|
||||||
'executeScheduleWorker' => null,
|
|
||||||
'executeQueueWorker' => null,
|
|
||||||
'pauseExecution' => Expected::exactly(1, function($pause_delay) {
|
|
||||||
expect($pause_delay)->lessThan(CronHelper::DAEMON_EXECUTION_LIMIT);
|
|
||||||
expect($pause_delay)->greaterThan(CronHelper::DAEMON_EXECUTION_LIMIT - 1);
|
|
||||||
}),
|
|
||||||
'callSelf' => null
|
|
||||||
), $this);
|
|
||||||
$data = array(
|
|
||||||
'token' => 123
|
|
||||||
);
|
|
||||||
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
|
||||||
$daemon->__construct($data);
|
|
||||||
$daemon->run();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testItTerminatesExecutionWhenDaemonIsDeleted() {
|
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
|
||||||
'executeScheduleWorker' => function() {
|
|
||||||
Setting::deleteValue(CronHelper::DAEMON_SETTING);
|
|
||||||
},
|
|
||||||
'executeQueueWorker' => null,
|
|
||||||
'pauseExecution' => null,
|
|
||||||
'terminateRequest' => Expected::exactly(1)
|
|
||||||
), $this);
|
|
||||||
$data = array(
|
|
||||||
'token' => 123
|
|
||||||
);
|
|
||||||
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
|
||||||
$daemon->__construct($data);
|
|
||||||
$daemon->run();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItTerminatesExecutionWhenDaemonTokenChangesAndKeepsChangedToken() {
|
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
|
||||||
'executeScheduleWorker' => function() {
|
|
||||||
Setting::setValue(
|
|
||||||
CronHelper::DAEMON_SETTING,
|
|
||||||
array('token' => 567)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
'executeQueueWorker' => null,
|
|
||||||
'pauseExecution' => null,
|
|
||||||
'terminateRequest' => Expected::exactly(1)
|
|
||||||
), $this);
|
|
||||||
$data = array(
|
|
||||||
'token' => 123
|
|
||||||
);
|
|
||||||
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
|
||||||
$daemon->__construct($data);
|
|
||||||
$daemon->run();
|
|
||||||
$data_after_run = Setting::getValue(CronHelper::DAEMON_SETTING);
|
|
||||||
expect($data_after_run['token'], 567);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItTerminatesExecutionWhenDaemonIsDeactivated() {
|
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), [
|
|
||||||
'executeScheduleWorker' => null,
|
|
||||||
'executeQueueWorker' => null,
|
|
||||||
'pauseExecution' => null,
|
|
||||||
'terminateRequest' => Expected::exactly(1)
|
|
||||||
], $this);
|
|
||||||
$data = [
|
|
||||||
'token' => 123,
|
|
||||||
'status' => CronHelper::DAEMON_STATUS_INACTIVE,
|
|
||||||
];
|
|
||||||
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
|
||||||
$daemon->__construct($data);
|
|
||||||
$daemon->run();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItUpdatesDaemonTokenDuringExecution() {
|
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
|
||||||
'executeScheduleWorker' => null,
|
|
||||||
'executeQueueWorker' => null,
|
|
||||||
'pauseExecution' => null,
|
|
||||||
'callSelf' => null
|
|
||||||
), $this);
|
|
||||||
$data = array(
|
|
||||||
'token' => 123
|
|
||||||
);
|
|
||||||
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
|
||||||
$daemon->__construct($data);
|
|
||||||
$daemon->run();
|
|
||||||
$updated_daemon = Setting::getValue(CronHelper::DAEMON_SETTING);
|
|
||||||
expect($updated_daemon['token'])->equals($daemon->token);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItUpdatesTimestampsDuringExecution() {
|
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
|
||||||
'executeScheduleWorker' => function() {
|
|
||||||
sleep(2);
|
|
||||||
},
|
|
||||||
'executeQueueWorker' => null,
|
|
||||||
'pauseExecution' => null,
|
|
||||||
'callSelf' => null
|
|
||||||
), $this);
|
|
||||||
$data = array(
|
|
||||||
'token' => 123,
|
|
||||||
);
|
|
||||||
$now = time();
|
|
||||||
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
|
||||||
$daemon->__construct($data);
|
|
||||||
$daemon->run();
|
|
||||||
$updated_daemon = Setting::getValue(CronHelper::DAEMON_SETTING);
|
|
||||||
expect($updated_daemon['run_started_at'])->greaterOrEquals($now);
|
|
||||||
expect($updated_daemon['run_started_at'])->lessThan($now + 2);
|
|
||||||
expect($updated_daemon['run_completed_at'])->greaterOrEquals($now + 2);
|
|
||||||
expect($updated_daemon['run_completed_at'])->lessThan($now + 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanRun() {
|
function testItCanRun() {
|
||||||
ignore_user_abort(0);
|
$daemon = Stub::make(new Daemon(), array(
|
||||||
expect(ignore_user_abort())->equals(0);
|
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
|
||||||
'pauseExecution' => null,
|
'pauseExecution' => null,
|
||||||
// workers should be executed
|
// workers should be executed
|
||||||
'executeScheduleWorker' => Expected::exactly(1),
|
'executeScheduleWorker' => Expected::exactly(1),
|
||||||
@@ -230,18 +38,8 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
|
|||||||
'token' => 123
|
'token' => 123
|
||||||
);
|
);
|
||||||
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
Setting::setValue(CronHelper::DAEMON_SETTING, $data);
|
||||||
$daemon->__construct($data);
|
$daemon->__construct();
|
||||||
$daemon->run();
|
$daemon->run($data);
|
||||||
expect(ignore_user_abort())->equals(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItRespondsToPingRequest() {
|
|
||||||
$daemon = Stub::make(new DaemonHttpRunner(true), array(
|
|
||||||
'terminateRequest' => Expected::exactly(1, function($message) {
|
|
||||||
expect($message)->equals('pong');
|
|
||||||
})
|
|
||||||
), $this);
|
|
||||||
$daemon->ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _after() {
|
function _after() {
|
||||||
|
Reference in New Issue
Block a user