From bbed9c35d26cc8e6e50c101a63580c0e48c5c8f6 Mon Sep 17 00:00:00 2001 From: Rostislav Wolny Date: Thu, 1 Aug 2024 12:38:23 +0200 Subject: [PATCH] Add check and cleanup for Orphaned sending task subscribers --- .../js/src/help/data-inconsistencies.tsx | 4 ++++ .../DataInconsistencyController.php | 6 +++++- .../DataInconsistencyRepository.php | 21 +++++++++++++++++++ .../DataInconsistencyRepositoryTest.php | 16 ++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mailpoet/assets/js/src/help/data-inconsistencies.tsx b/mailpoet/assets/js/src/help/data-inconsistencies.tsx index 553a0175af..d7c2360406 100644 --- a/mailpoet/assets/js/src/help/data-inconsistencies.tsx +++ b/mailpoet/assets/js/src/help/data-inconsistencies.tsx @@ -19,6 +19,10 @@ export function DataInconsistencies({ dataInconsistencies }: Props) { const labelsMap = useMemo( () => ({ orphaned_sending_tasks: __('Orphaned Sending Tasks', 'mailpoet'), + orphaned_sending_task_subscribers: __( + 'Orphaned Sending Task Subscribers', + 'mailpoet', + ), }), [], ); diff --git a/mailpoet/lib/Util/DataInconsistency/DataInconsistencyController.php b/mailpoet/lib/Util/DataInconsistency/DataInconsistencyController.php index ba65323611..d608023146 100644 --- a/mailpoet/lib/Util/DataInconsistency/DataInconsistencyController.php +++ b/mailpoet/lib/Util/DataInconsistency/DataInconsistencyController.php @@ -6,9 +6,11 @@ use MailPoet\UnexpectedValueException; class DataInconsistencyController { const ORPHANED_SENDING_TASKS = 'orphaned_sending_tasks'; + const ORPHANED_SENDING_TASK_SUBSCRIBERS = 'orphaned_sending_task_subscribers'; const SUPPORTED_INCONSISTENCY_CHECKS = [ self::ORPHANED_SENDING_TASKS, + self::ORPHANED_SENDING_TASK_SUBSCRIBERS, ]; private DataInconsistencyRepository $repository; @@ -22,6 +24,7 @@ class DataInconsistencyController { public function getInconsistentDataStatus(): array { $result = [ self::ORPHANED_SENDING_TASKS => $this->repository->getOrphanedSendingTasksCount(), + self::ORPHANED_SENDING_TASK_SUBSCRIBERS => $this->repository->getOrphanedScheduledTasksSubscribersCount(), ]; $result['total'] = array_sum($result); return $result; @@ -33,7 +36,8 @@ class DataInconsistencyController { } if ($inconsistency === self::ORPHANED_SENDING_TASKS) { $this->repository->cleanupOrphanedSendingTasks(); - return; + } elseif ($inconsistency === self::ORPHANED_SENDING_TASK_SUBSCRIBERS) { + $this->repository->cleanupOrphanedScheduledTaskSubscribers(); } } } diff --git a/mailpoet/lib/Util/DataInconsistency/DataInconsistencyRepository.php b/mailpoet/lib/Util/DataInconsistency/DataInconsistencyRepository.php index 21702c372a..5f175d1e74 100644 --- a/mailpoet/lib/Util/DataInconsistency/DataInconsistencyRepository.php +++ b/mailpoet/lib/Util/DataInconsistency/DataInconsistencyRepository.php @@ -24,6 +24,17 @@ class DataInconsistencyRepository { return (int)$this->buildOrphanedSendingTasksQuery($builder)->getSingleScalarResult(); } + public function getOrphanedScheduledTasksSubscribersCount(): int { + $stTable = $this->entityManager->getClassMetadata(ScheduledTaskEntity::class)->getTableName(); + $stsTable = $this->entityManager->getClassMetadata(ScheduledTaskSubscriberEntity::class)->getTableName(); + $count = $this->entityManager->getConnection()->executeQuery(" + SELECT count(*) FROM $stsTable sts + LEFT JOIN $stTable st ON st.`id` = sts.`task_id` + WHERE st.`id` IS NULL + ")->fetchOne(); + return intval($count); + } + public function cleanupOrphanedSendingTasks(): int { $ids = $this->buildOrphanedSendingTasksQuery( $this->entityManager->createQueryBuilder() @@ -53,6 +64,16 @@ class DataInconsistencyRepository { return $countDeletedTasks; } + public function cleanupOrphanedScheduledTaskSubscribers(): int { + $stTable = $this->entityManager->getClassMetadata(ScheduledTaskEntity::class)->getTableName(); + $stsTable = $this->entityManager->getClassMetadata(ScheduledTaskSubscriberEntity::class)->getTableName(); + return (int)$this->entityManager->getConnection()->executeStatement(" + DELETE sts FROM $stsTable sts + LEFT JOIN $stTable st ON st.`id` = sts.`task_id` + WHERE st.`id` IS NULL + "); + } + private function buildOrphanedSendingTasksQuery(QueryBuilder $queryBuilder): Query { return $queryBuilder ->from(ScheduledTaskEntity::class, 'st') diff --git a/mailpoet/tests/integration/Util/DataInconsistency/DataInconsistencyRepositoryTest.php b/mailpoet/tests/integration/Util/DataInconsistency/DataInconsistencyRepositoryTest.php index 78d847a115..bb7312b245 100644 --- a/mailpoet/tests/integration/Util/DataInconsistency/DataInconsistencyRepositoryTest.php +++ b/mailpoet/tests/integration/Util/DataInconsistency/DataInconsistencyRepositoryTest.php @@ -60,4 +60,20 @@ class DataInconsistencyRepositoryTest extends \MailPoetTest { $taskSubscriberCount = $this->entityManager->getRepository(ScheduledTaskSubscriberEntity::class)->count([]); verify($taskSubscriberCount)->equals(0); } + + public function testItHandlesOrphanedScheduledTaskSubscribers(): void { + $taskWithSubscriber = (new ScheduledTask())->create(SendingQueueWorker::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); + + $subscriber1 = (new Subscriber())->create(); + (new ScheduledTaskSubscriber())->createProcessed($taskWithSubscriber, $subscriber1); + $subscriber2 = (new Subscriber())->create(); + (new ScheduledTaskSubscriber())->createProcessed($taskWithSubscriber, $subscriber2); + + $this->entityManager->remove($taskWithSubscriber); + $this->entityManager->flush(); + + verify($this->repository->getOrphanedScheduledTasksSubscribersCount())->equals(2); + $this->repository->cleanupOrphanedScheduledTaskSubscribers(); + verify($this->repository->getOrphanedScheduledTasksSubscribersCount())->equals(0); + } }