From b1ee0c99a583693f9a83f07bd5790b7bbbd02bc7 Mon Sep 17 00:00:00 2001 From: Flavio Heleno Date: Tue, 19 Apr 2022 21:03:17 -0300 Subject: [PATCH] Rewrite Package discovery --- app/messages.php | 5 - app/processors.php | 2 - .../Console/Packagist/GetDataCommand.php | 20 ++-- .../Console/Packagist/GetListCommand.php | 91 ++++++--------- .../Console/Packagist/GetUpdatesCommand.php | 20 ++-- .../Console/Packagist/MassImportCommand.php | 22 ++-- .../Console/Queue/ConsumeCommand.php | 28 ++--- src/Application/Console/Queue/ListCommand.php | 24 ++-- .../Command/PackageDiscoveryCommand.php | 37 ++++-- .../Command/UpdateDependencyStatusCommand.php | 12 +- .../Command/UpdateVersionStatusCommand.php | 12 +- .../Preference/AbstractPreferenceEvent.php | 26 +++++ .../Preference/PreferenceCreatedEvent.php | 7 ++ .../Preference/PreferenceUpdatedEvent.php | 7 ++ .../Handler/PackageDiscoveryHandler.php | 108 +++++++++--------- .../Handler/UpdateDependencyStatusHandler.php | 22 ++-- .../Handler/UpdateVersionStatusHandler.php | 28 ++--- .../Package/PackageCreatedListener.php | 33 ------ .../Package/PackageUpdatedListener.php | 2 +- .../Version/VersionCreatedListener.php | 9 -- src/Domain/Dependency/Dependency.php | 2 +- .../Dependency/PdoDependencyRepository.php | 25 +++- .../Package/PdoPackageRepository.php | 21 +++- .../Preference/PdoPreferenceRepository.php | 25 +++- .../Persistence/Stats/PdoStatsRepository.php | 21 +++- .../Version/PdoVersionRepository.php | 25 +++- 26 files changed, 333 insertions(+), 301 deletions(-) create mode 100644 src/Application/Message/Event/Preference/AbstractPreferenceEvent.php create mode 100644 src/Application/Message/Event/Preference/PreferenceCreatedEvent.php create mode 100644 src/Application/Message/Event/Preference/PreferenceUpdatedEvent.php delete mode 100644 src/Application/Processor/Listener/Package/PackageCreatedListener.php diff --git a/app/messages.php b/app/messages.php index 0efa2329..716174ed 100644 --- a/app/messages.php +++ b/app/messages.php @@ -32,11 +32,6 @@ /* PACKAGE EVENTS */ $router - ->addRoute( - PackageCreatedEvent::class, - PackageCreatedListener::class, - 'PackageCreated' - ) ->addRoute( PackageUpdatedEvent::class, PackageUpdatedListener::class, diff --git a/app/processors.php b/app/processors.php index 588911d6..84dd13c5 100644 --- a/app/processors.php +++ b/app/processors.php @@ -5,7 +5,6 @@ use App\Application\Processor\Handler\UpdateDependencyStatusHandler; use App\Application\Processor\Handler\UpdateVersionStatusHandler; use App\Application\Processor\Listener\Dependency\DependencyUpdatedListener; -use App\Application\Processor\Listener\Package\PackageCreatedListener; use App\Application\Processor\Listener\Package\PackageUpdatedListener; use App\Application\Processor\Listener\Version\VersionCreatedListener; use DI\ContainerBuilder; @@ -25,7 +24,6 @@ $containerBuilder->addDefinitions( [ DependencyUpdatedListener::class => autowire(DependencyUpdatedListener::class), - PackageCreatedListener::class => autowire(PackageCreatedListener::class), PackageUpdatedListener::class => autowire(PackageUpdatedListener::class), VersionCreatedListener::class => autowire(VersionCreatedListener::class), ] diff --git a/src/Application/Console/Packagist/GetDataCommand.php b/src/Application/Console/Packagist/GetDataCommand.php index 6458a641..2e181c3b 100644 --- a/src/Application/Console/Packagist/GetDataCommand.php +++ b/src/Application/Console/Packagist/GetDataCommand.php @@ -410,17 +410,15 @@ static function (string $key): bool { ) ); } catch (Exception $exception) { - if (isset($io) === true) { - $io->error( - sprintf( - '[%s] %s', - date('H:i:s'), - $exception->getMessage() - ) - ); - if ($output->isDebug()) { - $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); - } + $io->error( + sprintf( + '[%s] %s', + date('H:i:s'), + $exception->getMessage() + ) + ); + if ($output->isDebug()) { + $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); } return Command::FAILURE; diff --git a/src/Application/Console/Packagist/GetListCommand.php b/src/Application/Console/Packagist/GetListCommand.php index 77a459e4..b6071fca 100644 --- a/src/Application/Console/Packagist/GetListCommand.php +++ b/src/Application/Console/Packagist/GetListCommand.php @@ -4,8 +4,6 @@ namespace App\Application\Console\Packagist; use App\Application\Message\Command\PackageDiscoveryCommand; -use App\Application\Message\Event\Package\PackageCreatedEvent; -use App\Application\Message\Event\Package\PackageRemovedEvent; use App\Domain\Package\Package; use App\Domain\Package\PackageRepositoryInterface; use App\Application\Service\Packagist; @@ -41,10 +39,10 @@ protected function configure(): void { $this ->setDescription('Get the complete list of packages from a Packagist mirror') ->addOption( - 'resync', - 'r', + 'offline', + null, InputOption::VALUE_NONE, - 'Resync the list' + 'Work in offline mode' ) ->addOption( 'mirror', @@ -75,6 +73,19 @@ protected function execute(InputInterface $input, OutputInterface $output): int ) ); + $workOffline = (bool)$input->getOption('offline'); + + if ($workOffline) { + $io->text( + sprintf( + '[%s] Running in offline mode', + date('H:i:s') + ) + ); + + $this->packagist->setOffline(); + } + $mirror = $input->getOption('mirror'); if (filter_var($mirror, FILTER_VALIDATE_URL) === false) { throw new InvalidArgumentException('Invalid mirror option'); @@ -97,36 +108,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int ) ); - if ((bool)$input->getOption('resync')) { - $io->text( - sprintf( - '[%s] Running in resync mode', - date('H:i:s') - ) - ); - - foreach ($packageList as $package) { - if ($this->packageRepository->exists($package)) { - $package = $this->packageRepository->get($package); - } else { - $package = $this->packageRepository->create($package); - } - - $this->producer->sendCommand( - new PackageDiscoveryCommand($package) - ); - } - - $io->text( - sprintf( - '[%s] Done', - date('H:i:s') - ) - ); - - return Command::SUCCESS; - } - $packageCol = $this->packageRepository->all(); $packages = $packageCol->map( static function (Package $package): string { @@ -162,13 +143,13 @@ static function (Package $package): string { ) ); - $removeList = array_diff($packages, $packageList); + $remList = array_diff($packages, $packageList); $io->text( sprintf( '[%s] %s package(s) will be removed', date('H:i:s'), number_format( - count($removeList), + count($remList), 0, ',', '.' @@ -177,10 +158,8 @@ static function (Package $package): string { ); foreach ($addList as $packageName) { - $package = $this->packageRepository->create($packageName); - - $this->producer->sendEvent( - new PackageCreatedEvent($package) + $this->producer->sendCommand( + new PackageDiscoveryCommand($packageName, workOffline: $workOffline) ); if ($this->mustStop === true) { @@ -195,13 +174,11 @@ static function (Package $package): string { } } - foreach ($removeList as $packageName) { - // $this->packageRepository->delete($package); - // - // $this->producer->sendEvent( - // new PackageRemovedEvent($package) + foreach ($remList as $packageName) { + // $this->producer->sendCommand( + // new PackageRemovalCommand($packageName) // ); - // + // if ($this->mustStop === true) { // $io->text( // sprintf( @@ -221,17 +198,15 @@ static function (Package $package): string { ) ); } catch (Exception $exception) { - if (isset($io) === true) { - $io->error( - sprintf( - '[%s] %s', - date('H:i:s'), - $exception->getMessage() - ) - ); - if ($output->isDebug()) { - $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); - } + $io->error( + sprintf( + '[%s] %s', + date('H:i:s'), + $exception->getMessage() + ) + ); + if ($output->isDebug()) { + $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); } return Command::FAILURE; diff --git a/src/Application/Console/Packagist/GetUpdatesCommand.php b/src/Application/Console/Packagist/GetUpdatesCommand.php index 9355bdac..7b5f8c92 100644 --- a/src/Application/Console/Packagist/GetUpdatesCommand.php +++ b/src/Application/Console/Packagist/GetUpdatesCommand.php @@ -137,17 +137,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int ) ); } catch (Exception $exception) { - if (isset($io) === true) { - $io->error( - sprintf( - '[%s] %s', - date('H:i:s'), - $exception->getMessage() - ) - ); - if ($output->isDebug()) { - $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); - } + $io->error( + sprintf( + '[%s] %s', + date('H:i:s'), + $exception->getMessage() + ) + ); + if ($output->isDebug()) { + $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); } return Command::FAILURE; diff --git a/src/Application/Console/Packagist/MassImportCommand.php b/src/Application/Console/Packagist/MassImportCommand.php index f6e07a22..3356ff26 100644 --- a/src/Application/Console/Packagist/MassImportCommand.php +++ b/src/Application/Console/Packagist/MassImportCommand.php @@ -126,17 +126,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int ) ); } catch (Exception $exception) { - if (isset($io) === true) { - $io->error( - sprintf( - '[%s] %s', - date('H:i:s'), - $exception->getMessage() - ) - ); - if ($output->isDebug()) { - $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); - } + $io->error( + sprintf( + '[%s] %s', + date('H:i:s'), + $exception->getMessage() + ) + ); + if ($output->isDebug()) { + $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); } return Command::FAILURE; @@ -146,7 +144,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } public function __construct(PackageRepositoryInterface $packageRepository) { - $this->packageRepository = $packageRepository; + $this->packageRepository = $packageRepository; parent::__construct(); } diff --git a/src/Application/Console/Queue/ConsumeCommand.php b/src/Application/Console/Queue/ConsumeCommand.php index 67ec7988..44d24d5e 100644 --- a/src/Application/Console/Queue/ConsumeCommand.php +++ b/src/Application/Console/Queue/ConsumeCommand.php @@ -43,7 +43,7 @@ protected function configure(): void { 1 ) ->addArgument( - 'name', + 'queueName', InputArgument::REQUIRED, 'Name of the bus queue' ); @@ -73,7 +73,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $messageCount = (int)$input->getOption('messageCount'); - $queueName = $input->getArgument('name'); + $queueName = $input->getArgument('queueName'); if ($output->isVerbose()) { $io->text( @@ -124,17 +124,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int ) ); } catch (Exception $exception) { - if (isset($io) === true) { - $io->error( - sprintf( - '[%s] %s', - date('H:i:s'), - $exception->getMessage() - ) - ); - if ($output->isDebug()) { - $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); - } + $io->error( + sprintf( + '[%s] %s', + date('H:i:s'), + $exception->getMessage() + ) + ); + if ($output->isDebug()) { + $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); } return Command::FAILURE; @@ -143,9 +141,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::SUCCESS; } - public function __construct( - Consumer $consumer - ) { + public function __construct(Consumer $consumer) { $this->consumer = $consumer; parent::__construct(); diff --git a/src/Application/Console/Queue/ListCommand.php b/src/Application/Console/Queue/ListCommand.php index a0c9d5aa..3aab8a93 100644 --- a/src/Application/Console/Queue/ListCommand.php +++ b/src/Application/Console/Queue/ListCommand.php @@ -70,17 +70,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int $table->render(); } catch (Exception $exception) { - if (isset($io) === true) { - $io->error( - sprintf( - '[%s] %s', - date('H:i:s'), - $exception->getMessage() - ) - ); - if ($output->isDebug()) { - $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); - } + $io->error( + sprintf( + '[%s] %s', + date('H:i:s'), + $exception->getMessage() + ) + ); + if ($output->isDebug()) { + $io->listing(explode(PHP_EOL, $exception->getTraceAsString())); } return Command::FAILURE; @@ -89,9 +87,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::SUCCESS; } - public function __construct( - Bus $bus - ) { + public function __construct(Bus $bus) { $this->bus = $bus; parent::__construct(); diff --git a/src/Application/Message/Command/PackageDiscoveryCommand.php b/src/Application/Message/Command/PackageDiscoveryCommand.php index 00f9370d..4848ae91 100644 --- a/src/Application/Message/Command/PackageDiscoveryCommand.php +++ b/src/Application/Message/Command/PackageDiscoveryCommand.php @@ -3,36 +3,49 @@ namespace App\Application\Message\Command; -use App\Domain\Package\Package; use Courier\Message\CommandInterface; final class PackageDiscoveryCommand implements CommandInterface { - private Package $package; + private string $packageName; /** * Force command execution (ie. skips command deduplication guards) */ - private bool $force; + private bool $forceExecution; + /** + * Work in offline mode (ie. avoids connecting to packagist's mirror) + */ + private bool $workOffline; - public function __construct(Package $package, bool $force = false) { - $this->package = $package; - $this->force = $force; + public function __construct( + string $packageName, + bool $forceExecution = false, + bool $workOffline = false + ) { + $this->packageName = $packageName; + $this->forceExecution = $forceExecution; + $this->workOffline = $workOffline; } - public function getPackage(): Package { - return $this->package; + public function getPackageName(): string { + return $this->packageName; } public function forceExecution(): bool { - return $this->force; + return $this->forceExecution; + } + + public function workOffline(): bool { + return $this->workOffline; } /** * @return array{ - * 0: \App\Domain\Package\Package, - * 1: bool + * 0: string, + * 1: bool, + * 2: bool * } */ public function toArray(): array { - return [$this->package, $this->force]; + return [$this->packageName, $this->forceExecution, $this->workOffline]; } } diff --git a/src/Application/Message/Command/UpdateDependencyStatusCommand.php b/src/Application/Message/Command/UpdateDependencyStatusCommand.php index ec50340e..4a0988e1 100644 --- a/src/Application/Message/Command/UpdateDependencyStatusCommand.php +++ b/src/Application/Message/Command/UpdateDependencyStatusCommand.php @@ -11,11 +11,11 @@ final class UpdateDependencyStatusCommand implements CommandInterface { /** * Force command execution (ie. skips command deduplication guards) */ - private bool $force; + private bool $forceExecution; - public function __construct(Package $package, bool $force = false) { - $this->package = $package; - $this->force = $force; + public function __construct(Package $package, bool $forceExecution = false) { + $this->package = $package; + $this->forceExecution = $forceExecution; } public function getPackage(): Package { @@ -23,7 +23,7 @@ public function getPackage(): Package { } public function forceExecution(): bool { - return $this->force; + return $this->forceExecution; } /** @@ -33,6 +33,6 @@ public function forceExecution(): bool { * } */ public function toArray(): array { - return [$this->package, $this->force]; + return [$this->package, $this->forceExecution]; } } diff --git a/src/Application/Message/Command/UpdateVersionStatusCommand.php b/src/Application/Message/Command/UpdateVersionStatusCommand.php index 30070427..08743429 100644 --- a/src/Application/Message/Command/UpdateVersionStatusCommand.php +++ b/src/Application/Message/Command/UpdateVersionStatusCommand.php @@ -11,11 +11,11 @@ final class UpdateVersionStatusCommand implements CommandInterface { /** * Force command execution (ie. skips command deduplication guards) */ - private bool $force; + private bool $forceExecution; - public function __construct(Dependency $dependency, bool $force = false) { - $this->dependency = $dependency; - $this->force = $force; + public function __construct(Dependency $dependency, bool $forceExecution = false) { + $this->dependency = $dependency; + $this->forceExecution = $forceExecution; } public function getDependency(): Dependency { @@ -23,7 +23,7 @@ public function getDependency(): Dependency { } public function forceExecution(): bool { - return $this->force; + return $this->forceExecution; } /** @@ -33,6 +33,6 @@ public function forceExecution(): bool { * } */ public function toArray(): array { - return [$this->dependency, $this->force]; + return [$this->dependency, $this->forceExecution]; } } diff --git a/src/Application/Message/Event/Preference/AbstractPreferenceEvent.php b/src/Application/Message/Event/Preference/AbstractPreferenceEvent.php new file mode 100644 index 00000000..cdd11b9e --- /dev/null +++ b/src/Application/Message/Event/Preference/AbstractPreferenceEvent.php @@ -0,0 +1,26 @@ +preference = $preference; + } + + public function getPreference(): Preference { + return $this->preference; + } + + /** + * @return array{0: \App\Domain\Preference\Preference} + */ + public function toArray(): array { + return [$this->preference]; + } +} diff --git a/src/Application/Message/Event/Preference/PreferenceCreatedEvent.php b/src/Application/Message/Event/Preference/PreferenceCreatedEvent.php new file mode 100644 index 00000000..7aa33459 --- /dev/null +++ b/src/Application/Message/Event/Preference/PreferenceCreatedEvent.php @@ -0,0 +1,7 @@ +dependencyRepository = $dependencyRepository; $this->packageRepository = $packageRepository; $this->versionRepository = $versionRepository; - $this->producer = $producer; $this->packagist = $packagist; $this->logger = $logger; } @@ -83,23 +96,32 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han } try { - $package = $command->getPackage(); + switch ($command->workOffline()) { + case true: + $this->packagist->workOffline(); + break; + case false: + $this->packagist->workOnline(); + break; + } - $packageName = $package->getName(); + $packageName = $command->getPackageName(); - // check for job duplication + // guard for job duplication $uniqueId = $packageName; $timestamp = ($attributes['timestamp'] ?? new DateTimeImmutable())->getTimestamp(); if ( $command->forceExecution() === false && $lastUniqueId === $uniqueId && + $lastTimestamp > 0 && $timestamp - $lastTimestamp < 10 ) { $this->logger->debug( 'Package discovery handler: Skipping duplicated job', [ + 'timestamp' => $timestamp, 'lastUniqueId' => $lastUniqueId, - 'lastTimestamp' => (new DateTimeImmutable)->setTimestamp($lastTimestamp)->format(DateTimeInterface::ATOM) + 'lastTimestamp' => (new DateTimeImmutable())->setTimestamp($lastTimestamp)->format(DateTimeInterface::ATOM) ] ); @@ -112,6 +134,12 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han ['package' => $packageName] ); + if ($this->packageRepository->exists($packageName)) { + $package = $this->packageRepository->get($packageName); + } else { + $package = $this->packageRepository->create($packageName); + } + $pkgs = [ // dev versions "${packageName}~dev", @@ -127,16 +155,19 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han continue; } + // ensure latest tagged version is set when importing a package for the first time + if ($pkg === $packageName && $package->getLatestVersion() === '') { + $package = $package->withLatestVersion( + $this->findLatestVersion($metadata) + ); + } + $package = $package ->withDescription($metadata[0]['description'] ?? '') - ->withUrl($metadata[0]['source']['url'] ?? ''); - if ($package->isDirty()) { - $package = $this->packageRepository->update($package); - - $this->producer->sendEvent( - new PackageUpdatedEvent($package) + ->withUrl( + preg_replace('/\.git$/', '', ($metadata[0]['source']['url'] ?? '')) ); - } + $package = $this->packageRepository->update($package); $this->logger->debug( 'Processing release list', @@ -168,30 +199,15 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han VersionStatusEnum::Unknown, new DateTimeImmutable($release['time'] ?? 'now') ); - - $this->producer->sendEvent( - new VersionCreatedEvent($version) - ); } // track "require" dependencies - $filteredRequire = array_filter( - $release['require'] ?? [], - static function (string $key): bool { - return preg_match('/^(php|hhvm|ext-.*|lib-.*|pear-.*)$/', $key) !== 1 && - preg_match('/^[^\/]+\/[^\/]+$/', $key) === 1; - }, - ARRAY_FILTER_USE_KEY - ); + $filteredRequire = $this->filterDeps($release['require'] ?? []); // flag packages without require dependencies with VersionStatusEnum::NoDeps if (empty($filteredRequire)) { $version = $version->withStatus(VersionStatusEnum::NoDeps); $version = $this->versionRepository->update($version); - - $this->producer->sendEvent( - new VersionUpdatedEvent($version) - ); } $this->logger->debug( @@ -226,23 +242,11 @@ static function (string $key): bool { $constraint, false ); - - $this->producer->sendEvent( - new DependencyCreatedEvent($dependency) - ); } } // track "require-dev" dependencies - $filteredRequireDev = array_filter( - $release['require-dev'] ?? [], - static function (string $key): bool { - return preg_match('/^(php|hhvm|ext-.*|lib-.*|pear-.*)$/', $key) !== 1 && - preg_match('/^[^\/]+\/[^\/]+$/', $key) === 1; - }, - ARRAY_FILTER_USE_KEY - ); - + $filteredRequireDev = $this->filterDeps($release['require-dev'] ?? []); if (empty($filteredRequireDev)) { continue; } @@ -279,10 +283,6 @@ static function (string $key): bool { $constraint, true ); - - $this->producer->sendEvent( - new DependencyCreatedEvent($dependency) - ); } } } @@ -297,7 +297,7 @@ static function (string $key): bool { $this->logger->error( $exception->getMessage(), [ - 'package' => $packageName, + 'package' => $command->getPackageName(), 'exception' => [ 'file' => $exception->getFile(), 'line' => $exception->getLine(), diff --git a/src/Application/Processor/Handler/UpdateDependencyStatusHandler.php b/src/Application/Processor/Handler/UpdateDependencyStatusHandler.php index f0eebb1c..fda8d2cc 100644 --- a/src/Application/Processor/Handler/UpdateDependencyStatusHandler.php +++ b/src/Application/Processor/Handler/UpdateDependencyStatusHandler.php @@ -4,11 +4,9 @@ namespace App\Application\Processor\Handler; use App\Application\Message\Command\UpdateDependencyStatusCommand; -use App\Application\Message\Event\Dependency\DependencyUpdatedEvent; use App\Domain\Dependency\DependencyRepositoryInterface; use App\Domain\Dependency\DependencyStatusEnum; use Composer\Semver\Semver; -use Courier\Client\Producer\ProducerInterface; use Courier\Message\CommandInterface; use Courier\Processor\Handler\HandlerResultEnum; use Courier\Processor\Handler\InvokeHandlerInterface; @@ -19,16 +17,13 @@ class UpdateDependencyStatusHandler implements InvokeHandlerInterface { private DependencyRepositoryInterface $dependencyRepository; - private ProducerInterface $producer; private LoggerInterface $logger; public function __construct( DependencyRepositoryInterface $dependencyRepository, - ProducerInterface $producer, LoggerInterface $logger ) { $this->dependencyRepository = $dependencyRepository; - $this->producer = $producer; $this->logger = $logger; } @@ -69,9 +64,9 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han $packageName = $package->getName(); - // check for job duplication + // guard for job duplication $uniqueId = sprintf( - '%s%s', + '%s@%s', $packageName, $package->getLatestVersion() ); @@ -79,14 +74,16 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han if ( $command->forceExecution() === false && $lastUniqueId === $uniqueId && + $lastTimestamp > 0 && $timestamp - $lastTimestamp < 10 ) { $this->logger->debug( 'Update dependency status handler: Skipping duplicated job', [ 'package' => $packageName, + 'timestamp' => $timestamp, 'uniqueId' => $uniqueId, - 'lastTimestamp' => (new DateTimeImmutable)->setTimestamp($lastTimestamp)->format(DateTimeInterface::ATOM) + 'lastTimestamp' => (new DateTimeImmutable())->setTimestamp($lastTimestamp)->format(DateTimeInterface::ATOM) ] ); @@ -124,12 +121,7 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han DependencyStatusEnum::Outdated ); - if ($dependency->isDirty()) { - $dependency = $this->dependencyRepository->update($dependency); - $this->producer->sendEvent( - new DependencyUpdatedEvent($dependency) - ); - } + $dependency = $this->dependencyRepository->update($dependency); } // update deduplication guards @@ -141,7 +133,7 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han $this->logger->error( $exception->getMessage(), [ - 'package' => $packageName, + 'package' => $command->getPackage()->getName(), 'exception' => [ 'file' => $exception->getFile(), 'line' => $exception->getLine(), diff --git a/src/Application/Processor/Handler/UpdateVersionStatusHandler.php b/src/Application/Processor/Handler/UpdateVersionStatusHandler.php index 3c89d46e..438ad85f 100644 --- a/src/Application/Processor/Handler/UpdateVersionStatusHandler.php +++ b/src/Application/Processor/Handler/UpdateVersionStatusHandler.php @@ -4,13 +4,11 @@ namespace App\Application\Processor\Handler; use App\Application\Message\Command\UpdateVersionStatusCommand; -use App\Application\Message\Event\Version\VersionUpdatedEvent; use App\Domain\Dependency\Dependency; use App\Domain\Dependency\DependencyRepositoryInterface; use App\Domain\Dependency\DependencyStatusEnum; use App\Domain\Version\VersionRepositoryInterface; use App\Domain\Version\VersionStatusEnum; -use Courier\Client\Producer\ProducerInterface; use Courier\Message\CommandInterface; use Courier\Processor\Handler\HandlerResultEnum; use Courier\Processor\Handler\InvokeHandlerInterface; @@ -22,18 +20,15 @@ final class UpdateVersionStatusHandler implements InvokeHandlerInterface { private VersionRepositoryInterface $versionRepository; private DependencyRepositoryInterface $dependencyRepository; - private ProducerInterface $producer; private LoggerInterface $logger; public function __construct( VersionRepositoryInterface $versionRepository, DependencyRepositoryInterface $dependencyRepository, - ProducerInterface $producer, LoggerInterface $logger ) { $this->versionRepository = $versionRepository; $this->dependencyRepository = $dependencyRepository; - $this->producer = $producer; $this->logger = $logger; } @@ -74,9 +69,9 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han $dependencyName = $dependency->getName(); - // check for job duplication + // guard for job duplication $uniqueId = sprintf( - '%s%d', + '%s@%d', $dependencyName, $dependency->getVersionId() ); @@ -84,14 +79,16 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han if ( $command->forceExecution() === false && $lastUniqueId === $uniqueId && + $lastTimestamp > 0 && $timestamp - $lastTimestamp < 10 ) { $this->logger->debug( 'Update version status handler: Skipping duplicated job', [ 'dependency' => $dependencyName, + 'timestamp' => $timestamp, 'lastUniqueId' => $lastUniqueId, - 'lastTimestamp' => (new DateTimeImmutable)->setTimestamp($lastTimestamp)->format(DateTimeInterface::ATOM) + 'lastTimestamp' => (new DateTimeImmutable())->setTimestamp($lastTimestamp)->format(DateTimeInterface::ATOM) ] ); @@ -101,7 +98,10 @@ public function __invoke(CommandInterface $command, array $attributes = []): Han $this->logger->info( 'Update version status handler', - ['dependency' => $dependencyName] + [ + 'dependency' => $dependencyName, + 'versionId' => $dependency->getVersionId() + ] ); $version = $this->versionRepository->get($dependency->getVersionId()); @@ -130,13 +130,7 @@ static function (Dependency $dependency): DependencyStatusEnum { } ); - if ($version->isDirty()) { - $version = $this->versionRepository->update($version); - - $this->producer->sendEvent( - new VersionUpdatedEvent($version) - ); - } + $version = $this->versionRepository->update($version); // update deduplication guards $lastUniqueId = $uniqueId; @@ -147,7 +141,7 @@ static function (Dependency $dependency): DependencyStatusEnum { $this->logger->error( $exception->getMessage(), [ - 'dependency' => $dependencyName, + 'dependency' => $command->getDependency()->getName(), 'exception' => [ 'file' => $exception->getFile(), 'line' => $exception->getLine(), diff --git a/src/Application/Processor/Listener/Package/PackageCreatedListener.php b/src/Application/Processor/Listener/Package/PackageCreatedListener.php deleted file mode 100644 index 6cd081da..00000000 --- a/src/Application/Processor/Listener/Package/PackageCreatedListener.php +++ /dev/null @@ -1,33 +0,0 @@ -producer = $producer; - $this->logger = $logger; - } - - public function __invoke(EventInterface $event, array $attributes = []): void { - $package = $event->getPackage(); - $this->logger->debug( - 'Package created', - ['package' => $package->getName()] - ); - - $this->producer->sendCommand( - new PackageDiscoveryCommand($package) - ); - } -} diff --git a/src/Application/Processor/Listener/Package/PackageUpdatedListener.php b/src/Application/Processor/Listener/Package/PackageUpdatedListener.php index a8996ce1..fa0c72ea 100644 --- a/src/Application/Processor/Listener/Package/PackageUpdatedListener.php +++ b/src/Application/Processor/Listener/Package/PackageUpdatedListener.php @@ -18,7 +18,6 @@ public function __construct(ProducerInterface $producer, LoggerInterface $logger $this->logger = $logger; } - public function __invoke(EventInterface $event, array $attributes = []): void { $package = $event->getPackage(); $this->logger->debug( @@ -26,6 +25,7 @@ public function __invoke(EventInterface $event, array $attributes = []): void { ['package' => $package->getName()] ); + // ignore updates with empty latest version as they have no side effects if ($package->getLatestVersion() === '') { return; } diff --git a/src/Application/Processor/Listener/Version/VersionCreatedListener.php b/src/Application/Processor/Listener/Version/VersionCreatedListener.php index 292b4d68..af38a5b0 100644 --- a/src/Application/Processor/Listener/Version/VersionCreatedListener.php +++ b/src/Application/Processor/Listener/Version/VersionCreatedListener.php @@ -3,11 +3,9 @@ namespace App\Application\Processor\Listener\Version; -use App\Application\Message\Event\Package\PackageUpdatedEvent; use App\Domain\Package\PackageRepositoryInterface; use Composer\Semver\Comparator; use Composer\Semver\VersionParser; -use Courier\Client\Producer\ProducerInterface; use Courier\Message\EventInterface; use Courier\Processor\Listener\InvokeListenerInterface; use Psr\Log\LoggerInterface; @@ -15,18 +13,15 @@ class VersionCreatedListener implements InvokeListenerInterface { private PackageRepositoryInterface $packageRepository; private VersionParser $versionParser; - private ProducerInterface $producer; private LoggerInterface $logger; public function __construct( PackageRepositoryInterface $packageRepository, VersionParser $versionParser, - ProducerInterface $producer, LoggerInterface $logger ) { $this->packageRepository = $packageRepository; $this->versionParser = $versionParser; - $this->producer = $producer; $this->logger = $logger; } @@ -63,10 +58,6 @@ public function __invoke(EventInterface $event, array $attributes = []): void { if (Comparator::greaterThan($version->getNormalized(), $latestVersionNormalized)) { $package = $package->withLatestVersion($version->getNumber()); $package = $this->packageRepository->update($package); - - $this->producer->sendEvent( - new PackageUpdatedEvent($package) - ); } } } diff --git a/src/Domain/Dependency/Dependency.php b/src/Domain/Dependency/Dependency.php index 0790cf42..a0bd7dc5 100644 --- a/src/Domain/Dependency/Dependency.php +++ b/src/Domain/Dependency/Dependency.php @@ -146,7 +146,7 @@ public function jsonSerialize(): array { 'name' => $this->name, 'constraint' => $this->constraint, 'development' => $this->development, - 'status' => $this->status->value, + 'status' => $this->status, 'createdAt' => $this->createdAt, 'updatedAt' => $this->updatedAt ]; diff --git a/src/Infrastructure/Persistence/Dependency/PdoDependencyRepository.php b/src/Infrastructure/Persistence/Dependency/PdoDependencyRepository.php index 03da4e91..9c861533 100644 --- a/src/Infrastructure/Persistence/Dependency/PdoDependencyRepository.php +++ b/src/Infrastructure/Persistence/Dependency/PdoDependencyRepository.php @@ -3,17 +3,21 @@ namespace App\Infrastructure\Persistence\Dependency; +use App\Application\Message\Event\Dependency\DependencyCreatedEvent; +use App\Application\Message\Event\Dependency\DependencyUpdatedEvent; use App\Domain\Dependency\Dependency; use App\Domain\Dependency\DependencyCollection; use App\Domain\Dependency\DependencyNotFoundException; use App\Domain\Dependency\DependencyRepositoryInterface; use App\Domain\Dependency\DependencyStatusEnum; +use Courier\Client\Producer\ProducerInterface; use DateTimeImmutable; use DateTimeInterface; use PDO; final class PdoDependencyRepository implements DependencyRepositoryInterface { private PDO $pdo; + private ProducerInterface $producer; /** * @param array{ @@ -40,8 +44,9 @@ private function hydrate(array $data): Dependency { ); } - public function __construct(PDO $pdo) { - $this->pdo = $pdo; + public function __construct(PDO $pdo, ProducerInterface $producer) { + $this->pdo = $pdo; + $this->producer = $producer; } public function create( @@ -170,7 +175,7 @@ public function save(Dependency $dependency): Dependency { ] ); - return new Dependency( + $dependency = new Dependency( (int)$this->pdo->lastInsertId('dependencies_id_seq'), $dependency->getVersionId(), $dependency->getName(), @@ -179,6 +184,12 @@ public function save(Dependency $dependency): Dependency { $dependency->getStatus(), $dependency->getCreatedAt() ); + + $this->producer->sendEvent( + new DependencyCreatedEvent($dependency) + ); + + return $dependency; } public function update(Dependency $dependency): Dependency { @@ -208,7 +219,13 @@ public function update(Dependency $dependency): Dependency { ] ); - return $this->get($dependency->getId()); + $dependency = $this->get($dependency->getId()); + + $this->producer->sendEvent( + new DependencyUpdatedEvent($dependency) + ); + + return $dependency; } return $dependency; diff --git a/src/Infrastructure/Persistence/Package/PdoPackageRepository.php b/src/Infrastructure/Persistence/Package/PdoPackageRepository.php index 36b388bf..3b567860 100644 --- a/src/Infrastructure/Persistence/Package/PdoPackageRepository.php +++ b/src/Infrastructure/Persistence/Package/PdoPackageRepository.php @@ -3,16 +3,20 @@ namespace App\Infrastructure\Persistence\Package; +use App\Application\Message\Event\Package\PackageCreatedEvent; +use App\Application\Message\Event\Package\PackageUpdatedEvent; use App\Domain\Package\Package; use App\Domain\Package\PackageCollection; use App\Domain\Package\PackageNotFoundException; use App\Domain\Package\PackageRepositoryInterface; +use Courier\Client\Producer\ProducerInterface; use DateTimeImmutable; use DateTimeInterface; use PDO; final class PdoPackageRepository implements PackageRepositoryInterface { private PDO $pdo; + private ProducerInterface $producer; /** * @param array{ @@ -35,8 +39,9 @@ private function hydrate(array $data): Package { ); } - public function __construct(PDO $pdo) { - $this->pdo = $pdo; + public function __construct(PDO $pdo, ProducerInterface $producer) { + $this->pdo = $pdo; + $this->producer = $producer; } public function create( @@ -224,6 +229,10 @@ public function save(Package $package): Package { ] ); + $this->producer->sendEvent( + new PackageCreatedEvent($package) + ); + return $package; } @@ -254,7 +263,13 @@ public function update(Package $package): Package { ] ); - return $this->get($package->getName()); + $package = $this->get($package->getName()); + + $this->producer->sendEvent( + new PackageUpdatedEvent($package) + ); + + return $package; } return $package; diff --git a/src/Infrastructure/Persistence/Preference/PdoPreferenceRepository.php b/src/Infrastructure/Persistence/Preference/PdoPreferenceRepository.php index f49be4cc..b69f3214 100644 --- a/src/Infrastructure/Persistence/Preference/PdoPreferenceRepository.php +++ b/src/Infrastructure/Persistence/Preference/PdoPreferenceRepository.php @@ -3,17 +3,21 @@ namespace App\Infrastructure\Persistence\Preference; +use App\Application\Message\Event\Preference\PreferenceCreatedEvent; +use App\Application\Message\Event\Preference\PreferenceUpdatedEvent; use App\Domain\Preference\Preference; use App\Domain\Preference\PreferenceCollection; use App\Domain\Preference\PreferenceNotFoundException; use App\Domain\Preference\PreferenceRepositoryInterface; use App\Domain\Preference\PreferenceTypeEnum; +use Courier\Client\Producer\ProducerInterface; use DateTimeImmutable; use DateTimeInterface; use PDO; final class PdoPreferenceRepository implements PreferenceRepositoryInterface { private PDO $pdo; + private ProducerInterface $producer; /** * @param array{ @@ -38,8 +42,9 @@ private function hydrate(array $data): Preference { ); } - public function __construct(PDO $pdo) { - $this->pdo = $pdo; + public function __construct(PDO $pdo, ProducerInterface $producer) { + $this->pdo = $pdo; + $this->producer = $producer; } public function create( @@ -153,7 +158,7 @@ public function save(Preference $preference): Preference { ] ); - return new Preference( + $preference = new Preference( (int)$this->pdo->lastInsertId('preferences_id_seq'), $preference->getCategory(), $preference->getProperty(), @@ -161,6 +166,12 @@ public function save(Preference $preference): Preference { $preference->getType()->value, $preference->getCreatedAt() ); + + $this->producer->sendEvent( + new PreferenceCreatedEvent($preference) + ); + + return $preference; } public function update(Preference $preference): Preference { @@ -192,7 +203,13 @@ public function update(Preference $preference): Preference { ] ); - return $this->get($preference->getId()); + $preference = $this->get($preference->getId()); + + $this->producer->sendEvent( + new PreferenceUpdatedEvent($preference) + ); + + return $preference; } return $preference; diff --git a/src/Infrastructure/Persistence/Stats/PdoStatsRepository.php b/src/Infrastructure/Persistence/Stats/PdoStatsRepository.php index f8f641c7..84b446a4 100644 --- a/src/Infrastructure/Persistence/Stats/PdoStatsRepository.php +++ b/src/Infrastructure/Persistence/Stats/PdoStatsRepository.php @@ -3,16 +3,20 @@ namespace App\Infrastructure\Persistence\Stats; +use App\Application\Message\Event\Stats\StatsCreatedEvent; +use App\Application\Message\Event\Stats\StatsUpdatedEvent; use App\Domain\Stats\Stats; use App\Domain\Stats\StatsCollection; use App\Domain\Stats\StatsNotFoundException; use App\Domain\Stats\StatsRepositoryInterface; +use Courier\Client\Producer\ProducerInterface; use DateTimeImmutable; use DateTimeInterface; use PDO; final class PdoStatsRepository implements StatsRepositoryInterface { private PDO $pdo; + private ProducerInterface $producer; /** * @param array{ @@ -47,8 +51,9 @@ private function hydrate(array $data): Stats { ); } - public function __construct(PDO $pdo) { - $this->pdo = $pdo; + public function __construct(PDO $pdo, ProducerInterface $producer) { + $this->pdo = $pdo; + $this->producer = $producer; } public function create( @@ -220,6 +225,10 @@ public function save(Stats $stats): Stats { ] ); + $this->producer->sendEvent( + new StatsCreatedEvent($stats) + ); + return $stats; } @@ -262,7 +271,13 @@ public function update(Stats $stats): Stats { ] ); - return $this->get($stats->getPackageName()); + $stats = $this->get($stats->getPackageName()); + + $this->producer->sendEvent( + new StatsUpdatedEvent($stats) + ); + + return $stats; } return $stats; diff --git a/src/Infrastructure/Persistence/Version/PdoVersionRepository.php b/src/Infrastructure/Persistence/Version/PdoVersionRepository.php index eb570a8b..f030e3e2 100644 --- a/src/Infrastructure/Persistence/Version/PdoVersionRepository.php +++ b/src/Infrastructure/Persistence/Version/PdoVersionRepository.php @@ -3,17 +3,21 @@ namespace App\Infrastructure\Persistence\Version; +use App\Application\Message\Event\Version\VersionCreatedEvent; +use App\Application\Message\Event\Version\VersionUpdatedEvent; use App\Domain\Version\Version; use App\Domain\Version\VersionCollection; use App\Domain\Version\VersionNotFoundException; use App\Domain\Version\VersionRepositoryInterface; use App\Domain\Version\VersionStatusEnum; +use Courier\Client\Producer\ProducerInterface; use DateTimeImmutable; use DateTimeInterface; use PDO; final class PdoVersionRepository implements VersionRepositoryInterface { private PDO $pdo; + private ProducerInterface $producer; /** * @param array{ @@ -40,8 +44,9 @@ private function hydrate(array $data): Version { ); } - public function __construct(PDO $pdo) { - $this->pdo = $pdo; + public function __construct(PDO $pdo, ProducerInterface $producer) { + $this->pdo = $pdo; + $this->producer = $producer; } public function create( @@ -169,7 +174,7 @@ public function save(Version $version): Version { ] ); - return new Version( + $version = new Version( (int)$this->pdo->lastInsertId('versions_id_seq'), $version->getNumber(), $version->getNormalized(), @@ -178,6 +183,12 @@ public function save(Version $version): Version { $version->getStatus(), $version->getCreatedAt() ); + + $this->producer->sendEvent( + new VersionCreatedEvent($version) + ); + + return $version; } public function update(Version $version): Version { @@ -211,7 +222,13 @@ public function update(Version $version): Version { ] ); - return $this->get($version->getId()); + $version = $this->get($version->getId()); + + $this->producer->sendEvent( + new VersionUpdatedEvent($version) + ); + + return $version; } return $version;