Cache homepage subscribers stats
[MAILPOET-5180]
This commit is contained in:
committed by
Aschepikov
parent
d7fd11387f
commit
4cd1667146
@@ -8,6 +8,7 @@ use MailPoetVendor\Carbon\Carbon;
|
|||||||
class TransientCache {
|
class TransientCache {
|
||||||
public const SUBSCRIBERS_STATISTICS_COUNT_KEY = 'mailpoet_subscribers_statistics_count_cache';
|
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_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 */
|
/** @var WPFunctions */
|
||||||
private $wp;
|
private $wp;
|
||||||
|
@@ -46,7 +46,10 @@ class SubscribersCountCacheRecalculation extends SimpleWorker {
|
|||||||
// update cache for subscribers without segment
|
// update cache for subscribers without segment
|
||||||
$this->recalculateSegmentCache($timer, 0);
|
$this->recalculateSegmentCache($timer, 0);
|
||||||
|
|
||||||
|
$this->recalculateHomepageCache($timer);
|
||||||
|
|
||||||
// remove redundancies from cache
|
// remove redundancies from cache
|
||||||
|
$this->cronHelper->enforceExecutionLimit($timer);
|
||||||
$this->subscribersCountsController->removeRedundancyFromStatisticsCache();
|
$this->subscribersCountsController->removeRedundancyFromStatisticsCache();
|
||||||
|
|
||||||
return true;
|
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() {
|
public function getNextRunDate() {
|
||||||
return Carbon::createFromTimestamp($this->wp->currentTime('timestamp'));
|
return Carbon::createFromTimestamp($this->wp->currentTime('timestamp'));
|
||||||
}
|
}
|
||||||
|
@@ -8,16 +8,13 @@ use MailPoet\Automation\Integrations\MailPoet\Actions\SendEmailAction;
|
|||||||
use MailPoet\Automation\Integrations\MailPoet\Triggers\SomeoneSubscribesTrigger;
|
use MailPoet\Automation\Integrations\MailPoet\Triggers\SomeoneSubscribesTrigger;
|
||||||
use MailPoet\Automation\Integrations\MailPoet\Triggers\UserRegistrationTrigger;
|
use MailPoet\Automation\Integrations\MailPoet\Triggers\UserRegistrationTrigger;
|
||||||
use MailPoet\Entities\NewsletterEntity;
|
use MailPoet\Entities\NewsletterEntity;
|
||||||
use MailPoet\Entities\SubscriberEntity;
|
|
||||||
use MailPoet\Form\FormsRepository;
|
use MailPoet\Form\FormsRepository;
|
||||||
use MailPoet\Newsletter\NewslettersRepository;
|
use MailPoet\Newsletter\NewslettersRepository;
|
||||||
use MailPoet\Services\Bridge;
|
use MailPoet\Services\Bridge;
|
||||||
use MailPoet\Settings\SettingsController;
|
use MailPoet\Settings\SettingsController;
|
||||||
use MailPoet\Subscribers\SubscribersRepository;
|
use MailPoet\Subscribers\SubscribersCountsController;
|
||||||
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
|
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
|
||||||
use MailPoet\WooCommerce\Helper as WooCommerceHelper;
|
use MailPoet\WooCommerce\Helper as WooCommerceHelper;
|
||||||
use MailPoet\WP\Functions as WPFunctions;
|
|
||||||
use MailPoetVendor\Carbon\Carbon;
|
|
||||||
|
|
||||||
class HomepageDataController {
|
class HomepageDataController {
|
||||||
public const UPSELL_SUBSCRIBERS_COUNT_REQUIRED = 600;
|
public const UPSELL_SUBSCRIBERS_COUNT_REQUIRED = 600;
|
||||||
@@ -25,9 +22,6 @@ class HomepageDataController {
|
|||||||
/** @var SettingsController */
|
/** @var SettingsController */
|
||||||
private $settingsController;
|
private $settingsController;
|
||||||
|
|
||||||
/** @var SubscribersRepository */
|
|
||||||
private $subscribersRepository;
|
|
||||||
|
|
||||||
/** @var FormsRepository */
|
/** @var FormsRepository */
|
||||||
private $formsRepository;
|
private $formsRepository;
|
||||||
|
|
||||||
@@ -43,27 +37,25 @@ class HomepageDataController {
|
|||||||
/** @var SubscribersFeature */
|
/** @var SubscribersFeature */
|
||||||
private $subscribersFeature;
|
private $subscribersFeature;
|
||||||
|
|
||||||
/** @var WPFunctions */
|
/** @var SubscribersCountsController */
|
||||||
private $wp;
|
private $subscribersCountsController;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
SettingsController $settingsController,
|
SettingsController $settingsController,
|
||||||
SubscribersRepository $subscribersRepository,
|
|
||||||
FormsRepository $formsRepository,
|
FormsRepository $formsRepository,
|
||||||
NewslettersRepository $newslettersRepository,
|
NewslettersRepository $newslettersRepository,
|
||||||
AutomationStorage $automationStorage,
|
AutomationStorage $automationStorage,
|
||||||
SubscribersFeature $subscribersFeature,
|
SubscribersFeature $subscribersFeature,
|
||||||
WPFunctions $wp,
|
SubscribersCountsController $subscribersCountsController,
|
||||||
WooCommerceHelper $wooCommerceHelper
|
WooCommerceHelper $wooCommerceHelper
|
||||||
) {
|
) {
|
||||||
$this->settingsController = $settingsController;
|
$this->settingsController = $settingsController;
|
||||||
$this->subscribersRepository = $subscribersRepository;
|
|
||||||
$this->formsRepository = $formsRepository;
|
$this->formsRepository = $formsRepository;
|
||||||
$this->newslettersRepository = $newslettersRepository;
|
$this->newslettersRepository = $newslettersRepository;
|
||||||
$this->automationStorage = $automationStorage;
|
$this->automationStorage = $automationStorage;
|
||||||
$this->wp = $wp;
|
|
||||||
$this->wooCommerceHelper = $wooCommerceHelper;
|
$this->wooCommerceHelper = $wooCommerceHelper;
|
||||||
$this->subscribersFeature = $subscribersFeature;
|
$this->subscribersFeature = $subscribersFeature;
|
||||||
|
$this->subscribersCountsController = $subscribersCountsController;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPageData(): array {
|
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>}
|
* @return array{global:array{subscribed:int, unsubscribed:int, changePercent:float|int}, lists:array<int, array>}
|
||||||
*/
|
*/
|
||||||
private function getSubscribersStats(): array {
|
private function getSubscribersStats(): array {
|
||||||
$thirtyDaysAgo = Carbon::createFromTimestamp($this->wp->currentTime('timestamp'))->subDays(30);
|
|
||||||
$listData = [];
|
$listData = [];
|
||||||
$listsDataSubscribed = $this->subscribersRepository->getListLevelCountsOfSubscribedAfter($thirtyDaysAgo);
|
$counts = $this->subscribersCountsController->getHomepageStatistics();
|
||||||
|
$listsDataSubscribed = $counts['listsDataSubscribed'] ?? [];
|
||||||
foreach ($listsDataSubscribed as $list) {
|
foreach ($listsDataSubscribed as $list) {
|
||||||
$listData[$list['id']] = array_intersect_key($list, array_flip(['name', 'id', 'type', 'averageEngagementScore']));
|
$listData[$list['id']] = array_intersect_key($list, array_flip(['name', 'id', 'type', 'averageEngagementScore']));
|
||||||
$listData[$list['id']]['subscribed'] = $list['count'];
|
$listData[$list['id']]['subscribed'] = $list['count'];
|
||||||
$listData[$list['id']]['unsubscribed'] = 0;
|
$listData[$list['id']]['unsubscribed'] = 0;
|
||||||
}
|
}
|
||||||
$listsDataUnsubscribed = $this->subscribersRepository->getListLevelCountsOfUnsubscribedAfter($thirtyDaysAgo);
|
$listsDataUnsubscribed = $counts['listsDataUnsubscribed'] ?? [];
|
||||||
foreach ($listsDataUnsubscribed as $list) {
|
foreach ($listsDataUnsubscribed as $list) {
|
||||||
if (!isset($listData[$list['id']])) {
|
if (!isset($listData[$list['id']])) {
|
||||||
$listData[$list['id']] = array_intersect_key($list, array_flip(['name', 'id', 'type', 'averageEngagementScore']));
|
$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'];
|
$listData[$list['id']]['unsubscribed'] = $list['count'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$subscribedCount = $this->subscribersRepository->getCountOfLastSubscribedAfter($thirtyDaysAgo);
|
$subscribedCount = intval($counts['subscribedCount'] ?? 0);
|
||||||
$unsubscribedCount = $this->subscribersRepository->getCountOfUnsubscribedAfter($thirtyDaysAgo);
|
$unsubscribedCount = intval($counts['unsubscribedCount'] ?? 0);
|
||||||
$subscribedSubscribersCount = $this->subscribersRepository->getCountOfSubscribersForStates([SubscriberEntity::STATUS_SUBSCRIBED]);
|
$subscribedSubscribersCount = intval($counts['subscribedSubscribersCount'] ?? 0);
|
||||||
$subscribedSubscribers30DaysAgo = $subscribedSubscribersCount - $subscribedCount + $unsubscribedCount;
|
$subscribedSubscribers30DaysAgo = $subscribedSubscribersCount - $subscribedCount + $unsubscribedCount;
|
||||||
if ($subscribedSubscribers30DaysAgo > 0) {
|
if ($subscribedSubscribers30DaysAgo > 0) {
|
||||||
$globalChangePercent = (($subscribedSubscribersCount - $subscribedSubscribers30DaysAgo) / $subscribedSubscribers30DaysAgo) * 100;
|
$globalChangePercent = (($subscribedSubscribersCount - $subscribedSubscribers30DaysAgo) / $subscribedSubscribers30DaysAgo) * 100;
|
||||||
|
@@ -4,10 +4,14 @@ namespace MailPoet\Subscribers;
|
|||||||
|
|
||||||
use MailPoet\Cache\TransientCache;
|
use MailPoet\Cache\TransientCache;
|
||||||
use MailPoet\Entities\SegmentEntity;
|
use MailPoet\Entities\SegmentEntity;
|
||||||
|
use MailPoet\Entities\SubscriberEntity;
|
||||||
use MailPoet\InvalidStateException;
|
use MailPoet\InvalidStateException;
|
||||||
use MailPoet\Segments\SegmentsRepository;
|
use MailPoet\Segments\SegmentsRepository;
|
||||||
use MailPoet\Segments\SegmentSubscribersRepository;
|
use MailPoet\Segments\SegmentSubscribersRepository;
|
||||||
|
use MailPoet\Subscribers\SubscribersRepository;
|
||||||
use MailPoet\Tags\TagRepository;
|
use MailPoet\Tags\TagRepository;
|
||||||
|
use MailPoet\WP\Functions as WPFunctions;
|
||||||
|
use MailPoetVendor\Carbon\Carbon;
|
||||||
|
|
||||||
class SubscribersCountsController {
|
class SubscribersCountsController {
|
||||||
/** @var SegmentsRepository */
|
/** @var SegmentsRepository */
|
||||||
@@ -16,23 +20,33 @@ class SubscribersCountsController {
|
|||||||
/** @var SegmentSubscribersRepository */
|
/** @var SegmentSubscribersRepository */
|
||||||
private $segmentSubscribersRepository;
|
private $segmentSubscribersRepository;
|
||||||
|
|
||||||
|
/** @var SubscribersRepository */
|
||||||
|
private $subscribersRepository;
|
||||||
|
|
||||||
/** @var TagRepository */
|
/** @var TagRepository */
|
||||||
private $tagRepository;
|
private $tagRepository;
|
||||||
|
|
||||||
/** @var TransientCache */
|
/** @var TransientCache */
|
||||||
private $transientCache;
|
private $transientCache;
|
||||||
|
|
||||||
|
/** @var WPFunctions */
|
||||||
|
private $wp;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
SegmentsRepository $segmentsRepository,
|
SegmentsRepository $segmentsRepository,
|
||||||
SegmentSubscribersRepository $segmentSubscribersRepository,
|
SegmentSubscribersRepository $segmentSubscribersRepository,
|
||||||
|
SubscribersRepository $subscribersRepository,
|
||||||
TagRepository $subscriberTagRepository,
|
TagRepository $subscriberTagRepository,
|
||||||
TransientCache $transientCache
|
TransientCache $transientCache,
|
||||||
|
WPFunctions $wp
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
|
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
|
||||||
$this->transientCache = $transientCache;
|
$this->transientCache = $transientCache;
|
||||||
$this->segmentsRepository = $segmentsRepository;
|
$this->segmentsRepository = $segmentsRepository;
|
||||||
|
$this->subscribersRepository = $subscribersRepository;
|
||||||
$this->tagRepository = $subscriberTagRepository;
|
$this->tagRepository = $subscriberTagRepository;
|
||||||
|
$this->wp = $wp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSubscribersWithoutSegmentStatisticsCount(): array {
|
public function getSubscribersWithoutSegmentStatisticsCount(): array {
|
||||||
@@ -71,6 +85,14 @@ class SubscribersCountsController {
|
|||||||
return $result;
|
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 {
|
public function recalculateSegmentGlobalStatusStatisticsCache(SegmentEntity $segment): array {
|
||||||
$result = $this->segmentSubscribersRepository->getSubscribersGlobalStatusStatisticsCount($segment);
|
$result = $this->segmentSubscribersRepository->getSubscribersGlobalStatusStatisticsCount($segment);
|
||||||
$this->transientCache->setItem(
|
$this->transientCache->setItem(
|
||||||
@@ -97,6 +119,22 @@ class SubscribersCountsController {
|
|||||||
return $result;
|
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() {
|
public function removeRedundancyFromStatisticsCache() {
|
||||||
$segments = $this->segmentsRepository->findAll();
|
$segments = $this->segmentsRepository->findAll();
|
||||||
$segmentIds = array_map(function (SegmentEntity $segment): int {
|
$segmentIds = array_map(function (SegmentEntity $segment): int {
|
||||||
|
Reference in New Issue
Block a user