Cache homepage subscribers stats

[MAILPOET-5180]
This commit is contained in:
alex-mailpoet
2023-05-09 11:35:40 +03:00
committed by Aschepikov
parent d7fd11387f
commit 4cd1667146
4 changed files with 64 additions and 20 deletions

View File

@@ -8,6 +8,7 @@ use MailPoetVendor\Carbon\Carbon;
class TransientCache {
public const SUBSCRIBERS_STATISTICS_COUNT_KEY = 'mailpoet_subscribers_statistics_count_cache';
public const SUBSCRIBERS_GLOBAL_STATUS_STATISTICS_COUNT_KEY = 'mailpoet_subscribers_statistics_count_global_status_cache';
public const SUBSCRIBERS_HOMEPAGE_STATISTICS_COUNT_KEY = 'mailpoet_subscribers_statistics_count_homepage_cache';
/** @var WPFunctions */
private $wp;

View File

@@ -46,7 +46,10 @@ class SubscribersCountCacheRecalculation extends SimpleWorker {
// update cache for subscribers without segment
$this->recalculateSegmentCache($timer, 0);
$this->recalculateHomepageCache($timer);
// remove redundancies from cache
$this->cronHelper->enforceExecutionLimit($timer);
$this->subscribersCountsController->removeRedundancyFromStatisticsCache();
return true;
@@ -68,6 +71,16 @@ class SubscribersCountCacheRecalculation extends SimpleWorker {
}
}
private function recalculateHomepageCache($timer): void {
$this->cronHelper->enforceExecutionLimit($timer);
$now = Carbon::now();
$item = $this->transientCache->getItem(TransientCache::SUBSCRIBERS_HOMEPAGE_STATISTICS_COUNT_KEY, 0);
if ($item === null || !isset($item['created_at']) || $now->diffInMinutes($item['created_at']) > self::EXPIRATION_IN_MINUTES) {
$this->cronHelper->enforceExecutionLimit($timer);
$this->subscribersCountsController->recalculateHomepageStatisticsCache();
}
}
public function getNextRunDate() {
return Carbon::createFromTimestamp($this->wp->currentTime('timestamp'));
}

View File

@@ -8,16 +8,13 @@ use MailPoet\Automation\Integrations\MailPoet\Actions\SendEmailAction;
use MailPoet\Automation\Integrations\MailPoet\Triggers\SomeoneSubscribesTrigger;
use MailPoet\Automation\Integrations\MailPoet\Triggers\UserRegistrationTrigger;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Form\FormsRepository;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Services\Bridge;
use MailPoet\Settings\SettingsController;
use MailPoet\Subscribers\SubscribersRepository;
use MailPoet\Subscribers\SubscribersCountsController;
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
use MailPoet\WooCommerce\Helper as WooCommerceHelper;
use MailPoet\WP\Functions as WPFunctions;
use MailPoetVendor\Carbon\Carbon;
class HomepageDataController {
public const UPSELL_SUBSCRIBERS_COUNT_REQUIRED = 600;
@@ -25,9 +22,6 @@ class HomepageDataController {
/** @var SettingsController */
private $settingsController;
/** @var SubscribersRepository */
private $subscribersRepository;
/** @var FormsRepository */
private $formsRepository;
@@ -43,27 +37,25 @@ class HomepageDataController {
/** @var SubscribersFeature */
private $subscribersFeature;
/** @var WPFunctions */
private $wp;
/** @var SubscribersCountsController */
private $subscribersCountsController;
public function __construct(
SettingsController $settingsController,
SubscribersRepository $subscribersRepository,
FormsRepository $formsRepository,
NewslettersRepository $newslettersRepository,
AutomationStorage $automationStorage,
SubscribersFeature $subscribersFeature,
WPFunctions $wp,
SubscribersCountsController $subscribersCountsController,
WooCommerceHelper $wooCommerceHelper
) {
$this->settingsController = $settingsController;
$this->subscribersRepository = $subscribersRepository;
$this->formsRepository = $formsRepository;
$this->newslettersRepository = $newslettersRepository;
$this->automationStorage = $automationStorage;
$this->wp = $wp;
$this->wooCommerceHelper = $wooCommerceHelper;
$this->subscribersFeature = $subscribersFeature;
$this->subscribersCountsController = $subscribersCountsController;
}
public function getPageData(): array {
@@ -158,15 +150,15 @@ class HomepageDataController {
* @return array{global:array{subscribed:int, unsubscribed:int, changePercent:float|int}, lists:array<int, array>}
*/
private function getSubscribersStats(): array {
$thirtyDaysAgo = Carbon::createFromTimestamp($this->wp->currentTime('timestamp'))->subDays(30);
$listData = [];
$listsDataSubscribed = $this->subscribersRepository->getListLevelCountsOfSubscribedAfter($thirtyDaysAgo);
$counts = $this->subscribersCountsController->getHomepageStatistics();
$listsDataSubscribed = $counts['listsDataSubscribed'] ?? [];
foreach ($listsDataSubscribed as $list) {
$listData[$list['id']] = array_intersect_key($list, array_flip(['name', 'id', 'type', 'averageEngagementScore']));
$listData[$list['id']]['subscribed'] = $list['count'];
$listData[$list['id']]['unsubscribed'] = 0;
}
$listsDataUnsubscribed = $this->subscribersRepository->getListLevelCountsOfUnsubscribedAfter($thirtyDaysAgo);
$listsDataUnsubscribed = $counts['listsDataUnsubscribed'] ?? [];
foreach ($listsDataUnsubscribed as $list) {
if (!isset($listData[$list['id']])) {
$listData[$list['id']] = array_intersect_key($list, array_flip(['name', 'id', 'type', 'averageEngagementScore']));
@@ -175,9 +167,9 @@ class HomepageDataController {
$listData[$list['id']]['unsubscribed'] = $list['count'];
}
$subscribedCount = $this->subscribersRepository->getCountOfLastSubscribedAfter($thirtyDaysAgo);
$unsubscribedCount = $this->subscribersRepository->getCountOfUnsubscribedAfter($thirtyDaysAgo);
$subscribedSubscribersCount = $this->subscribersRepository->getCountOfSubscribersForStates([SubscriberEntity::STATUS_SUBSCRIBED]);
$subscribedCount = intval($counts['subscribedCount'] ?? 0);
$unsubscribedCount = intval($counts['unsubscribedCount'] ?? 0);
$subscribedSubscribersCount = intval($counts['subscribedSubscribersCount'] ?? 0);
$subscribedSubscribers30DaysAgo = $subscribedSubscribersCount - $subscribedCount + $unsubscribedCount;
if ($subscribedSubscribers30DaysAgo > 0) {
$globalChangePercent = (($subscribedSubscribersCount - $subscribedSubscribers30DaysAgo) / $subscribedSubscribers30DaysAgo) * 100;

View File

@@ -4,10 +4,14 @@ namespace MailPoet\Subscribers;
use MailPoet\Cache\TransientCache;
use MailPoet\Entities\SegmentEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\InvalidStateException;
use MailPoet\Segments\SegmentsRepository;
use MailPoet\Segments\SegmentSubscribersRepository;
use MailPoet\Subscribers\SubscribersRepository;
use MailPoet\Tags\TagRepository;
use MailPoet\WP\Functions as WPFunctions;
use MailPoetVendor\Carbon\Carbon;
class SubscribersCountsController {
/** @var SegmentsRepository */
@@ -16,23 +20,33 @@ class SubscribersCountsController {
/** @var SegmentSubscribersRepository */
private $segmentSubscribersRepository;
/** @var SubscribersRepository */
private $subscribersRepository;
/** @var TagRepository */
private $tagRepository;
/** @var TransientCache */
private $transientCache;
/** @var WPFunctions */
private $wp;
public function __construct(
SegmentsRepository $segmentsRepository,
SegmentSubscribersRepository $segmentSubscribersRepository,
SubscribersRepository $subscribersRepository,
TagRepository $subscriberTagRepository,
TransientCache $transientCache
TransientCache $transientCache,
WPFunctions $wp
) {
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
$this->transientCache = $transientCache;
$this->segmentsRepository = $segmentsRepository;
$this->subscribersRepository = $subscribersRepository;
$this->tagRepository = $subscriberTagRepository;
$this->wp = $wp;
}
public function getSubscribersWithoutSegmentStatisticsCount(): array {
@@ -71,6 +85,14 @@ class SubscribersCountsController {
return $result;
}
public function getHomepageStatistics(): array {
$result = $this->transientCache->getItem(TransientCache::SUBSCRIBERS_HOMEPAGE_STATISTICS_COUNT_KEY, 0) ?? [];
if (!$result) {
$result = $this->recalculateHomepageStatisticsCache();
}
return $result;
}
public function recalculateSegmentGlobalStatusStatisticsCache(SegmentEntity $segment): array {
$result = $this->segmentSubscribersRepository->getSubscribersGlobalStatusStatisticsCount($segment);
$this->transientCache->setItem(
@@ -97,6 +119,22 @@ class SubscribersCountsController {
return $result;
}
public function recalculateHomepageStatisticsCache(): array {
$thirtyDaysAgo = Carbon::createFromTimestamp($this->wp->currentTime('timestamp'))->subDays(30);
$result = [];
$result['listsDataSubscribed'] = $this->subscribersRepository->getListLevelCountsOfSubscribedAfter($thirtyDaysAgo);
$result['listsDataUnsubscribed'] = $this->subscribersRepository->getListLevelCountsOfUnsubscribedAfter($thirtyDaysAgo);
$result['subscribedCount'] = $this->subscribersRepository->getCountOfLastSubscribedAfter($thirtyDaysAgo);
$result['unsubscribedCount'] = $this->subscribersRepository->getCountOfUnsubscribedAfter($thirtyDaysAgo);
$result['subscribedSubscribersCount'] = $this->subscribersRepository->getCountOfSubscribersForStates([SubscriberEntity::STATUS_SUBSCRIBED]);
$this->transientCache->setItem(
TransientCache::SUBSCRIBERS_HOMEPAGE_STATISTICS_COUNT_KEY,
$result,
0
);
return $result;
}
public function removeRedundancyFromStatisticsCache() {
$segments = $this->segmentsRepository->findAll();
$segmentIds = array_map(function (SegmentEntity $segment): int {