Add cron worker for reporting subscriber stats
[MAILPOET-3868]
This commit is contained in:
committed by
Veljko V
parent
b07326aaa4
commit
ffe291c521
@@ -131,4 +131,17 @@ class ServicesChecker {
|
||||
$mssKeyPendingApproval = $isApproved === false || $isApproved === 'false'; // API unfortunately saves this as a string
|
||||
return $mssActive && $mssKeyValid && $mssKeyPendingApproval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns MSS or Premium valid key.
|
||||
*/
|
||||
public function getAnyValidKey(): ?string {
|
||||
if ($this->isMailPoetAPIKeyValid(false, true)) {
|
||||
return $this->settings->get(Bridge::API_KEY_SETTING_NAME);
|
||||
}
|
||||
if ($this->isPremiumKeyValid(false)) {
|
||||
return $this->settings->get(Bridge::PREMIUM_KEY_SETTING_NAME);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -69,6 +69,7 @@ class Daemon {
|
||||
yield $this->workersFactory->createQueueWorker(); // not CronWorkerInterface compatible
|
||||
yield $this->workersFactory->createSendingServiceKeyCheckWorker();
|
||||
yield $this->workersFactory->createPremiumKeyCheckWorker();
|
||||
yield $this->workersFactory->createSubscribersStatsReportWorker();
|
||||
yield $this->workersFactory->createBounceWorker();
|
||||
yield $this->workersFactory->createExportFilesCleanupWorker();
|
||||
yield $this->workersFactory->createBeamerkWorker();
|
||||
|
62
lib/Cron/Workers/SubscribersStatsReport.php
Normal file
62
lib/Cron/Workers/SubscribersStatsReport.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace MailPoet\Cron\Workers;
|
||||
|
||||
use MailPoet\Config\ServicesChecker;
|
||||
use MailPoet\Cron\CronWorkerScheduler;
|
||||
use MailPoet\Entities\ScheduledTaskEntity;
|
||||
use MailPoet\Services\Bridge;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
use MailPoetVendor\Carbon\Carbon;
|
||||
|
||||
class SubscribersStatsReport extends SimpleWorker {
|
||||
const TASK_TYPE = 'subscribers_stats_report';
|
||||
|
||||
/** @var Bridge */
|
||||
private $bridge;
|
||||
|
||||
/** @var ServicesChecker */
|
||||
private $serviceChecker;
|
||||
|
||||
/** @var CronWorkerScheduler */
|
||||
private $workerScheduler;
|
||||
|
||||
public function __construct(
|
||||
Bridge $bridge,
|
||||
ServicesChecker $servicesChecker,
|
||||
CronWorkerScheduler $workerScheduler,
|
||||
WPFunctions $wp
|
||||
) {
|
||||
parent::__construct($wp);
|
||||
$this->bridge = $bridge;
|
||||
$this->serviceChecker = $servicesChecker;
|
||||
$this->workerScheduler = $workerScheduler;
|
||||
}
|
||||
|
||||
public function checkProcessingRequirements() {
|
||||
return (bool)$this->serviceChecker->getAnyValidKey();
|
||||
}
|
||||
|
||||
public function processTaskStrategy(ScheduledTaskEntity $task, $timer): bool {
|
||||
$key = $this->serviceChecker->getAnyValidKey();
|
||||
if ($key === null) {
|
||||
return false;
|
||||
}
|
||||
$result = $this->bridge->updateSubscriberCount($key);
|
||||
// We have a valid key, but request failed
|
||||
if ($result === false) {
|
||||
$this->workerScheduler->rescheduleProgressively($task);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getNextRunDate() {
|
||||
$date = Carbon::createFromTimestamp($this->wp->currentTime('timestamp'));
|
||||
// Spread the check within 6 hours after midnight so that all plugins don't ping the service at the same time
|
||||
return $date->startOfDay()
|
||||
->addDay()
|
||||
->addHours(rand(0, 5))
|
||||
->addMinutes(rand(0, 59))
|
||||
->addSeconds(rand(0, 59));
|
||||
}
|
||||
}
|
@@ -122,4 +122,9 @@ class WorkersFactory {
|
||||
public function createReEngagementEmailsSchedulerWorker() {
|
||||
return $this->container->get(ReEngagementEmailsScheduler::class);
|
||||
}
|
||||
|
||||
/** @return SubscribersStatsReport */
|
||||
public function createSubscribersStatsReportWorker() {
|
||||
return $this->container->get(SubscribersStatsReport::class);
|
||||
}
|
||||
}
|
||||
|
@@ -173,6 +173,7 @@ class ContainerConfigurator implements IContainerConfigurator {
|
||||
$container->autowire(\MailPoet\Cron\Workers\SubscribersEngagementScore::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Cron\Workers\SubscribersLastEngagement::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Cron\Workers\SubscribersCountCacheRecalculation::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Cron\Workers\SubscribersStatsReport::class)->setPublic(true);
|
||||
// Custom field
|
||||
$container->autowire(\MailPoet\CustomFields\ApiDataSanitizer::class);
|
||||
$container->autowire(\MailPoet\CustomFields\CustomFieldsRepository::class)->setPublic(true);
|
||||
|
@@ -214,20 +214,8 @@ class Bridge {
|
||||
return $state;
|
||||
}
|
||||
|
||||
public function updateSubscriberCount($result) {
|
||||
if (
|
||||
(
|
||||
!empty($result['state'])
|
||||
&& (
|
||||
$result['state'] === self::KEY_VALID
|
||||
|| $result['state'] === self::KEY_EXPIRING
|
||||
)
|
||||
)
|
||||
&& ($this->api instanceof API)
|
||||
) {
|
||||
return $this->api->updateSubscriberCount($this->subscribersFeature->getSubscribersCount());
|
||||
}
|
||||
return null;
|
||||
public function updateSubscriberCount(string $key): bool {
|
||||
return $this->getApi($key)->updateSubscriberCount($this->subscribersFeature->getSubscribersCount());
|
||||
}
|
||||
|
||||
public static function invalidateKey() {
|
||||
|
@@ -143,7 +143,7 @@ class API {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function updateSubscriberCount($count) {
|
||||
public function updateSubscriberCount($count): bool {
|
||||
$result = $this->request(
|
||||
$this->urlStats,
|
||||
['subscriber_count' => (int)$count],
|
||||
|
@@ -160,6 +160,67 @@ class ServicesCheckerTest extends \MailPoetTest {
|
||||
expect($result)->false();
|
||||
}
|
||||
|
||||
public function testItReturnsAnyValidKey() {
|
||||
$premiumKey = 'premium_key';
|
||||
$mssKey = 'mss_key';
|
||||
$this->settings->set(Bridge::PREMIUM_KEY_SETTING_NAME, $premiumKey);
|
||||
$this->settings->set(Bridge::API_KEY_SETTING_NAME, $mssKey);
|
||||
// Only MSS is Valid
|
||||
$this->settings->set(
|
||||
Bridge::PREMIUM_KEY_STATE_SETTING_NAME,
|
||||
[
|
||||
'state' => '',
|
||||
]
|
||||
);
|
||||
$this->settings->set(
|
||||
Bridge::API_KEY_STATE_SETTING_NAME,
|
||||
[
|
||||
'state' => Bridge::KEY_VALID,
|
||||
]
|
||||
);
|
||||
expect($this->servicesChecker->getAnyValidKey())->equals($mssKey);
|
||||
|
||||
// Only Premium is Valid
|
||||
$this->settings->set(
|
||||
Bridge::PREMIUM_KEY_STATE_SETTING_NAME,
|
||||
[
|
||||
'state' => Bridge::KEY_VALID,
|
||||
]
|
||||
);
|
||||
$this->settings->set(
|
||||
Bridge::API_KEY_STATE_SETTING_NAME,
|
||||
[
|
||||
'state' => '',
|
||||
]
|
||||
);
|
||||
expect($this->servicesChecker->getAnyValidKey())->equals($premiumKey);
|
||||
|
||||
// Both Valid (lets use MSS in that case)
|
||||
$this->settings->set(
|
||||
Bridge::API_KEY_STATE_SETTING_NAME,
|
||||
[
|
||||
'state' => Bridge::KEY_VALID,
|
||||
]
|
||||
);
|
||||
expect($this->servicesChecker->getAnyValidKey())->equals($mssKey);
|
||||
|
||||
// None valid
|
||||
// Only MSS is Valid
|
||||
$this->settings->set(
|
||||
Bridge::PREMIUM_KEY_STATE_SETTING_NAME,
|
||||
[
|
||||
'state' => '',
|
||||
]
|
||||
);
|
||||
$this->settings->set(
|
||||
Bridge::API_KEY_STATE_SETTING_NAME,
|
||||
[
|
||||
'state' => '',
|
||||
]
|
||||
);
|
||||
expect($this->servicesChecker->getAnyValidKey())->null();
|
||||
}
|
||||
|
||||
private function setMailPoetSendingMethod() {
|
||||
$this->settings->set(
|
||||
Mailer::MAILER_CONFIG_SETTING_NAME,
|
||||
|
@@ -292,6 +292,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
|
||||
'createStatsNotificationsWorkerForAutomatedEmails' => $worker,
|
||||
'createSendingServiceKeyCheckWorker' => $worker,
|
||||
'createPremiumKeyCheckWorker' => $worker,
|
||||
'createSubscribersStatsReportWorker' => $worker,
|
||||
'createBounceWorker' => $worker,
|
||||
'createMigrationWorker' => $worker,
|
||||
'createWooCommerceSyncWorker' => $worker,
|
||||
|
@@ -48,6 +48,7 @@ class DaemonTest extends \MailPoetTest {
|
||||
'createStatsNotificationsWorkerForAutomatedEmails' => $this->createSimpleWorkerMock(),
|
||||
'createSendingServiceKeyCheckWorker' => $this->createSimpleWorkerMock(),
|
||||
'createPremiumKeyCheckWorker' => $this->createSimpleWorkerMock(),
|
||||
'createSubscribersStatsReportWorker' => $this->createSimpleWorkerMock(),
|
||||
'createBounceWorker' => $this->createSimpleWorkerMock(),
|
||||
'createMigrationWorker' => $this->createSimpleWorkerMock(),
|
||||
'createWooCommerceSyncWorker' => $this->createSimpleWorkerMock(),
|
||||
|
@@ -201,21 +201,6 @@ class BridgeTest extends \MailPoetTest {
|
||||
}
|
||||
}
|
||||
|
||||
public function testItUpdatesSubscriberCount() {
|
||||
// it performs update if the key is valid or expiring
|
||||
$result = [];
|
||||
$result['state'] = Bridge::KEY_VALID;
|
||||
$updated = $this->bridge->updateSubscriberCount($result);
|
||||
expect($updated)->true();
|
||||
$result['state'] = Bridge::KEY_EXPIRING;
|
||||
$updated = $this->bridge->updateSubscriberCount($result);
|
||||
expect($updated)->true();
|
||||
// it does not perform update if the key is invalid
|
||||
$result['state'] = Bridge::KEY_INVALID;
|
||||
$updated = $this->bridge->updateSubscriberCount($result);
|
||||
expect($updated)->null();
|
||||
}
|
||||
|
||||
public function testItInvalidatesMSSKey() {
|
||||
$this->settings->set(
|
||||
Bridge::API_KEY_STATE_SETTING_NAME,
|
||||
|
@@ -29,7 +29,7 @@ class BridgeTestMockAPI extends API {
|
||||
return $this->processPremiumResponse($code);
|
||||
}
|
||||
|
||||
public function updateSubscriberCount($count) {
|
||||
public function updateSubscriberCount($count): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user