From ea0b09e76097efd5d828b5190718bec3c57452b0 Mon Sep 17 00:00:00 2001 From: Uladzimir Tsykun Date: Sat, 28 Jan 2023 23:01:25 +0100 Subject: [PATCH] Enable cron cleanup commands --- composer.json | 2 +- composer.lock | 107 +++++++++++++++++------ src/Cron/Handler/CleanupDistDir.php | 30 +++---- src/Cron/Handler/CleanupJobStorage.php | 40 ++++----- src/Cron/Handler/ScheduleHookHandler.php | 8 +- src/Cron/WorkerMiddleware.php | 2 +- src/Kernel.php | 10 +++ 7 files changed, 127 insertions(+), 72 deletions(-) diff --git a/composer.json b/composer.json index 9da13ec0..7dc14382 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,7 @@ "knplabs/knp-menu-bundle": "^3.2", "laminas/laminas-feed": "^2.20", "nelmio/cors-bundle": "^2.2", - "okvpn/cron-bundle": "^0.1.1", + "okvpn/cron-bundle": "^0.2", "oro/doctrine-extensions": "^2.0", "pagerfanta/core": "^3.7", "pagerfanta/doctrine-orm-adapter": "^3.7", diff --git a/composer.lock b/composer.lock index 52c0f9d8..360d8a61 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "deb7138db151a4773876ee9a00f16917", + "content-hash": "f377185c47f6bdcc797d724452c7afb7", "packages": [ { "name": "babdev/pagerfanta-bundle", @@ -1987,30 +1987,32 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v2.3.1", + "version": "v3.3.2", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2" + "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/65b2d8ee1f10915efb3b55597da3404f096acba2", - "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8", + "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8", "shasum": "" }, "require": { - "php": "^7.0|^8.0" + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^6.4|^7.0|^8.0|^9.0" + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-webmozart-assert": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" @@ -2021,11 +2023,6 @@ "MIT" ], "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, { "name": "Chris Tankersley", "email": "chris@ctankersley.com", @@ -2039,7 +2036,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v2.3.1" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2" }, "funding": [ { @@ -2047,7 +2044,7 @@ "type": "github" } ], - "time": "2020-10-13T00:52:37+00:00" + "time": "2022-09-10T18:51:20+00:00" }, { "name": "egulias/email-validator", @@ -3046,22 +3043,22 @@ }, { "name": "okvpn/cron-bundle", - "version": "0.1.2", + "version": "0.2.1", "source": { "type": "git", "url": "https://github.com/vtsykun/cron-bundle.git", - "reference": "cfbfcbd047881a38079aa1b1a84b44753716691c" + "reference": "835df9afd2fcaf300de3246b5582e6f167b99a2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vtsykun/cron-bundle/zipball/cfbfcbd047881a38079aa1b1a84b44753716691c", - "reference": "cfbfcbd047881a38079aa1b1a84b44753716691c", + "url": "https://api.github.com/repos/vtsykun/cron-bundle/zipball/835df9afd2fcaf300de3246b5582e6f167b99a2d", + "reference": "835df9afd2fcaf300de3246b5582e6f167b99a2d", "shasum": "" }, "require": { - "dragonmantank/cron-expression": "^2.0", + "dragonmantank/cron-expression": "^2.0 || ^3.0", "php": ">=7.2", - "symfony/framework-bundle": "^3.4|^4.0|^5.0|^6.0" + "symfony/framework-bundle": "^3.4 || ^4.0 || ^5.0 || ^6.0" }, "suggest": { "symfony/lock": "For locking jobs", @@ -3109,7 +3106,7 @@ "issues": "https://github.com/vtsykun/cron-bundle/issues", "source": "https://github.com/vtsykun/cron-bundle/releases" }, - "time": "2023-01-01T02:33:18+00:00" + "time": "2023-01-28T21:29:36+00:00" }, { "name": "oro/doctrine-extensions", @@ -9189,6 +9186,64 @@ } ], "time": "2022-12-27T12:28:18+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" } ], "packages-dev": [ diff --git a/src/Cron/Handler/CleanupDistDir.php b/src/Cron/Handler/CleanupDistDir.php index 6cd51369..b1cc2f77 100644 --- a/src/Cron/Handler/CleanupDistDir.php +++ b/src/Cron/Handler/CleanupDistDir.php @@ -4,6 +4,7 @@ namespace Packeton\Cron\Handler; +use Okvpn\Bundle\CronBundle\Attribute\AsCron; use Packeton\Service\DistConfig; use Psr\Log\LoggerInterface; use Symfony\Component\Filesystem\Filesystem; @@ -11,32 +12,29 @@ /** * Remove unused mirrored package's *.zip archives */ +#[AsCron('40 1 */2 * *')] class CleanupDistDir { const DEFAULT_PERIOD = 60; // 60 days - private $fs; - private $distConfig; - private $logger; - - public function __construct(DistConfig $distConfig, LoggerInterface $logger) - { - $this->fs = new Filesystem(); - $this->distConfig = $distConfig; - $this->logger = $logger; + public function __construct( + private readonly DistConfig $distConfig, + private readonly LoggerInterface $logger, + private readonly Filesystem $fs, + ) { } - public function __invoke(array $arguments = []) + public function __invoke(array $arguments = []): array { $keepPeriod = $arguments['period'] ?? self::DEFAULT_PERIOD; $expireDate = new \DateTime('now', new \DateTimeZone('UTC')); - $expireDate->modify(sprintf('-%d days', $keepPeriod)); + $expireDate->modify(\sprintf('-%d days', $keepPeriod)); if (null === $this->distConfig->getDistDir() || !$this->fs->exists($this->distConfig->getDistDir())) { return []; } - $root = realpath($this->distConfig->getDistDir()); + $root = \realpath($this->distConfig->getDistDir()); $dir = new \RecursiveDirectoryIterator( $root, \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::SKIP_DOTS @@ -49,13 +47,13 @@ function (\SplFileInfo $current) use (&$paths, $expireDate) { if (!$current->getRealPath()) { return false; } - if ($current->isFile() && preg_match('/[a-f0-9]{40}\.zip$/', $current->getFilename())) { + if ($current->isFile() && \preg_match('/[a-f0-9]{40}\.zip$/', $current->getFilename())) { if ($current->getMTime() < $expireDate->getTimestamp()) { $paths[] = $current->getRealPath(); } return false; } - if (is_dir($current->getPathname()) && 0 !== strpos($current->getPathname(), '.')) { + if (\is_dir($current->getPathname()) && !\str_starts_with($current->getPathname(), '.')) { return true; } @@ -66,14 +64,14 @@ function (\SplFileInfo $current) use (&$paths, $expireDate) { $iterator = new \RecursiveIteratorIterator($filter); $iterator->rewind(); if ($paths) { - $this->logger->info(sprintf('Unused %s *.zip archives was found', count($paths)), ['paths' => $paths]); + $this->logger->info(\sprintf('Unused %s *.zip archives was found', \count($paths)), ['paths' => $paths]); } foreach ($paths as $path) { try { $this->fs->remove($path); } catch (\Exception $exception) { - $this->logger->warning(sprintf('Unable to delete the file "%s", cause %s', $path, $exception->getMessage()), ['path' => $path, 'e' => $exception]); + $this->logger->warning(\sprintf('Unable to delete the file "%s", cause %s', $path, $exception->getMessage()), ['path' => $path, 'e' => $exception]); } } diff --git a/src/Cron/Handler/CleanupJobStorage.php b/src/Cron/Handler/CleanupJobStorage.php index dd23e9ad..1713dcf5 100644 --- a/src/Cron/Handler/CleanupJobStorage.php +++ b/src/Cron/Handler/CleanupJobStorage.php @@ -5,28 +5,27 @@ namespace Packeton\Cron\Handler; use Doctrine\Persistence\ManagerRegistry; +use Okvpn\Bundle\CronBundle\Attribute\AsCron; use Packeton\Entity\Job; use Psr\Log\LoggerInterface; /** * Cron command to cleanup jobs storage */ +#[AsCron('49 0 * * *')] class CleanupJobStorage { - private $registry; - private $logger; - - public function __construct(ManagerRegistry $registry, LoggerInterface $logger) - { - $this->registry = $registry; - $this->logger = $logger; + public function __construct( + private readonly ManagerRegistry $registry, + private readonly LoggerInterface $logger + ) { } - public function __invoke() + public function __invoke(): array { $keepPeriod = $this->selectKeepPeriod($count); $expireDate = new \DateTime('now', new \DateTimeZone('UTC')); - $expireDate->modify(sprintf('-%d days', $keepPeriod)); + $expireDate->modify(\sprintf('-%d days', $keepPeriod)); $rowCount = $this->registry->getRepository(Job::class) ->createQueryBuilder('j') @@ -36,7 +35,7 @@ public function __invoke() ->getQuery() ->execute(); - $this->logger->info(sprintf('Removed %s jobs from storage, since: %s, jobs count: %s', $rowCount, $expireDate->format('c'), $count)); + $this->logger->info(\sprintf('Removed %s jobs from storage, since: %s, jobs count: %s', $rowCount, $expireDate->format('c'), $count)); return [ 'since' => $expireDate->format('c'), @@ -45,7 +44,7 @@ public function __invoke() ]; } - protected function selectKeepPeriod(&$count = null) + protected function selectKeepPeriod(&$count = null): int { $count = $this->registry->getRepository(Job::class) ->createQueryBuilder('j') @@ -54,17 +53,12 @@ protected function selectKeepPeriod(&$count = null) ->getQuery() ->getSingleScalarResult(); - switch ($count) { - case $count > 60000: - return 2; - case $count > 40000: - return 5; - case $count > 25000: - return 10; - case $count > 10000: - return 21; - } - - return 60; + return match ($count) { + $count > 60000 => 2, + $count > 40000 => 5, + $count > 25000 => 10, + $count > 10000 => 21, + default => 60, + }; } } diff --git a/src/Cron/Handler/ScheduleHookHandler.php b/src/Cron/Handler/ScheduleHookHandler.php index 047d43b2..2c19a5df 100644 --- a/src/Cron/Handler/ScheduleHookHandler.php +++ b/src/Cron/Handler/ScheduleHookHandler.php @@ -4,15 +4,13 @@ namespace Packeton\Cron\Handler; +use Okvpn\Bundle\CronBundle\CronServiceInterface; use Packeton\Webhook\HookBus; -class ScheduleHookHandler +class ScheduleHookHandler implements CronServiceInterface { - private $hookBus; - - public function __construct(HookBus $hookBus) + public function __construct(private readonly HookBus $hookBus) { - $this->hookBus = $hookBus; } /** diff --git a/src/Cron/WorkerMiddleware.php b/src/Cron/WorkerMiddleware.php index 4643118a..261f4aaa 100644 --- a/src/Cron/WorkerMiddleware.php +++ b/src/Cron/WorkerMiddleware.php @@ -27,7 +27,7 @@ public function handle(ScheduleEnvelope $envelope, StackInterface $stack): Sched return $stack->next()->handle($envelope, $stack); } - $envelopeData = serialize($envelope->without(WorkerStamp::class)); + $envelopeData = \serialize($envelope->without(WorkerStamp::class)); $this->jobScheduler->publish(WorkerStamp::JOB_NAME, [ 'envelope' => $envelopeData ]); diff --git a/src/Kernel.php b/src/Kernel.php index b6ffe4fc..5456586d 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -15,6 +15,7 @@ use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use Symfony\Component\ErrorHandler\DebugClassLoader; use Symfony\Component\HttpKernel\Kernel as BaseKernel; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; @@ -26,6 +27,15 @@ class Kernel extends BaseKernel configureRoutes as traitConfigureRoutes; } + public function __construct(string $environment, bool $debug) + { + if (\class_exists(DebugClassLoader::class)) { + DebugClassLoader::disable(); + } + + parent::__construct($environment, $debug); + } + private function configureContainer(ContainerConfigurator $container, LoaderInterface $loader, ContainerBuilder $builder): void { $configDir = $this->getConfigDir();