8000 [HttpKernel] Introduce `BuildWarmerInterface` and `WarmableAggregate`… · symfony/symfony@26d4e11 · GitHub
[go: up one dir, main page]

Skip to content

Commit 26d4e11

Browse files
committed
[HttpKernel] Introduce BuildWarmerInterface and WarmableAggregate to build read-only artifacts in build_dir during Kernel compilation
1 parent 2979e1e commit 26d4e11

File tree

5 files changed

+155
-78
lines changed

5 files changed

+155
-78
lines changed

src/Symfony/Component/HttpKernel/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
6.3
55
---
66

7+
* Introduce `BuildWarmerInterface` and `WarmableAggregate` to build read-only artifacts in `build_dir` during Kernel compilation
78
* Deprecate parameters `container.dumper.inline_factories` and `container.dumper.inline_class_loader`, use `.container.dumper.inline_factories` and `.container.dumper.inline_class_loader` instead
89
* `FileProfilerStorage` removes profiles automatically after two days
910
* Add `#[WithHttpStatus]` for defining status codes for exceptions
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\CacheWarmer;
13+
14+
/**
15+
* Interface for classes that support warming their cache, if the cache is read-only.
16+
*
17+
* @author Quentin Devos <quentin@devos.pm>
18+
*/
19+
interface BuildWarmerInterface extends WarmableInterface
20+
{
21+
22+
}

src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php

Lines changed: 14 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,15 @@
1111

1212
namespace Symfony\Component\HttpKernel\CacheWarmer;
1313

14-
use Symfony\Component\Console\Style\SymfonyStyle;
15-
1614
/**
1715
* Aggregates several cache warmers into a single one.
1816
*
1917
* @author Fabien Potencier <fabien@symfony.com>
2018
*
2119
* @final
2220
*/
23-
class CacheWarmerAggregate implements CacheWarmerInterface
21+
class CacheWarmerAggregate extends WarmableAggregate implements CacheWarmerInterface
2422
{
25-
private iterable $warmers;
26-
private bool $debug;
27-
private ?string $deprecationLogsFilepath;
2823
private bool $optionalsEnabled = false;
2924
private bool $onlyOptionalsEnabled = false;
3025

@@ -33,9 +28,7 @@ class CacheWarmerAggregate implements CacheWarmerInterface
3328
*/
3429
public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null)
3530
{
36-
$this->warmers = $warmers;
37-
$this->debug = $debug;
38-
$this->deprecationLogsFilepath = $deprecationLogsFilepath;
31+
parent::__construct($warmers, $debug, $deprecationLogsFilepath);
3932
}
4033

4134
public function enableOptionalWarmers(): void
@@ -48,85 +41,28 @@ public function enableOnlyOptionalWarmers(): void
4841
$this->onlyOptionalsEnabled = $this->optionalsEnabled = true;
4942
}
5043

51-
public function warmUp(string $cacheDir, SymfonyStyle $io = null): array
44+
public function isOptional(): bool
5245
{
53-
if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) {
54-
$collectedLogs = [];
55-
$previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
56-
if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) {
57-
return $previousHandler ? $previousHandler($type, $message, $file, $line) : false;
58-
}
59-
60-
if (isset($collectedLogs[$message])) {
61-
++$collectedLogs[$message]['count'];
62-
63-
return null;
64-
}
65-
66-
$backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3);
67-
// Clean the trace by removing first frames added by the error handler itself.
68-
for ($i = 0; isset($backtrace[$i]); ++$i) {
69-
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
70-
$backtrace = \array_slice($backtrace, 1 + $i);
71-
break;
72-
}
73-
}
74-
75-
$collectedLogs[$message] = [
76-
'type' => $type,
77-
'message' => $message,
78-
'file' => $file,
79-
'line' => $line,
80-
'trace' => $backtrace,
81-
'count' => 1,
82-
];
83-
84-
return null;
85-
});
86-
}
46+
return false;
47+
}
8748

88-
$preload = [];
89-
try {
90-
foreach ($this->warmers as $warmer) {
49+
/**
50+
* @return iterable<mixed, CacheWarmerInterface>
51+
*/
52+
protected function getWarmers(): iterable
53+
{
54+
foreach (parent::getWarmers() as $warmer)
55+
{
56+
if ($warmer instanceof CacheWarmerInterface) {
9157
if (!$this->optionalsEnabled && $warmer->isOptional()) {
9258
continue;
9359
}
9460
if ($this->onlyOptionalsEnabled && !$warmer->isOptional()) {
9561
continue;
9662
}
9763

98-
$start = microtime(true);
99-
foreach ((array) $warmer->warmUp($cacheDir) as $item) {
100-
if (is_dir($item) || (str_starts_with($item, \dirname($cacheDir)) && !is_file($item))) {
101-
throw new \LogicException(sprintf('"%s::warmUp()" should return a list of files or classes but "%s" is none of them.', $warmer::class, $item));
102-
}
103-
$preload[] = $item;
104-
}
105-
106-
if ($io?->isDebug()) {
107-
$io->info(sprintf('"%s" completed in %0.2fms.', $warmer::class, 1000 * (microtime(true) - $start)));
108-
}
109-
}
110-
} finally {
111-
if ($collectDeprecations) {
112-
restore_error_handler();
113-
114-
if (is_file($this->deprecationLogsFilepath)) {
115-
$previousLogs = unserialize(file_get_contents($this->deprecationLogsFilepath));
116-
if (\is_array($previousLogs)) {
117-
$collectedLogs = array_merge($previousLogs, $collectedLogs);
118-
}
119-
}
120-
121-
file_put_contents($this->deprecationLogsFilepath, serialize(array_values($collectedLogs)));
64+
yield $warmer;
12265
}
12366
}
124-
125-
return array_values(array_unique($preload));
126-
}
127-
128-
public function isOptional(): bool
129-
{
130-
return false;
13167
}
13268
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\CacheWarmer;
13+
14+
use Symfony\Component\Console\Style\SymfonyStyle;
15+
16+
/**
17+
* Aggregates several cache warmers into a single one.
18+
*
19+
* @author Fabien Potencier <fabien@symfony.com>
20+
*/
21+
class WarmableAggregate implements WarmableInterface
22+
{
23+
private iterable $warmers;
24+
private bool $debug;
25+
private ?string $deprecationLogsFilepath;
26+
27+
/**
28+
* @param iterable<mixed, WarmableInterface> $warmers
29+
*/
30+
public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null)
31+
{
32+
$this->warmers = $warmers;
33+
$this->debug = $debug;
34+
$this->deprecationLogsFilepath = $deprecationLogsFilepath;
35+
}
36+
37+
public function warmUp(string $cacheDir, SymfonyStyle $io = null): array
38+
{
39+
if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) {
40+
$collectedLogs = [];
41+
$previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
42+
if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) {
43+
return $previousHandler ? $previousHandler($type, $message, $file, $line) : false;
44+
}
45+
46+
if (isset($collectedLogs[$message])) {
47+
++$collectedLogs[$message]['count'];
48+
49+
return null;
50+
}
51+
52+
$backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3);
53+
// Clean the trace by removing first frames added by the error handler itself.
54+
for ($i = 0; isset($backtrace[$i]); ++$i) {
55+
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
56+
$backtrace = \array_slice($backtrace, 1 + $i);
57+
break;
58+
}
59+
}
60+
61+
$collectedLogs[$message] = [
62+
'type' => $type,
63+
'message' => $message,
64+
'file' => $file,
65+
'line' => $line,
66+
'trace' => $backtrace,
67+
'count' => 1,
68+
];
69+
70+
return null;
71+
});
72+
}
73+
74+
$preload = [];
75+
try {
76+
foreach ($this->getWarmers() as $warmer) {
77+
$start = microtime(true);
78+
foreach ((array) $warmer->warmUp($cacheDir) as $item) {
79+
if (is_dir($item) || (str_starts_with($item, \dirname($cacheDir)) && !is_file($item))) {
80+
throw new \LogicException(sprintf('"%s::warmUp()" should return a list of files or classes but "%s" is none of them.', $warmer::class, $item));
81+
}
82+
$preload[] = $item;
83+
}
84+
85+
if ($io?->isDebug()) {
86+
$io->info(sprintf('"%s" completed in %0.2fms.', $warmer::class, 1000 * (microtime(true) - $start)));
87+
}
88+
}
89+
} finally {
90+
if ($collectDeprecations) {
91+
restore_error_handler();
92+
93+
if (is_file($this->deprecationLogsFilepath)) {
94+
$previousLogs = unserialize(file_get_contents($this->deprecationLogsFilepath));
95+
if (\is_array($previousLogs)) {
96+
$collectedLogs = array_merge($previousLogs, $collectedLogs);
97+
}
98+
}
99+
100+
file_put_contents($this->deprecationLogsFilepath, serialize(array_values($collectedLogs)));
101+
}
102+
}
103+
104+
return array_values(array_unique($preload));
105+
}
106+
107+
/**
108+
* @return iterable<mixed, WarmableInterface>
109+
*/
110+
protected function getWarmers(): iterable
111+
{
112+
return $this->warmers;
113+
}
114+
}

src/Symfony/Component/HttpKernel/Kernel.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,10 @@ protected function initializeContainer()
541541

542542
$preload = $this instanceof WarmableInterface ? (array) $this->warmUp($this->container->getParameter('kernel.cache_dir')) : [];
543543

544+
if ($this->container->has('build_warmer')) {
545+
$preload = array_merge($preload, (array) $this->container->get('build_warmer')->warmUp($this->container->getParameter('kernel.build_dir')));
546+
}
547+
544548
if ($this->container->has('cache_warmer')) {
545549
$preload = array_merge($preload, (array) $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')));
546550
}

0 commit comments

Comments
 (0)
0