Skip to content

Commit

Permalink
Journal for used generated containers
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 8, 2024
1 parent 6628bcd commit 57c6588
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 44 deletions.
4 changes: 3 additions & 1 deletion src/Command/CommandHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ public static function begin(

$analysedPathsFromConfig = [];
$containerFactory = new ContainerFactory($currentWorkingDirectory);
if ($cleanupContainerCache) {
$containerFactory->setJournalContainer();
}
$projectConfig = null;
if ($projectConfigFile !== null) {
if (!is_file($projectConfigFile)) {
Expand Down Expand Up @@ -434,7 +437,6 @@ public static function begin(
}

if ($cleanupContainerCache) {
$containerFactory->clearOldContainers($tmpDir);
$cacheStorage = $container->getService('cacheStorage');
if ($cacheStorage instanceof FileCacheStorage) {
$cacheStorage->clearUnusedFiles();
Expand Down
114 changes: 112 additions & 2 deletions src/DependencyInjection/Configurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,31 @@

namespace PHPStan\DependencyInjection;

use DirectoryIterator;
use Nette\DI\Config\Loader;
use Nette\DI\Container as OriginalNetteContainer;
use Nette\DI\ContainerLoader;
use PHPStan\File\CouldNotReadFileException;
use PHPStan\File\CouldNotWriteFileException;
use PHPStan\File\FileReader;
use PHPStan\File\FileWriter;
use function array_keys;
use function count;
use function error_reporting;
use function explode;
use function implode;
use function in_array;
use function is_dir;
use function is_file;
use function restore_error_handler;
use function set_error_handler;
use function sha1_file;
use function sprintf;
use function str_ends_with;
use function substr;
use function time;
use function trim;
use function unlink;
use const E_USER_DEPRECATED;
use const PHP_RELEASE_VERSION;
use const PHP_VERSION_ID;
Expand All @@ -21,7 +37,7 @@ final class Configurator extends \Nette\Bootstrap\Configurator
/** @var string[] */
private array $allConfigFiles = [];

public function __construct(private LoaderFactory $loaderFactory)
public function __construct(private LoaderFactory $loaderFactory, private bool $journalContainer)
{
parent::__construct();
}
Expand Down Expand Up @@ -59,10 +75,104 @@ public function loadContainer(): string
$this->staticParameters['debugMode'],
);

return $loader->load(
$className = $loader->load(
[$this, 'generateContainer'],
[$this->staticParameters, array_keys($this->dynamicParameters), $this->configs, PHP_VERSION_ID - PHP_RELEASE_VERSION, NeonAdapter::CACHE_KEY, $this->getAllConfigFilesHashes()],
);

if ($this->journalContainer) {
$this->journal($className);
}

return $className;
}

private function journal(string $currentContainerClassName): void
{
$directory = $this->getContainerCacheDirectory();
if (!is_dir($directory)) {
return;
}

$journalFile = $directory . '/container.journal';
if (!is_file($journalFile)) {
try {
FileWriter::write($journalFile, sprintf("%s:%d\n", $currentContainerClassName, time()));
} catch (CouldNotWriteFileException) {
// pass
}

return;
}

try {
$journalContents = FileReader::read($journalFile);
} catch (CouldNotReadFileException) {
return;
}

$journalLines = explode("\n", trim($journalContents));
$linesToWrite = [];
$usedInTheLastWeek = [];
$now = time();
$currentAlreadyInTheJournal = false;
foreach ($journalLines as $journalLine) {
if ($journalLine === '') {
continue;
}
$journalLineParts = explode(':', $journalLine);
if (count($journalLineParts) !== 2) {
return;
}
$className = $journalLineParts[0];
$containerLastUsedTime = (int) $journalLineParts[1];

$week = 3600 * 24 * 7;

if ($containerLastUsedTime + $week >= $now) {
$usedInTheLastWeek[] = $className;
}

if ($currentContainerClassName !== $className) {
$linesToWrite[] = sprintf('%s:%d', $className, $containerLastUsedTime);
continue;
}

$linesToWrite[] = sprintf('%s:%d', $currentContainerClassName, $now);
$currentAlreadyInTheJournal = true;
}

if (!$currentAlreadyInTheJournal) {
$linesToWrite[] = sprintf('%s:%d', $currentContainerClassName, $now);
$usedInTheLastWeek[] = $currentContainerClassName;
}

try {
FileWriter::write($journalFile, implode("\n", $linesToWrite) . "\n");
} catch (CouldNotWriteFileException) {
return;
}

foreach (new DirectoryIterator($directory) as $fileInfo) {
if ($fileInfo->isDot()) {
continue;
}
$fileName = $fileInfo->getFilename();
if ($fileName === 'container.journal') {
continue;
}
if (!str_ends_with($fileName, '.php')) {
continue;
}
$fileClassName = substr($fileName, 0, -4);
if (in_array($fileClassName, $usedInTheLastWeek, true)) {
continue;
}
$basePathname = $fileInfo->getPathname();
@unlink($basePathname);
@unlink($basePathname . '.lock');
@unlink($basePathname . '.meta');
}
}

public function createContainer(bool $initialize = true): OriginalNetteContainer
Expand Down
49 changes: 8 additions & 41 deletions src/DependencyInjection/ContainerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
use PHPStan\Reflection\ReflectionProviderStaticAccessor;
use PHPStan\ShouldNotHappenException;
use PHPStan\Type\ObjectType;
use Symfony\Component\Finder\Finder;
use function array_diff_key;
use function array_map;
use function array_merge;
Expand All @@ -42,15 +41,12 @@
use function getenv;
use function ini_get;
use function is_array;
use function is_dir;
use function is_file;
use function is_readable;
use function spl_object_id;
use function sprintf;
use function str_ends_with;
use function substr;
use function time;
use function unlink;

/**
* @api
Expand All @@ -66,6 +62,8 @@ final class ContainerFactory

private static ?int $lastInitializedContainerId = null;

private bool $journalContainer = false;

/** @api */
public function __construct(private string $currentWorkingDirectory)
{
Expand All @@ -83,6 +81,11 @@ public function __construct(private string $currentWorkingDirectory)
$this->configDirectory = $originalRootDir . '/conf';
}

public function setJournalContainer(): void
{
$this->journalContainer = true;
}

/**
* @param string[] $additionalConfigFiles
* @param string[] $analysedPaths
Expand Down Expand Up @@ -114,7 +117,7 @@ public function create(
$this->rootDirectory,
$this->currentWorkingDirectory,
$generateBaselineFile,
));
), $this->journalContainer);
$configurator->defaultExtensions = [
'php' => PhpExtension::class,
'extensions' => ExtensionsExtension::class,
Expand Down Expand Up @@ -188,42 +191,6 @@ public static function postInitializeContainer(Container $container): void
BleedingEdgeToggle::setBleedingEdge($container->getParameter('featureToggles')['bleedingEdge']);
}

public function clearOldContainers(string $tempDirectory): void
{
$configurator = new Configurator(new LoaderFactory(
$this->fileHelper,
$this->rootDirectory,
$this->currentWorkingDirectory,
null,
));
$configurator->setDebugMode(true);
$configurator->setTempDirectory($tempDirectory);

$containerDirectory = $configurator->getContainerCacheDirectory();
if (!is_dir($containerDirectory)) {
return;
}

$finder = new Finder();
$finder->name('Container_*')->in($containerDirectory);
$twoDaysAgo = time() - 24 * 60 * 60 * 2;

foreach ($finder as $containerFile) {
$path = $containerFile->getRealPath();
if ($path === false) {
continue;
}
if ($containerFile->getATime() > $twoDaysAgo) {
continue;
}
if ($containerFile->getCTime() > $twoDaysAgo) {
continue;
}

@unlink($path);
}
}

public function getCurrentWorkingDirectory(): string
{
return $this->currentWorkingDirectory;
Expand Down
1 change: 1 addition & 0 deletions src/DependencyInjection/DerivativeContainerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public function create(array $additionalConfigFiles): Container
$containerFactory = new ContainerFactory(
$this->currentWorkingDirectory,
);
$containerFactory->setJournalContainer();

return $containerFactory->create(
$this->tempDirectory,
Expand Down

0 comments on commit 57c6588

Please sign in to comment.