Refactor CronWorkerRunner to use Doctrine instead of Paris

[MAILPOET-3844]
This commit is contained in:
Rodrigo Primo
2021-09-22 15:09:43 -03:00
committed by Veljko V
parent 2c78db9e04
commit 498ceabc8c
5 changed files with 115 additions and 119 deletions

View File

@@ -3,7 +3,6 @@
namespace MailPoet\Cron;
use MailPoet\Entities\ScheduledTaskEntity;
use MailPoet\Models\ScheduledTask;
use MailPoet\Newsletter\Sending\ScheduledTasksRepository;
use MailPoet\WP\Functions as WPFunctions;
use MailPoetVendor\Carbon\Carbon;
@@ -66,16 +65,10 @@ class CronWorkerRunner {
try {
foreach ($dueTasks as $task) {
$parisTask = ScheduledTask::getFromDoctrineEntity($task);
if ($parisTask) {
$this->prepareTask($worker, $parisTask);
}
$this->prepareTask($worker, $task);
}
foreach ($runningTasks as $task) {
$parisTask = ScheduledTask::getFromDoctrineEntity($task);
if ($parisTask) {
$this->processTask($worker, $parisTask);
}
$this->processTask($worker, $task);
}
} catch (\Exception $e) {
if ($task && $e->getCode() !== CronHelper::DAEMON_EXECUTION_LIMIT_REACHED) {
@@ -95,21 +88,20 @@ class CronWorkerRunner {
return $this->scheduledTasksRepository->findRunningByType($worker->getTaskType(), self::TASK_BATCH_SIZE);
}
private function prepareTask(CronWorkerInterface $worker, ScheduledTask $task) {
private function prepareTask(CronWorkerInterface $worker, ScheduledTaskEntity $task) {
// abort if execution limit is reached
$this->cronHelper->enforceExecutionLimit($this->timer);
$doctrineTask = $this->convertTaskClassToDoctrine($task);
if ($doctrineTask) {
$prepareCompleted = $worker->prepareTaskStrategy($doctrineTask, $this->timer);
if ($prepareCompleted) {
$task->status = null;
$task->save();
}
$prepareCompleted = $worker->prepareTaskStrategy($task, $this->timer);
if ($prepareCompleted) {
$task->setStatus(null);
$this->scheduledTasksRepository->persist($task);
$this->scheduledTasksRepository->flush();
}
}
private function processTask(CronWorkerInterface $worker, ScheduledTask $task) {
private function processTask(CronWorkerInterface $worker, ScheduledTaskEntity $task) {
// abort if execution limit is reached
$this->cronHelper->enforceExecutionLimit($this->timer);
@@ -125,11 +117,7 @@ class CronWorkerRunner {
$this->startProgress($task);
try {
$completed = false;
$doctrineTask = $this->convertTaskClassToDoctrine($task);
if ($doctrineTask) {
$completed = $worker->processTaskStrategy($doctrineTask, $this->timer);
}
$completed = $worker->processTaskStrategy($task, $this->timer);
} catch (\Exception $e) {
$this->stopProgress($task);
throw $e;
@@ -144,18 +132,20 @@ class CronWorkerRunner {
return (bool)$completed;
}
private function rescheduleOutdated(ScheduledTask $task) {
private function rescheduleOutdated(ScheduledTaskEntity $task) {
$currentTime = Carbon::createFromTimestamp($this->wp->currentTime('timestamp'));
$updated = strtotime((string)$task->updatedAt);
if ($updated === false) {
if (empty($task->getUpdatedAt())) {
// missing updatedAt, consider this task outdated (set year to 2000) and reschedule
$updatedAt = Carbon::createFromDate(2000);
} else if (!$task->getUpdatedAt() instanceof Carbon) {
$updatedAt = new Carbon($task->getUpdatedAt());
} else {
$updatedAt = Carbon::createFromTimestamp($updated);
$updatedAt = $task->getUpdatedAt();
}
// If the task is running for too long consider it stuck and reschedule
if (!empty($task->updatedAt) && $updatedAt->diffInMinutes($currentTime, false) > self::TASK_RUN_TIMEOUT) {
if (!empty($task->getUpdatedAt()) && $updatedAt->diffInMinutes($currentTime, false) > self::TASK_RUN_TIMEOUT) {
$this->stopProgress($task);
$this->cronWorkerScheduler->reschedule($task, self::TIMED_OUT_TASK_RESCHEDULE_TIMEOUT);
return true;
@@ -163,39 +153,30 @@ class CronWorkerRunner {
return false;
}
private function isInProgress(ScheduledTask $task) {
if (!empty($task->inProgress)) {
private function isInProgress(ScheduledTaskEntity $task) {
if ($task->getInProgress()) {
// Do not run multiple instances of the task
return true;
}
return false;
}
private function startProgress(ScheduledTask $task) {
$task->inProgress = true;
$task->save();
private function startProgress(ScheduledTaskEntity $task) {
$task->setInProgress(true);
$this->scheduledTasksRepository->persist($task);
$this->scheduledTasksRepository->flush();
}
private function stopProgress(ScheduledTask $task) {
$task->inProgress = false;
$task->save();
private function stopProgress(ScheduledTaskEntity $task) {
$task->setInProgress(false);
$this->scheduledTasksRepository->persist($task);
$this->scheduledTasksRepository->flush();
}
private function complete(ScheduledTask $task) {
$task->processedAt = $this->wp->currentTime('mysql');
$task->status = ScheduledTask::STATUS_COMPLETED;
$task->save();
}
// temporary function to convert an ScheduledTask object to ScheduledTaskEntity while we don't migrate the rest of
// the code in this class to use Doctrine entities
private function convertTaskClassToDoctrine(ScheduledTask $parisTask): ?ScheduledTaskEntity {
$doctrineTask = $this->scheduledTasksRepository->findOneById($parisTask->id);
if (!$doctrineTask instanceof ScheduledTaskEntity) {
return null;
}
return $doctrineTask;
private function complete(ScheduledTaskEntity $task) {
$task->setProcessedAt(new Carbon());
$task->setStatus(ScheduledTaskEntity::STATUS_COMPLETED);
$this->scheduledTasksRepository->persist($task);
$this->scheduledTasksRepository->flush();
}
}

View File

@@ -88,9 +88,9 @@ class Bounce extends SimpleWorker {
return true; // mark completed
}
$parisTask = ScheduledTask::getFromDoctrineEntity($task);
$parisTask = ScheduledTask::findOne($task->getId());
if ($parisTask) {
if ($parisTask instanceof ScheduledTask) {
$taskSubscribers = new TaskSubscribers($parisTask);
foreach ($subscriberBatches as $subscribersToProcessIds) {