diff --git a/assets/js/src/help/cron_status.jsx b/assets/js/src/help/cron_status.jsx
index 80b268ab74..73c6a15e44 100644
--- a/assets/js/src/help/cron_status.jsx
+++ b/assets/js/src/help/cron_status.jsx
@@ -13,7 +13,7 @@ function renderStatusTableRow(title, value) {
const CronStatus = (props) => {
const status = props.status_data;
const activeStatusMapping = {
- active: MailPoet.I18n.t('cronRunning'),
+ active: MailPoet.I18n.t('running'),
inactive: MailPoet.I18n.t('cronWaiting'),
};
return (
@@ -41,7 +41,7 @@ const CronStatus = (props) => {
MailPoet.I18n.t('lastRunCompleted'),
status.run_completed_at ? MailPoet.Date.full(status.run_completed_at * 1000) : MailPoet.I18n.t('unknown'))
}
- {renderStatusTableRow(MailPoet.I18n.t('lastSeenError'), status.last_error || '-')}
+ {renderStatusTableRow(MailPoet.I18n.t('lastSeenError'), status.last_error || MailPoet.I18n.t('none'))}
diff --git a/assets/js/src/help/queue_status.jsx b/assets/js/src/help/queue_status.jsx
new file mode 100644
index 0000000000..b0f0064f4d
--- /dev/null
+++ b/assets/js/src/help/queue_status.jsx
@@ -0,0 +1,91 @@
+import MailPoet from 'mailpoet';
+import React from 'react';
+
+function renderStatusTableRow(title, value) {
+ return (
+
+ { title } | { value } |
+
+ );
+}
+
+const QueueStatus = (props) => {
+ const status = props.status_data;
+ return (
+
+
{MailPoet.I18n.t('systemStatusQueueTitle')}
+
+
+ {renderStatusTableRow(
+ MailPoet.I18n.t('status'),
+ status.status === 'paused' ? MailPoet.I18n.t('paused') : MailPoet.I18n.t('running'))
+ }
+ {renderStatusTableRow(
+ MailPoet.I18n.t('startedAt'),
+ status.started ? MailPoet.Date.full(status.started * 1000) : MailPoet.I18n.t('unknown'))
+ }
+ {renderStatusTableRow(
+ MailPoet.I18n.t('sentEmails'),
+ status.sent || 0)
+ }
+ {renderStatusTableRow(
+ MailPoet.I18n.t('retryAttempts'),
+ status.retry_attempt || MailPoet.I18n.t('none'))
+ }
+ {renderStatusTableRow(
+ MailPoet.I18n.t('retryAt'),
+ status.retry_at ? MailPoet.Date.full(status.retry_at * 1000) : MailPoet.I18n.t('none'))
+ }
+ {renderStatusTableRow(
+ MailPoet.I18n.t('error'),
+ status.error || MailPoet.I18n.t('none'))
+ }
+ {renderStatusTableRow(
+ MailPoet.I18n.t('totalCompletedTasks'),
+ status.tasksStatusCounts.completed)
+ }
+ {renderStatusTableRow(
+ MailPoet.I18n.t('totalRunningTasks'),
+ status.tasksStatusCounts.running)
+ }
+ {renderStatusTableRow(
+ MailPoet.I18n.t('totalPausedTasks'),
+ status.tasksStatusCounts.paused)
+ }
+ {renderStatusTableRow(
+ MailPoet.I18n.t('totalScheduledTasks'),
+ status.tasksStatusCounts.scheduled)
+ }
+
+
+
+ );
+};
+
+QueueStatus.propTypes = {
+ status_data: React.PropTypes.shape({
+ status: React.PropTypes.string,
+ started: React.PropTypes.number,
+ sent: React.PropTypes.number,
+ retry_attempt: React.PropTypes.number,
+ retry_at: React.PropTypes.number,
+ tasksStatusCounts: React.PropTypes.shape({
+ completed: React.PropTypes.number.isRequired,
+ running: React.PropTypes.number.isRequired,
+ paused: React.PropTypes.number.isRequired,
+ scheduled: React.PropTypes.number.isRequired,
+ }).isRequired,
+ }).isRequired,
+};
+
+QueueStatus.defaultProps = {
+ status_data: {
+ status: null,
+ started: null,
+ sent: null,
+ retry_attempt: null,
+ retry_at: null,
+ },
+};
+
+module.exports = QueueStatus;
diff --git a/assets/js/src/help/system_status.jsx b/assets/js/src/help/system_status.jsx
index 7eb7f7b8cc..943c5009f1 100644
--- a/assets/js/src/help/system_status.jsx
+++ b/assets/js/src/help/system_status.jsx
@@ -2,6 +2,7 @@ import MailPoet from 'mailpoet';
import React from 'react';
import ReactStringReplace from 'react-string-replace';
import CronStatus from './cron_status.jsx';
+import QueueStatus from './queue_status.jsx';
import Tabs from './tabs.jsx';
function renderStatusMessage(status, error, link) {
@@ -67,6 +68,7 @@ function SystemStatus() {
{renderCronSection(systemStatusData)}
{renderMSSSection(systemStatusData)}
+
);
}
diff --git a/lib/Config/Menu.php b/lib/Config/Menu.php
index 97f168d3f7..6892703c2e 100644
--- a/lib/Config/Menu.php
+++ b/lib/Config/Menu.php
@@ -9,8 +9,10 @@ use MailPoet\Form\Block;
use MailPoet\Form\Renderer as FormRenderer;
use MailPoet\Helpscout\Beacon;
use MailPoet\Listing;
+use MailPoet\Mailer\MailerLog;
use MailPoet\Models\CustomField;
use MailPoet\Models\Form;
+use MailPoet\Models\ScheduledTask;
use MailPoet\Models\Segment;
use MailPoet\Models\Setting;
use MailPoet\Models\Subscriber;
@@ -20,6 +22,7 @@ use MailPoet\Services\Bridge;
use MailPoet\Settings\Hosts;
use MailPoet\Settings\Pages;
use MailPoet\Subscribers\ImportExport\ImportExportFactory;
+use MailPoet\Tasks\State;
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
use MailPoet\Util\License\License;
use MailPoet\WP\DateTime;
@@ -447,6 +450,7 @@ class Menu {
function help() {
+ $tasks_state = new State();
$system_info_data = Beacon::getData();
$system_status_data = [
'cron' => [
@@ -459,8 +463,10 @@ class Menu {
false
],
'cronStatus' => CronHelper::getDaemon(),
+ 'queueStatus' => MailerLog::getMailerLog(),
];
$system_status_data['cronStatus']['accessible'] = CronHelper::isDaemonAccessible();
+ $system_status_data['queueStatus']['tasksStatusCounts'] = $tasks_state->getCountsPerStatus();
$this->displayPage(
'help.html',
array(
diff --git a/lib/Models/ScheduledTask.php b/lib/Models/ScheduledTask.php
index 525f896ce1..9dbc38558e 100644
--- a/lib/Models/ScheduledTask.php
+++ b/lib/Models/ScheduledTask.php
@@ -11,6 +11,7 @@ class ScheduledTask extends Model {
const STATUS_COMPLETED = 'completed';
const STATUS_SCHEDULED = 'scheduled';
const STATUS_PAUSED = 'paused';
+ const VIRTUAL_STATUS_RUNNING = 'running'; // For historical reasons this is stored as null in DB
const PRIORITY_HIGH = 1;
const PRIORITY_MEDIUM = 5;
const PRIORITY_LOW = 10;
diff --git a/lib/Tasks/State.php b/lib/Tasks/State.php
new file mode 100644
index 0000000000..fb0a2b14b2
--- /dev/null
+++ b/lib/Tasks/State.php
@@ -0,0 +1,35 @@
+ 0,
+ ScheduledTask::STATUS_PAUSED => 0,
+ ScheduledTask::STATUS_SCHEDULED => 0,
+ ScheduledTask::VIRTUAL_STATUS_RUNNING => 0,
+ ];
+ $counts = ScheduledTask::rawQuery(
+ "SELECT COUNT(*) as value, status
+ FROM `" . ScheduledTask::$_table . "`
+ WHERE deleted_at IS NULL AND `type` = 'sending'
+ GROUP BY status;"
+ )->findMany();
+ foreach($counts as $count) {
+ if($count->status === null) {
+ $stats[ScheduledTask::VIRTUAL_STATUS_RUNNING] = (int)$count->value;
+ continue;
+ }
+ $stats[$count->status] = (int)$count->value;
+ }
+ return $stats;
+ }
+}
diff --git a/views/help.html b/views/help.html
index 1d9c7b9f2f..cfc222bf49 100644
--- a/views/help.html
+++ b/views/help.html
@@ -34,6 +34,7 @@
'systemInfoIntro': __('The information below is useful when you need to get in touch with our support. Just copy all the text below and paste it into a message to us.'),
'systemInfoDataError': __('Sorry, there was an error, please try again later.'),
'systemStatusCronStatusTitle': __('Cron'),
+ 'systemStatusQueueTitle': __('Sending Queue'),
'lastUpdated': __('Last updated'),
'lastRunStarted': __('Last run started'),
'lastRunCompleted': __('Last run completed'),
@@ -43,8 +44,18 @@
'status': __('Status'),
'yes': __('yes'),
'no': __('no'),
- 'cronRunning': __('running'),
+ 'none': __('none'),
+ 'running': __('running'),
'cronWaiting': __('waiting for the next run'),
+ 'startedAt': __('Started at'),
+ 'sentEmails': __('Sent emails'),
+ 'retryAttempt': __('Retry attempt'),
+ 'retryAt': __('Retry at'),
+ 'error': __('Error'),
+ 'totalCompletedTasks': __('Total completed tasks'),
+ 'totalScheduledTasks': __('Total scheduled tasks'),
+ 'totalRunningTasks': __('Total running tasks'),
+ 'totalPausedTasks': __('Total paused tasks'),
}) %>
<% endblock %>