<?php declare(strict_types = 1);
namespace MailPoet\Cron\Workers;
if (!defined('ABSPATH')) exit;
use MailPoet\Entities\ScheduledTaskEntity;
use MailPoet\Newsletter\Sending\SendingQueuesRepository;
use MailPoet\Settings\SettingsController;
use MailPoetVendor\Carbon\Carbon;
/**
* Runs 4x daily in staggered 6-hour slots. Each run NULLs newsletter_rendered_body
* for completed sending queues older than the configured retention window (default 30 days).
* Processes in batches of 250 rows with a 30s time limit per run.
* Setting the retention to '' (Never) disables cleanup entirely.
*/
class SendingQueueBodyCleanup extends SimpleWorker {
const TASK_TYPE = 'sending_queue_body_cleanup';
const BATCH_SIZE = 250;
const MAX_EXECUTION_TIME = 30;
const SUPPORT_MULTIPLE_INSTANCES = false;
/** @var SendingQueuesRepository */
private $sendingQueuesRepository;
/** @var SettingsController */
private $settings;
public function __construct(
SendingQueuesRepository $sendingQueuesRepository,
SettingsController $settings
) {
$this->sendingQueuesRepository = $sendingQueuesRepository;
$this->settings = $settings;
parent::__construct();
}
public function processTaskStrategy(ScheduledTaskEntity $task, $timer) {
$retentionDays = (int)$this->settings->get('sending_queue_body_retention_days');
if ($retentionDays <= 0) {
return true;
}
$startTime = microtime(true);
do {
$this->cronHelper->enforceExecutionLimit($timer);
$updated = $this->sendingQueuesRepository->nullRenderedBodyForOldCompletedQueues(
$retentionDays,
self::BATCH_SIZE
);
if ($updated < self::BATCH_SIZE || (microtime(true) - $startTime) > self::MAX_EXECUTION_TIME) {
break;
}
} while (true);
return true;
}
public function schedule() {
$baseDate = Carbon::now()->millisecond(0)->startOfDay();
for ($slot = 0; $slot < 4; $slot++) {
$hour = $slot * 6 + mt_rand(0, 5);
$minute = mt_rand(0, 59);
$second = mt_rand(0, 59);
$scheduleDate = clone $baseDate;
$scheduleDate->setTime($hour, $minute, $second);
if ($scheduleDate->isPast()) {
$scheduleDate->addDay();
}
$this->cronWorkerScheduler->scheduleMultiple(static::TASK_TYPE, $scheduleDate);
}
}
public function getNextRunDate() {
$date = Carbon::now()->millisecond(0);
$timeSlot = mt_rand(0, 3);
$hour = $timeSlot * 6 + mt_rand(0, 5);
$minute = mt_rand(0, 59);
$date->setTime($hour, $minute, mt_rand(0, 59));
if ($date->isPast()) {
$date->addDay();
}
return $date;
}
}