- Fixes blocking HTTP request issue

- Simplifies cron supervisor
This commit is contained in:
Vlad
2016-07-25 11:54:11 -04:00
parent 3cc5812c1d
commit 3f5c36d2d4
6 changed files with 29 additions and 156 deletions

View File

@ -21,8 +21,6 @@ define(
action: 'getStatus' action: 'getStatus'
}) })
.done(function(response) { .done(function(response) {
jQuery('.button-primary')
.removeClass('disabled');
if(response.status !== undefined) { if(response.status !== undefined) {
this.setState(response); this.setState(response);
} else { } else {
@ -36,22 +34,6 @@ define(
setInterval(this.getCronData, 5000); setInterval(this.getCronData, 5000);
} }
}, },
controlCron: function(action) {
if(jQuery('.button-primary').hasClass('disabled')) {
return;
}
jQuery('.button-primary')
.addClass('disabled');
MailPoet.Ajax.post({
endpoint: 'cron',
action: action,
})
.done(function(response) {
if(!response.result) {
MailPoet.Notice.error(MailPoet.I18n.t('daemonControlError'));
}
}.bind(this));
},
render: function() { render: function() {
switch(this.state.status) { switch(this.state.status) {
case 'loading': case 'loading':
@ -60,48 +42,18 @@ define(
{MailPoet.I18n.t('loadingDaemonStatus')} {MailPoet.I18n.t('loadingDaemonStatus')}
</div> </div>
); );
case 'started':
return(
<div>
{MailPoet.I18n.t('cronDaemonIsRunning')}
<br/>
<br/>
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'stop')}>{MailPoet.I18n.t('stop')}</a>
</div>
);
break;
case 'starting':
case 'stopping':
return(
<div>
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
</div>
);
break;
case 'stopped':
return(
<div>
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
<br />
<br />
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'start')}>{MailPoet.I18n.t('start')}</a>
</div>
);
break;
case 'wordpress_task_scheduler_enabled':
return(
<div>
{MailPoet.I18n.t('wordpressTaskSchedulerEnabled')}
</div>
);
break;
case false: case false:
return( return(
<div> <div>
{MailPoet.I18n.t('daemonNotRunning')} {MailPoet.I18n.t('daemonNotRunning')}
</div> </div>
); );
break; default:
return(
<div>
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
</div>
);
} }
} }
}); });

View File

@ -2,31 +2,11 @@
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints;
use MailPoet\Cron\CronHelper; use MailPoet\Cron\CronHelper;
use MailPoet\Cron\CronTrigger;
use MailPoet\Cron\Supervisor;
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class Cron { class Cron {
function start() {
$supervisor = new Supervisor($force_run = true);
return $supervisor->checkDaemon();
}
function stop() {
$daemon = CronHelper::getDaemon();
if(!$daemon || $daemon['status'] !== 'started') {
$result = false;
} else {
$daemon['status'] = 'stopping';
$result = CronHelper::saveDaemon($daemon);
}
return array(
'result' => $result
);
}
function getStatus() { function getStatus() {
$daemon = Setting::getValue(CronHelper::DAEMON_SETTING); $daemon = Setting::getValue(CronHelper::DAEMON_SETTING);
return ($daemon) ? return ($daemon) ?

View File

@ -11,10 +11,10 @@ if(!defined('ABSPATH')) exit;
class CronHelper { class CronHelper {
const DAEMON_EXECUTION_LIMIT = 20; const DAEMON_EXECUTION_LIMIT = 20;
const DAEMON_EXECUTION_TIMEOUT = 35; const DAEMON_EXECUTION_TIMEOUT = 35;
const DAEMON_REQUEST_TIMEOUT = 2; const DAEMON_REQUEST_TIMEOUT = 5;
const DAEMON_SETTING = 'cron_daemon'; const DAEMON_SETTING = 'cron_daemon';
static function createDaemon($token) { static function createOrRestartDaemon($token) {
$daemon = array( $daemon = array(
'status' => Daemon::STATUS_STARTING, 'status' => Daemon::STATUS_STARTING,
'token' => $token 'token' => $token
@ -49,7 +49,7 @@ class CronHelper {
return Security::generateRandomString(); return Security::generateRandomString();
} }
static function accessDaemon($token, $timeout = self::DAEMON_REQUEST_TIMEOUT) { static function accessDaemon($token) {
$data = array('token' => $token); $data = array('token' => $token);
$url = FrontRouter::buildRequest( $url = FrontRouter::buildRequest(
QueueEndpoint::ENDPOINT, QueueEndpoint::ENDPOINT,
@ -57,7 +57,9 @@ class CronHelper {
$data $data
); );
$args = array( $args = array(
'timeout' => $timeout, 'blocking' => false,
'sslverify' => false,
'timeout' => self::DAEMON_REQUEST_TIMEOUT,
'user-agent' => 'MailPoet (www.mailpoet.com) Cron' 'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
); );
$result = wp_remote_get($url, $args); $result = wp_remote_get($url, $args);

View File

@ -16,7 +16,6 @@ class Daemon {
const STATUS_STOPPING = 'stopping'; const STATUS_STOPPING = 'stopping';
const STATUS_STARTED = 'started'; const STATUS_STARTED = 'started';
const STATUS_STARTING = 'starting'; const STATUS_STARTING = 'starting';
const REQUEST_TIMEOUT = 5;
private $timer; private $timer;
function __construct($data) { function __construct($data) {
@ -78,13 +77,14 @@ class Daemon {
} }
} }
function abortWithError($message) { function callSelf() {
exit('[mailpoet_cron_error:' . base64_encode($message) . ']'); CronHelper::accessDaemon($this->token);
$this->terminateRequest();
} }
function callSelf() { function abortWithError($message) {
CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT); status_header(404, $message);
$this->terminateRequest(); exit;
} }
function terminateRequest() { function terminateRequest() {

View File

@ -16,77 +16,19 @@ class Supervisor {
function checkDaemon() { function checkDaemon() {
$daemon = $this->daemon; $daemon = $this->daemon;
if(!$daemon) { $execution_timeout_exceeded = ($daemon) ?
$daemon = CronHelper::createDaemon($this->token); (time() - (int)$daemon['updated_at']) > CronHelper::DAEMON_EXECUTION_TIMEOUT :
return $this->runDaemon($daemon); false;
} if(!$daemon || $execution_timeout_exceeded) {
// if the daemon is stopped, return its status and do nothing CronHelper::createOrRestartDaemon($this->token);
if(!$this->force_run &&
isset($daemon['status']) &&
$daemon['status'] === Daemon::STATUS_STOPPED
) {
return $this->formatDaemonStatusMessage($daemon['status']);
}
$elapsed_time = time() - (int)$daemon['updated_at'];
// if it's been less than 40 seconds since last execution and we're not
// force-running the daemon, return its status and do nothing
if($elapsed_time < CronHelper::DAEMON_EXECUTION_TIMEOUT && !$this->force_run) {
return $this->formatDaemonStatusMessage($daemon['status']);
} elseif($elapsed_time < CronHelper::DAEMON_EXECUTION_TIMEOUT &&
$this->force_run &&
in_array($daemon['status'], array(
Daemon::STATUS_STOPPING,
Daemon::STATUS_STARTING
))
) {
// if it's been less than 40 seconds since last execution, we are
// force-running the daemon and it's either being started or stopped,
// return its status and do nothing
return $this->formatDaemonStatusMessage($daemon['status']);
}
// re-create (restart) daemon
CronHelper::createDaemon($this->token);
return $this->runDaemon(); return $this->runDaemon();
} }
return $daemon;
}
function runDaemon() { function runDaemon() {
$request = CronHelper::accessDaemon($this->token); CronHelper::accessDaemon($this->token);
preg_match('/\[(mailpoet_cron_error:.*?)\]/i', $request, $status);
$daemon = CronHelper::getDaemon(); $daemon = CronHelper::getDaemon();
if(!empty($status) || !$daemon) { return $daemon;
if(!$daemon) {
$message = __('Daemon failed to run.');
} else {
list(, $message) = explode(':', $status[0]);
$message = base64_decode($message);
}
return $this->formatResultMessage(
false,
$message
);
}
return $this->formatDaemonStatusMessage($daemon['status']);
}
private function formatDaemonStatusMessage($status) {
return $this->formatResultMessage(
true,
sprintf(
__('Daemon is currently %s.'),
__($status)
)
);
}
private function formatResultMessage($result, $message) {
$formattedResult = array(
'result' => $result
);
if(!$result) {
$formattedResult['errors'] = array($message);
} else {
$formattedResult['message'] = $message;
}
return $formattedResult;
} }
} }

View File

@ -7,12 +7,9 @@
<% block translations %> <% block translations %>
<%= localize({ <%= localize({
'daemonNotRunning': __('Daemon is not running'), 'daemonNotRunning': __('Daemon is not running'),
'wordpressTaskSchedulerEnabled': __('Daemon is not running because WordPress task scheduler is enabled and there are no scheduled or in-progress jobs'),
'daemonControlError': __('Cron daemon error'), 'daemonControlError': __('Cron daemon error'),
'loadingDaemonStatus': __('Loading daemon status...'), 'loadingDaemonStatus': __('Loading daemon status...'),
'cronDaemonIsRunning': __('Cron daemon is running'), 'cronDaemonIsRunning': __('Cron daemon is running'),
'stop': __('Stop'),
'start': __('Start'),
'cronDaemonState': __('Cron is %$1s') 'cronDaemonState': __('Cron is %$1s')
}) %> }) %>
<% endblock %> <% endblock %>