Create worker for subscribers count calculation

[MAILPOET-3646]
This commit is contained in:
Jan Lysý
2021-07-01 15:25:36 +02:00
committed by Veljko V
parent 40a511c641
commit 77c00014ca
5 changed files with 91 additions and 0 deletions

View File

@@ -74,5 +74,6 @@ class Daemon {
yield $this->workersFactory->createStatsNotificationsWorkerForAutomatedEmails(); yield $this->workersFactory->createStatsNotificationsWorkerForAutomatedEmails();
yield $this->workersFactory->createSubscriberLinkTokensWorker(); yield $this->workersFactory->createSubscriberLinkTokensWorker();
yield $this->workersFactory->createSubscribersEngagementScoreWorker(); yield $this->workersFactory->createSubscribersEngagementScoreWorker();
yield $this->workersFactory->createSubscribersCountCacheRecalculationWorker();
} }
} }

View File

@@ -15,6 +15,7 @@ use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
use MailPoet\Cron\Workers\StatsNotifications\AutomatedEmails; use MailPoet\Cron\Workers\StatsNotifications\AutomatedEmails;
use MailPoet\Cron\Workers\StatsNotifications\Worker as StatsNotificationsWorker; use MailPoet\Cron\Workers\StatsNotifications\Worker as StatsNotificationsWorker;
use MailPoet\Cron\Workers\SubscriberLinkTokens; use MailPoet\Cron\Workers\SubscriberLinkTokens;
use MailPoet\Cron\Workers\SubscribersCountCacheRecalculation;
use MailPoet\Cron\Workers\SubscribersEngagementScore; use MailPoet\Cron\Workers\SubscribersEngagementScore;
use MailPoet\Cron\Workers\UnsubscribeTokens; use MailPoet\Cron\Workers\UnsubscribeTokens;
use MailPoet\Cron\Workers\WooCommercePastOrders; use MailPoet\Cron\Workers\WooCommercePastOrders;
@@ -213,6 +214,13 @@ class WordPress {
'status' => ['null', ScheduledTask::STATUS_SCHEDULED], 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
]); ]);
// subscriber engagement score
$subscribersCountCacheRecalculationTasks = $this->getTasksCount([
'type' => SubscribersCountCacheRecalculation::TASK_TYPE,
'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
]);
// check requirements for each worker // check requirements for each worker
$sendingQueueActive = (($scheduledQueues || $runningQueues) && !$sendingLimitReached && !$sendingIsPaused); $sendingQueueActive = (($scheduledQueues || $runningQueues) && !$sendingLimitReached && !$sendingIsPaused);
$bounceSyncActive = ($mpSendingEnabled && ($bounceDueTasks || !$bounceFutureTasks)); $bounceSyncActive = ($mpSendingEnabled && ($bounceDueTasks || !$bounceFutureTasks));
@@ -237,6 +245,7 @@ class WordPress {
|| $unsubscribeTokensTasks || $unsubscribeTokensTasks
|| $subscriberLinkTokensTasks || $subscriberLinkTokensTasks
|| $subscriberEngagementScoreTasks || $subscriberEngagementScoreTasks
|| $subscribersCountCacheRecalculationTasks
); );
} }

View File

@@ -0,0 +1,75 @@
<?php declare(strict_types = 1);
namespace MailPoet\Cron\Workers;
use MailPoet\Cache\TransientCache;
use MailPoet\Entities\SegmentEntity;
use MailPoet\Models\ScheduledTask;
use MailPoet\Segments\SegmentsRepository;
use MailPoet\Segments\SegmentSubscribersRepository;
use MailPoet\WP\Functions as WPFunctions;
use MailPoetVendor\Carbon\Carbon;
class SubscribersCountCacheRecalculation extends SimpleWorker {
private const EXPIRATION_IN_MINUTES = 30;
const TASK_TYPE = 'subscribers_count_cache_recalculation';
const AUTOMATIC_SCHEDULING = false;
const SUPPORT_MULTIPLE_INSTANCES = false;
/** @var TransientCache */
private $transientCache;
/** @var SegmentsRepository */
private $segmentsRepository;
/** @var SegmentSubscribersRepository */
private $segmentSubscribersRepository;
public function __construct(
TransientCache $transientCache,
SegmentsRepository $segmentsRepository,
SegmentSubscribersRepository $segmentSubscribersRepository,
WPFunctions $wp
) {
parent::__construct($wp);
$this->transientCache = $transientCache;
$this->segmentsRepository = $segmentsRepository;
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
}
public function processTaskStrategy(ScheduledTask $task, $timer) {
$segments = $this->segmentsRepository->findAll();
foreach ($segments as $segment) {
$this->recalculateSegmentCache($timer, (int)$segment->getId(), $segment);
}
// update cache for subscribers without segment
$this->recalculateSegmentCache($timer, 0);
return true;
}
private function recalculateSegmentCache($timer, int $segmentId, ?SegmentEntity $segment = null): void {
$this->cronHelper->enforceExecutionLimit($timer);
$now = Carbon::now();
$item = $this->transientCache->getItem(TransientCache::SUBSCRIBERS_STATISTICS_COUNT_KEY, $segmentId);
if ($item === null || $now->diffInMinutes($item['created_at']) > self::EXPIRATION_IN_MINUTES) {
$this->transientCache->invalidateItem(TransientCache::SUBSCRIBERS_STATISTICS_COUNT_KEY, $segmentId);
if ($segment) {
$this->segmentSubscribersRepository->getSubscribersStatisticsCount($segment);
} else {
$this->segmentSubscribersRepository->getSubscribersWithoutSegmentStatisticsCount();
}
}
}
public function getNextRunDate() {
return Carbon::createFromTimestamp($this->wp->currentTime('timestamp'));
}
public function shouldBeScheduled(): bool {
$now = Carbon::now();
$oldestCreatedAt = $this->transientCache->getOldestCreatedAt(TransientCache::SUBSCRIBERS_STATISTICS_COUNT_KEY);
return $oldestCreatedAt === null || $now->diffInMinutes($oldestCreatedAt) > self::EXPIRATION_IN_MINUTES;
}
}

View File

@@ -105,4 +105,9 @@ class WorkersFactory {
public function createWooCommercePastOrdersWorker() { public function createWooCommercePastOrdersWorker() {
return $this->container->get(WooCommercePastOrders::class); return $this->container->get(WooCommercePastOrders::class);
} }
/** @return SubscribersCountCacheRecalculation */
public function createSubscribersCountCacheRecalculationWorker() {
return $this->container->get(SubscribersCountCacheRecalculation::class);
}
} }

View File

@@ -169,6 +169,7 @@ class ContainerConfigurator implements IContainerConfigurator {
$container->autowire(\MailPoet\Cron\Workers\AuthorizedSendingEmailsCheck::class)->setPublic(true); $container->autowire(\MailPoet\Cron\Workers\AuthorizedSendingEmailsCheck::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\Workers\WooCommercePastOrders::class)->setPublic(true); $container->autowire(\MailPoet\Cron\Workers\WooCommercePastOrders::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\Workers\SubscribersEngagementScore::class)->setPublic(true); $container->autowire(\MailPoet\Cron\Workers\SubscribersEngagementScore::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\Workers\SubscribersCountCacheRecalculation::class)->setPublic(true);
// Custom field // Custom field
$container->autowire(\MailPoet\CustomFields\ApiDataSanitizer::class); $container->autowire(\MailPoet\CustomFields\ApiDataSanitizer::class);
$container->autowire(\MailPoet\CustomFields\CustomFieldsRepository::class)->setPublic(true); $container->autowire(\MailPoet\CustomFields\CustomFieldsRepository::class)->setPublic(true);