From c46c61a923b60a94e9e2c5c4fcbeba7e44609335 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Fri, 11 Nov 2022 23:05:44 +0100 Subject: [PATCH] Simplify and optimize automation stats [MAILPOET-4788] --- .../Storage/AutomationStatisticsStorage.php | 93 +++++++------------ .../Migrations/Migration_20221110_151621.php | 3 +- 2 files changed, 37 insertions(+), 59 deletions(-) diff --git a/mailpoet/lib/Automation/Engine/Storage/AutomationStatisticsStorage.php b/mailpoet/lib/Automation/Engine/Storage/AutomationStatisticsStorage.php index f83a623533..c085ef4190 100644 --- a/mailpoet/lib/Automation/Engine/Storage/AutomationStatisticsStorage.php +++ b/mailpoet/lib/Automation/Engine/Storage/AutomationStatisticsStorage.php @@ -5,7 +5,6 @@ namespace MailPoet\Automation\Engine\Storage; use MailPoet\Automation\Engine\Data\Automation; use MailPoet\Automation\Engine\Data\AutomationRun; use MailPoet\Automation\Engine\Data\AutomationStatistics; -use MailPoet\InvalidStateException; class AutomationStatisticsStorage { @@ -24,7 +23,6 @@ class AutomationStatisticsStorage { /** * @param Automation ...$automations * @return AutomationStatistics[] - * @throws \MailPoet\Automation\Engine\Exceptions\InvalidStateException */ public function getAutomationStatisticsForAutomations(Automation ...$automations): array { if (empty($automations)) { @@ -36,80 +34,61 @@ class AutomationStatisticsStorage { }, $automations ); - $runMatrix = $this->queryRunsFor(...$automationIds); + + $data = $this->getStatistics($automationIds); $statistics = []; - foreach ($automations as $automation) { - $statistics[$automation->getId()] = $this->buildAutomationStatisticFromMatrix($runMatrix, $automation->getId(), null); + foreach ($automationIds as $id) { + $statistics[$id] = new AutomationStatistics( + $id, + (int)($data[$id]['total'] ?? 0), + (int)($data[$id]['running'] ?? 0) + ); } return $statistics; } public function getAutomationStats(int $automationId, int $versionId = null): AutomationStatistics { - return $this->buildAutomationStatisticFromMatrix( - $this->queryRunsFor($automationId), - $automationId, - $versionId - ); - } - - private function buildAutomationStatisticFromMatrix(array $matrix, int $automationId, int $versionId = null): AutomationStatistics { - - $automationMatrix = $matrix[$automationId] ?? []; - $versionMatrix = $automationMatrix[$versionId] ?? []; - if ($versionId === null) { - foreach ($automationMatrix as $version) { - foreach ($version as $status => $runs) { - if (!isset($versionMatrix[$status])) { - $versionMatrix[$status] = 0; - } - $versionMatrix[$status] += $runs; - } - } - } - $totals = (int)array_sum($versionMatrix); + $data = $this->getStatistics([$automationId], $versionId); return new AutomationStatistics( $automationId, - $totals, - $versionMatrix[AutomationRun::STATUS_RUNNING] ?? 0, + (int)($data[$automationId]['total'] ?? 0), + (int)($data[$automationId]['running'] ?? 0), $versionId ); } /** - * Returns an array with all runs for all versions of the given automations - * [ - * => [ - * => [ - * => int, - * ], - * ], - * ] - * @param int ...$automationIds - * @return array>> + * @param int[] $automationIds + * @return array */ - private function queryRunsFor(int ...$automationIds): array { - $table = esc_sql($this->table); + private function getStatistics(array $automationIds, int $versionId = null): array { + $totalSubquery = $this->getStatsQuery($automationIds, $versionId); + $runningSubquery = $this->getStatsQuery($automationIds, $versionId, AutomationRun::STATUS_RUNNING); + // The subqueries are created using $wpdb->prepare(). + // phpcs:ignore WordPressDotOrg.sniffs.DirectDB.UnescapedDBParameter + $results = (array)$this->wpdb->get_results(" + SELECT t.id, t.count AS total, r.count AS running + FROM ($totalSubquery) t + LEFT JOIN ($runningSubquery) r ON t.id = r.id + ", ARRAY_A); + + return array_combine(array_column($results, 'id'), $results) ?: []; + } + + private function getStatsQuery(array $automationIds, int $versionId = null, string $status = null): string { + $table = esc_sql($this->table); $placeholders = implode(',', array_fill(0, count($automationIds), '%d')); + $versionCondition = strval($versionId ? $this->wpdb->prepare('AND version_id = %d', $versionId) : ''); + $statusCondition = strval($status ? $this->wpdb->prepare('AND status = %s', $status) : ''); $query = $this->wpdb->prepare(" - SELECT status, automation_id as workfowId, version_id as versionId, COUNT(id) as runs + SELECT automation_id AS id, COUNT(*) AS count FROM $table WHERE automation_id IN ($placeholders) - GROUP BY status, automation_id, version_id + $versionCondition + $statusCondition + GROUP BY automation_id ", $automationIds); - - if (!is_string($query)) { - throw InvalidStateException::create(); - } - - $matrix = []; - $results = $this->wpdb->get_results($query); - if (!is_array($results) || !count($results)) { - return $matrix; - } - foreach ($results as $result) { - $matrix[(int)$result->workfowId][(int)$result->versionId][(string)$result->status] = (int)$result->runs; - } - return $matrix; + return strval($query); } } diff --git a/mailpoet/lib/Migrations/Migration_20221110_151621.php b/mailpoet/lib/Migrations/Migration_20221110_151621.php index d0c1ed9e8d..3f408f69ae 100644 --- a/mailpoet/lib/Migrations/Migration_20221110_151621.php +++ b/mailpoet/lib/Migrations/Migration_20221110_151621.php @@ -56,8 +56,7 @@ class Migration_20221110_151621 extends Migration { subjects longtext, next_step_id varchar(255), PRIMARY KEY (id), - INDEX (automation_id), - INDEX (status) + INDEX (automation_id, status) ) {$charsetCollate}; ");