- Implements starting/stopping/pausing daemon
This commit is contained in:
@@ -11,64 +11,89 @@ define(
|
|||||||
MailPoet,
|
MailPoet,
|
||||||
classNames
|
classNames
|
||||||
) {
|
) {
|
||||||
var QueueDaemonControl = React.createClass({
|
var QueueControl = React.createClass({
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return (queueDaemon) ? {
|
return (queueDaemon) ? queueDaemon : null;
|
||||||
status: queueDaemon.status,
|
|
||||||
timeSinceStart: queueDaemon.time_since_start,
|
|
||||||
timeSinceUpdate: queueDaemon.time_since_update,
|
|
||||||
counter: queueDaemon.counter
|
|
||||||
} : null;
|
|
||||||
},
|
},
|
||||||
getDaemonData: function () {
|
getDaemonData: function () {
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'queue',
|
endpoint: 'queue',
|
||||||
action: 'getQueueStatus'
|
action: 'getDaemonStatus'
|
||||||
}).done(function (response) {
|
}).done(function (response) {
|
||||||
this.setState({
|
jQuery('.button-primary').removeClass('disabled');
|
||||||
status: response.status,
|
if (!response) {
|
||||||
timeSinceStart: response.time_since_start,
|
this.replaceState();
|
||||||
timeSinceUpdate: response.time_since_update,
|
} else {
|
||||||
counter: response.counter,
|
this.setState(response);
|
||||||
});
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function componentDidMount() {
|
||||||
this.getDaemonData;
|
if (this.isMounted()) {
|
||||||
setInterval(this.getDaemonData, 5000);
|
this.getDaemonData;
|
||||||
|
setInterval(this.getDaemonData, 5000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
controlDaemon: function (action) {
|
||||||
|
jQuery('.button-primary').addClass('disabled');
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'queue',
|
||||||
|
action: 'controlDaemon',
|
||||||
|
data: {'action': action}
|
||||||
|
}).done(function (response) {
|
||||||
|
if (!response) {
|
||||||
|
this.replaceState();
|
||||||
|
} else {
|
||||||
|
this.setState(response);
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
if (!this.state) {
|
if (!this.state) {
|
||||||
return (
|
return
|
||||||
<div className="QueueControl">
|
<div>
|
||||||
Woops, daemon is not running ;\
|
Woops, daemon is not running ;\
|
||||||
</div>
|
</div>
|
||||||
)
|
}
|
||||||
|
switch (this.state.status) {
|
||||||
|
case 'started':
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
Queue daemon is running.
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
It was started
|
||||||
|
<strong> {this.state.timeSinceStart} </strong> and last executed
|
||||||
|
<strong> {this.state.timeSinceUpdate} </strong> for a total of
|
||||||
|
<strong> {this.state.counter} </strong> times (once every 30 seconds, unless it was interrupted and restarted).
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'stop')}>Stop</a>
|
||||||
|
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'pause')}>Pause</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'paused':
|
||||||
|
case 'stopped':
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
Daemon is {this.state.status}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'start')}>Start</a>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
Queue is currently <b>{this.state.status}</b>.
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
It was started
|
|
||||||
<b> {this.state.timeSinceStart} </b> and was last executed
|
|
||||||
<b> {this.state.timeSinceUpdate} </b> for a total of
|
|
||||||
<b> {this.state.counter} </b> times (once every 30 seconds, unless it was interrupted and restarted).
|
|
||||||
<br />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let container = document.getElementById('queue_container');
|
let container = document.getElementById('queue_container');
|
||||||
if (container) {
|
if (container) {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<QueueDaemonControl />,
|
<QueueControl />,
|
||||||
container
|
document.getElementById('queue_status')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,13 +16,13 @@ class BootStrapMenu {
|
|||||||
return ($this->daemon) ?
|
return ($this->daemon) ?
|
||||||
array_merge(
|
array_merge(
|
||||||
array(
|
array(
|
||||||
'time_since_start' =>
|
'timeSinceStart' =>
|
||||||
Carbon::createFromFormat(
|
Carbon::createFromFormat(
|
||||||
'Y-m-d H:i:s',
|
'Y-m-d H:i:s',
|
||||||
$this->daemon->created_at,
|
$this->daemon->created_at,
|
||||||
'UTC'
|
'UTC'
|
||||||
)->diffForHumans(),
|
)->diffForHumans(),
|
||||||
'time_since_update' =>
|
'timeSinceUpdate' =>
|
||||||
Carbon::createFromFormat(
|
Carbon::createFromFormat(
|
||||||
'Y-m-d H:i:s',
|
'Y-m-d H:i:s',
|
||||||
$this->daemon->updated_at,
|
$this->daemon->updated_at,
|
||||||
|
@@ -28,7 +28,10 @@ class Daemon {
|
|||||||
if(!$daemon) {
|
if(!$daemon) {
|
||||||
$daemon = Setting::create();
|
$daemon = Setting::create();
|
||||||
$daemon->name = 'daemon';
|
$daemon->name = 'daemon';
|
||||||
$daemon->value = json_encode(array('status' => 'stopped'));
|
$daemon->value = json_encode(
|
||||||
|
array(
|
||||||
|
'status' => 'stopped',
|
||||||
|
));
|
||||||
$daemon->save();
|
$daemon->save();
|
||||||
}
|
}
|
||||||
if($daemonData['status'] !== 'started') {
|
if($daemonData['status'] !== 'started') {
|
||||||
@@ -36,7 +39,7 @@ class Daemon {
|
|||||||
$daemonData = array(
|
$daemonData = array(
|
||||||
'status' => 'started',
|
'status' => 'started',
|
||||||
'token' => $this->refreshedToken,
|
'token' => $this->refreshedToken,
|
||||||
'counter' => ($daemonData['status'] === 'paused') ?
|
'counter' => $daemonData['status'] === 'paused' ?
|
||||||
$daemonData['counter'] :
|
$daemonData['counter'] :
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
@@ -67,7 +70,7 @@ class Daemon {
|
|||||||
$worker = new Worker();
|
$worker = new Worker();
|
||||||
$worker->process();
|
$worker->process();
|
||||||
$elapsedTime = microtime(true) - $this->timer;
|
$elapsedTime = microtime(true) - $this->timer;
|
||||||
if ($elapsedTime < 30) {
|
if($elapsedTime < 30) {
|
||||||
sleep(30 - $elapsedTime);
|
sleep(30 - $elapsedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,11 +93,11 @@ class Daemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function refreshToken() {
|
function refreshToken() {
|
||||||
return Security::generateRandomString(5);
|
return Security::generateRandomString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function manageSession($action) {
|
function manageSession($action) {
|
||||||
switch ($action) {
|
switch($action) {
|
||||||
case 'start':
|
case 'start':
|
||||||
if(session_id()) {
|
if(session_id()) {
|
||||||
session_write_close();
|
session_write_close();
|
||||||
|
@@ -17,11 +17,11 @@ class Supervisor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkDaemon() {
|
function checkDaemon() {
|
||||||
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH'])) return;
|
|
||||||
if(!$this->daemon) {
|
if(!$this->daemon) {
|
||||||
return $this->startDaemon();
|
return $this->startDaemon();
|
||||||
} else {
|
} else {
|
||||||
if(!$this->forceStart && ($this->daemonData['status'] === 'paused' ||
|
if(!$this->forceStart && (
|
||||||
|
$this->daemonData['status'] === 'paused' ||
|
||||||
$this->daemonData['status'] === 'stopped'
|
$this->daemonData['status'] === 'stopped'
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@@ -33,8 +33,13 @@ class Supervisor {
|
|||||||
$this->daemon->updated_at, 'UTC'
|
$this->daemon->updated_at, 'UTC'
|
||||||
);
|
);
|
||||||
$timeSinceLastStart = $currentTime->diffInSeconds($lastUpdateTime);
|
$timeSinceLastStart = $currentTime->diffInSeconds($lastUpdateTime);
|
||||||
if($timeSinceLastStart < 50) return;
|
if(!$this->forceStart && $timeSinceLastStart < 50) return;
|
||||||
$this->daemonData['status'] = 'paused';
|
if(
|
||||||
|
($this->forceStart && $this->daemonData['status'] === 'paused') ||
|
||||||
|
!$this->forceStart
|
||||||
|
) {
|
||||||
|
$this->daemonData['status'] = 'paused';
|
||||||
|
}
|
||||||
$this->daemon->value = json_encode($this->daemonData);
|
$this->daemon->value = json_encode($this->daemonData);
|
||||||
$this->daemon->save();
|
$this->daemon->save();
|
||||||
return $this->startDaemon();
|
return $this->startDaemon();
|
||||||
|
@@ -1,26 +1,24 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Router;
|
namespace MailPoet\Router;
|
||||||
|
|
||||||
use MailPoet\Models\Setting;
|
|
||||||
use MailPoet\Queue\Daemon;
|
use MailPoet\Queue\Daemon;
|
||||||
use MailPoet\Queue\Supervisor;
|
use MailPoet\Queue\Supervisor;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Queue {
|
class Queue {
|
||||||
function start() {
|
function controlDaemon($data) {
|
||||||
$supervisor = new Supervisor();
|
switch($data['action']) {
|
||||||
wp_send_json(
|
case 'start':
|
||||||
array(
|
$supervisor = new Supervisor($forceStart = true);
|
||||||
'result' => ($supervisor->checkDaemon($forceStart = true)) ?
|
wp_send_json(
|
||||||
true :
|
array(
|
||||||
false
|
'result' => $supervisor->checkDaemon() ?
|
||||||
)
|
true :
|
||||||
);
|
false
|
||||||
}
|
)
|
||||||
|
);
|
||||||
function update($data) {
|
break;
|
||||||
switch ($data['action']) {
|
|
||||||
case 'stop':
|
case 'stop':
|
||||||
$status = 'stopped';
|
$status = 'stopped';
|
||||||
break;
|
break;
|
||||||
@@ -43,9 +41,8 @@ class Queue {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getQueueStatus() {
|
function getDaemonStatus() {
|
||||||
$daemon = new \MailPoet\Queue\BootStrapMenu();
|
$daemon = new \MailPoet\Queue\BootStrapMenu();
|
||||||
wp_send_json($daemon->bootStrap());
|
wp_send_json($daemon->bootStrap());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,7 +8,14 @@ class Security {
|
|||||||
return wp_create_nonce('mailpoet_token');
|
return wp_create_nonce('mailpoet_token');
|
||||||
}
|
}
|
||||||
|
|
||||||
static function generateRandomString($length) {
|
static function generateRandomString($length = 5) {
|
||||||
return substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, $length);
|
// non-cryptographically strong random generator
|
||||||
|
return substr(
|
||||||
|
md5(
|
||||||
|
uniqid(
|
||||||
|
mt_rand(), true)
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
(!is_int($length) || $length <= 5 || $length >= 32) ? 5 : $length);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,10 @@
|
|||||||
<% extends 'layout.html' %>
|
<% extends 'layout.html' %>
|
||||||
|
|
||||||
<% block content %>
|
<% block content %>
|
||||||
<div id="queue_container"></div>
|
<div id="queue_container">
|
||||||
|
<div id="queue_status"></div>
|
||||||
|
<div id="queue_control"></div>
|
||||||
|
</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
|
Reference in New Issue
Block a user