Skip to content

Commit 57c6588

Browse files
committed
Journal for used generated containers
1 parent 6628bcd commit 57c6588

File tree

4 files changed

+124
-44
lines changed

4 files changed

+124
-44
lines changed

src/Command/CommandHelper.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ public static function begin(
213213

214214
$analysedPathsFromConfig = [];
215215
$containerFactory = new ContainerFactory($currentWorkingDirectory);
216+
if ($cleanupContainerCache) {
217+
$containerFactory->setJournalContainer();
218+
}
216219
$projectConfig = null;
217220
if ($projectConfigFile !== null) {
218221
if (!is_file($projectConfigFile)) {
@@ -434,7 +437,6 @@ public static function begin(
434437
}
435438

436439
if ($cleanupContainerCache) {
437-
$containerFactory->clearOldContainers($tmpDir);
438440
$cacheStorage = $container->getService('cacheStorage');
439441
if ($cacheStorage instanceof FileCacheStorage) {
440442
$cacheStorage->clearUnusedFiles();

src/DependencyInjection/Configurator.php

+112-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,31 @@
22

33
namespace PHPStan\DependencyInjection;
44

5+
use DirectoryIterator;
56
use Nette\DI\Config\Loader;
67
use Nette\DI\Container as OriginalNetteContainer;
78
use Nette\DI\ContainerLoader;
89
use PHPStan\File\CouldNotReadFileException;
10+
use PHPStan\File\CouldNotWriteFileException;
11+
use PHPStan\File\FileReader;
12+
use PHPStan\File\FileWriter;
913
use function array_keys;
14+
use function count;
1015
use function error_reporting;
16+
use function explode;
17+
use function implode;
18+
use function in_array;
19+
use function is_dir;
20+
use function is_file;
1121
use function restore_error_handler;
1222
use function set_error_handler;
1323
use function sha1_file;
24+
use function sprintf;
25+
use function str_ends_with;
26+
use function substr;
27+
use function time;
28+
use function trim;
29+
use function unlink;
1430
use const E_USER_DEPRECATED;
1531
use const PHP_RELEASE_VERSION;
1632
use const PHP_VERSION_ID;
@@ -21,7 +37,7 @@ final class Configurator extends \Nette\Bootstrap\Configurator
2137
/** @var string[] */
2238
private array $allConfigFiles = [];
2339

24-
public function __construct(private LoaderFactory $loaderFactory)
40+
public function __construct(private LoaderFactory $loaderFactory, private bool $journalContainer)
2541
{
2642
parent::__construct();
2743
}
@@ -59,10 +75,104 @@ public function loadContainer(): string
5975
$this->staticParameters['debugMode'],
6076
);
6177

62-
return $loader->load(
78+
$className = $loader->load(
6379
[$this, 'generateContainer'],
6480
[$this->staticParameters, array_keys($this->dynamicParameters), $this->configs, PHP_VERSION_ID - PHP_RELEASE_VERSION, NeonAdapter::CACHE_KEY, $this->getAllConfigFilesHashes()],
6581
);
82+
83+
if ($this->journalContainer) {
84+
$this->journal($className);
85+
}
86+
87+
return $className;
88+
}
89+
90+
private function journal(string $currentContainerClassName): void
91+
{
92+
$directory = $this->getContainerCacheDirectory();
93+
if (!is_dir($directory)) {
94+
return;
95+
}
96+
97+
$journalFile = $directory . '/container.journal';
98+
if (!is_file($journalFile)) {
99+
try {
100+
FileWriter::write($journalFile, sprintf("%s:%d\n", $currentContainerClassName, time()));
101+
} catch (CouldNotWriteFileException) {
102+
// pass
103+
}
104+
105+
return;
106+
}
107+
108+
try {
109+
$journalContents = FileReader::read($journalFile);
110+
} catch (CouldNotReadFileException) {
111+
return;
112+
}
113+
114+
$journalLines = explode("\n", trim($journalContents));
115+
$linesToWrite = [];
116+
$usedInTheLastWeek = [];
117+
$now = time();
118+
$currentAlreadyInTheJournal = false;
119+
foreach ($journalLines as $journalLine) {
120+
if ($journalLine === '') {
121+
continue;
122+
}
123+
$journalLineParts = explode(':', $journalLine);
124+
if (count($journalLineParts) !== 2) {
125+
return;
126+
}
127+
$className = $journalLineParts[0];
128+
$containerLastUsedTime = (int) $journalLineParts[1];
129+
130+
$week = 3600 * 24 * 7;
131+
132+
if ($containerLastUsedTime + $week >= $now) {
133+
$usedInTheLastWeek[] = $className;
134+
}
135+
136+
if ($currentContainerClassName !== $className) {
137+
$linesToWrite[] = sprintf('%s:%d', $className, $containerLastUsedTime);
138+
continue;
139+
}
140+
141+
$linesToWrite[] = sprintf('%s:%d', $currentContainerClassName, $now);
142+
$currentAlreadyInTheJournal = true;
143+
}
144+
145+
if (!$currentAlreadyInTheJournal) {
146+
$linesToWrite[] = sprintf('%s:%d', $currentContainerClassName, $now);
147+
$usedInTheLastWeek[] = $currentContainerClassName;
148+
}
149+
150+
try {
151+
FileWriter::write($journalFile, implode("\n", $linesToWrite) . "\n");
152+
} catch (CouldNotWriteFileException) {
153+
return;
154+
}
155+
156+
foreach (new DirectoryIterator($directory) as $fileInfo) {
157+
if ($fileInfo->isDot()) {
158+
continue;
159+
}
160+
$fileName = $fileInfo->getFilename();
161+
if ($fileName === 'container.journal') {
162+
continue;
163+
}
164+
if (!str_ends_with($fileName, '.php')) {
165+
continue;
166+
}
167+
$fileClassName = substr($fileName, 0, -4);
168+
if (in_array($fileClassName, $usedInTheLastWeek, true)) {
169+
continue;
170+
}
171+
$basePathname = $fileInfo->getPathname();
172+
@unlink($basePathname);
173+
@unlink($basePathname . '.lock');
174+
@unlink($basePathname . '.meta');
175+
}
66176
}
67177

68178
public function createContainer(bool $initialize = true): OriginalNetteContainer

src/DependencyInjection/ContainerFactory.php

+8-41
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
use PHPStan\Reflection\ReflectionProviderStaticAccessor;
3232
use PHPStan\ShouldNotHappenException;
3333
use PHPStan\Type\ObjectType;
34-
use Symfony\Component\Finder\Finder;
3534
use function array_diff_key;
3635
use function array_map;
3736
use function array_merge;
@@ -42,15 +41,12 @@
4241
use function getenv;
4342
use function ini_get;
4443
use function is_array;
45-
use function is_dir;
4644
use function is_file;
4745
use function is_readable;
4846
use function spl_object_id;
4947
use function sprintf;
5048
use function str_ends_with;
5149
use function substr;
52-
use function time;
53-
use function unlink;
5450

5551
/**
5652
* @api
@@ -66,6 +62,8 @@ final class ContainerFactory
6662

6763
private static ?int $lastInitializedContainerId = null;
6864

65+
private bool $journalContainer = false;
66+
6967
/** @api */
7068
public function __construct(private string $currentWorkingDirectory)
7169
{
@@ -83,6 +81,11 @@ public function __construct(private string $currentWorkingDirectory)
8381
$this->configDirectory = $originalRootDir . '/conf';
8482
}
8583

84+
public function setJournalContainer(): void
85+
{
86+
$this->journalContainer = true;
87+
}
88+
8689
/**
8790
* @param string[] $additionalConfigFiles
8891
* @param string[] $analysedPaths
@@ -114,7 +117,7 @@ public function create(
114117
$this->rootDirectory,
115118
$this->currentWorkingDirectory,
116119
$generateBaselineFile,
117-
));
120+
), $this->journalContainer);
118121
$configurator->defaultExtensions = [
119122
'php' => PhpExtension::class,
120123
'extensions' => ExtensionsExtension::class,
@@ -188,42 +191,6 @@ public static function postInitializeContainer(Container $container): void
188191
BleedingEdgeToggle::setBleedingEdge($container->getParameter('featureToggles')['bleedingEdge']);
189192
}
190193

191-
public function clearOldContainers(string $tempDirectory): void
192-
{
193-
$configurator = new Configurator(new LoaderFactory(
194-
$this->fileHelper,
195-
$this->rootDirectory,
196-
$this->currentWorkingDirectory,
197-
null,
198-
));
199-
$configurator->setDebugMode(true);
200-
$configurator->setTempDirectory($tempDirectory);
201-
202-
$containerDirectory = $configurator->getContainerCacheDirectory();
203-
if (!is_dir($containerDirectory)) {
204-
return;
205-
}
206-
207-
$finder = new Finder();
208-
$finder->name('Container_*')->in($containerDirectory);
209-
$twoDaysAgo = time() - 24 * 60 * 60 * 2;
210-
211-
foreach ($finder as $containerFile) {
212-
$path = $containerFile->getRealPath();
213-
if ($path === false) {
214-
continue;
215-
}
216-
if ($containerFile->getATime() > $twoDaysAgo) {
217-
continue;
218-
}
219-
if ($containerFile->getCTime() > $twoDaysAgo) {
220-
continue;
221-
}
222-
223-
@unlink($path);
224-
}
225-
}
226-
227194
public function getCurrentWorkingDirectory(): string
228195
{
229196
return $this->currentWorkingDirectory;

src/DependencyInjection/DerivativeContainerFactory.php

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public function create(array $additionalConfigFiles): Container
3535
$containerFactory = new ContainerFactory(
3636
$this->currentWorkingDirectory,
3737
);
38+
$containerFactory->setJournalContainer();
3839

3940
return $containerFactory->create(
4041
$this->tempDirectory,

0 commit comments

Comments
 (0)