mirror of
https://github.com/AzuraCast/AzuraCast.git
synced 2024-06-14 21:26:37 +00:00
207 lines
6.0 KiB
PHP
207 lines
6.0 KiB
PHP
<?php
|
|
|
|
namespace App\Sync;
|
|
|
|
use App\Entity\Repository\SettingsRepository;
|
|
use App\Environment;
|
|
use App\Event\GetSyncTasks;
|
|
use App\EventDispatcher;
|
|
use App\LockFactory;
|
|
use App\Message;
|
|
use Monolog\Handler\StreamHandler;
|
|
use Monolog\Logger;
|
|
use Psr\Log\LogLevel;
|
|
|
|
/**
|
|
* The runner of scheduled synchronization tasks.
|
|
*/
|
|
class Runner
|
|
{
|
|
protected Logger $logger;
|
|
|
|
protected Environment $environment;
|
|
|
|
protected SettingsRepository $settingsRepo;
|
|
|
|
protected LockFactory $lockFactory;
|
|
|
|
protected EventDispatcher $eventDispatcher;
|
|
|
|
public function __construct(
|
|
SettingsRepository $settingsRepo,
|
|
Environment $environment,
|
|
Logger $logger,
|
|
LockFactory $lockFactory,
|
|
EventDispatcher $eventDispatcher
|
|
) {
|
|
$this->settingsRepo = $settingsRepo;
|
|
$this->environment = $environment;
|
|
$this->logger = $logger;
|
|
$this->lockFactory = $lockFactory;
|
|
$this->eventDispatcher = $eventDispatcher;
|
|
}
|
|
|
|
public function __invoke(Message\AbstractMessage $message): void
|
|
{
|
|
if ($message instanceof Message\RunSyncTaskMessage) {
|
|
$outputPath = $message->outputPath;
|
|
|
|
if (null !== $outputPath) {
|
|
$logHandler = new StreamHandler($outputPath, LogLevel::DEBUG, true);
|
|
$this->logger->pushHandler($logHandler);
|
|
}
|
|
|
|
$this->runSyncTask($message->type, true);
|
|
|
|
if (null !== $outputPath) {
|
|
$this->logger->popHandler();
|
|
}
|
|
}
|
|
}
|
|
|
|
public function runSyncTask(string $type, bool $force = false): void
|
|
{
|
|
// Immediately halt if setup is not complete.
|
|
$settings = $this->settingsRepo->readSettings();
|
|
if (!$settings->isSetupComplete()) {
|
|
$this->logger->notice(
|
|
sprintf('Skipping sync task %s; setup not complete.', $type)
|
|
);
|
|
return;
|
|
}
|
|
|
|
$allSyncInfo = $this->getSyncTimes();
|
|
|
|
if (!isset($allSyncInfo[$type])) {
|
|
throw new \InvalidArgumentException(sprintf('Invalid sync task: %s', $type));
|
|
}
|
|
|
|
$syncInfo = $allSyncInfo[$type];
|
|
|
|
set_time_limit($syncInfo['timeout']);
|
|
|
|
$this->logger->notice(
|
|
sprintf('Running sync task: %s', $syncInfo['name']),
|
|
[
|
|
'force' => $force,
|
|
]
|
|
);
|
|
|
|
$lock = $this->lockFactory->createLock('sync_' . $type, $syncInfo['timeout']);
|
|
|
|
if ($force) {
|
|
$this->lockFactory->clearQueue('sync_' . $type);
|
|
try {
|
|
$lock->acquire($force);
|
|
} catch (\Exception $e) {
|
|
// Noop
|
|
}
|
|
} elseif (!$lock->acquire()) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$event = new GetSyncTasks($type);
|
|
$this->eventDispatcher->dispatch($event);
|
|
|
|
$tasks = $event->getTasks();
|
|
|
|
foreach ($tasks as $taskClass => $task) {
|
|
if (!$force && !$lock->isAcquired()) {
|
|
$this->logger->error(
|
|
sprintf('Lock timed out before task %s can run.', $taskClass)
|
|
);
|
|
return;
|
|
}
|
|
|
|
$this->logger->debug(sprintf(
|
|
'Starting sub-task: %s',
|
|
$taskClass
|
|
));
|
|
|
|
$start_time = microtime(true);
|
|
|
|
$task->run($force);
|
|
|
|
$end_time = microtime(true);
|
|
$time_diff = $end_time - $start_time;
|
|
|
|
$this->logger->debug(
|
|
sprintf(
|
|
'Timer "%s" completed in %01.3f second(s).',
|
|
$taskClass,
|
|
round($time_diff, 3)
|
|
)
|
|
);
|
|
}
|
|
|
|
$settings = $this->settingsRepo->readSettings(true);
|
|
$settings->updateSyncLastRunTime($type);
|
|
$this->settingsRepo->writeSettings($settings);
|
|
} finally {
|
|
$lock->release();
|
|
}
|
|
|
|
$this->logger->debug(
|
|
sprintf('Sync task "%s" completed successfully.', $syncInfo['name']),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return mixed[]
|
|
*/
|
|
public function getSyncTimes(): array
|
|
{
|
|
$shortTaskTimeout = $this->environment->getSyncShortExecutionTime();
|
|
$longTaskTimeout = $this->environment->getSyncLongExecutionTime();
|
|
|
|
$settings = $this->settingsRepo->readSettings();
|
|
|
|
$syncs = [
|
|
GetSyncTasks::SYNC_NOWPLAYING => [
|
|
'name' => __('Now Playing Data'),
|
|
'contents' => [
|
|
__('Now Playing Data'),
|
|
],
|
|
'timeout' => $shortTaskTimeout,
|
|
'latest' => $settings->getSyncNowplayingLastRun(),
|
|
'interval' => 15,
|
|
],
|
|
GetSyncTasks::SYNC_SHORT => [
|
|
'name' => __('1-Minute Sync'),
|
|
'contents' => [
|
|
__('Song Requests Queue'),
|
|
],
|
|
'timeout' => $shortTaskTimeout,
|
|
'latest' => $settings->getSyncShortLastRun(),
|
|
'interval' => 60,
|
|
],
|
|
GetSyncTasks::SYNC_MEDIUM => [
|
|
'name' => __('5-Minute Sync'),
|
|
'contents' => [
|
|
__('Check Media Folders'),
|
|
],
|
|
'timeout' => $shortTaskTimeout,
|
|
'latest' => $settings->getSyncMediumLastRun(),
|
|
'interval' => 300,
|
|
],
|
|
GetSyncTasks::SYNC_LONG => [
|
|
'name' => __('1-Hour Sync'),
|
|
'contents' => [
|
|
__('Analytics/Statistics'),
|
|
__('Cleanup'),
|
|
],
|
|
'timeout' => $longTaskTimeout,
|
|
'latest' => $settings->getSyncLongLastRun(),
|
|
'interval' => 3600,
|
|
],
|
|
];
|
|
|
|
foreach ($syncs as &$sync_info) {
|
|
$sync_info['diff'] = time() - $sync_info['latest'];
|
|
}
|
|
|
|
return $syncs;
|
|
}
|
|
}
|