8000 bug #25117 [FrameworkBundle] Make cache:clear "atomic" and consistent… · symfony/symfony@315180c · GitHub
[go: up one dir, main page]

Skip to content

Commit 315180c

Browse files
committed
bug #25117 [FrameworkBundle] Make cache:clear "atomic" and consistent with cache:warmup (hkdobrev)
This PR was merged into the 3.4 branch. Discussion ---------- [FrameworkBundle] Make cache:clear "atomic" and consistent with cache:warmup | Q | A | ------------- | --- | Branch? | master | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes/no | Fixed tickets | - | License | MIT | Doc PR | - Here's what happens before/after this PR on `cache:clear` and `cache:clear --no-warmup`. ### Before PR **`cache:clear`** 1. `rm var/cache_old` 1. Clearing cache in `var/cache` &nbsp;<i>&lt;--- This is not in line and not atomic</i> 1. `rm var/cache_warmup` 1. Warming up cache in `var/cache_warmup` 1. `mv var/cache var/cache_old` 1. `mv var/cache_warmup var/cache` 1. `rm var/cache_old` **`cache:clear --no-warmup`** 1. `rm var/cache_old` 1. Clearing cache in `var/cache` &nbsp;<i>&lt;--- This is not in line and not atomic</i> 1. `mv var/cache var/cache_old` <i>&lt;--- The old cache dir is completely obsolete in this workflow</i> 1. `rm var/cache_old` --- ### After PR **`cache:clear`** 1. `rm var/cache_old` 1. `rm var/cache_new` 1. Clearing cache in `var/cache_new` 1. Warming up cache in `var/cache_new` 1. `mv var/cache var/cache_old` 1. `mv var/cache_new var/cache` 1. `rm var/cache_old` **`cache:clear --no-warmup`** 1. `rm var/cache_old` 1. `rm var/cache_new` 1. Clearing cache in `var/cache_new` 1. `mv var/cache var/cache_old` 1. `mv var/cache_new var/cache` 1. `rm var/cache_old` --- The main differences: - Unify the flows and have each distinct operation only once in the code - Clear the cache in the new cache directory and then switch to it atomically instead of clearing in the current one. - Always have the cache directory present in the end. It was missing after `cache:clear --no-warmup` before. I think this brings more consistency and is aligned with the present goals of the command as well. However, I'm not really familiar with the Symfony framework and I might have wrong assumptions. Commits ------- 8b88d9f [FrameworkBundle] Make cache:clear "atomic" and consistent with cache:warmup
2 parents 0d655ba + 8b88d9f commit 315180c

File tree

1 file changed

+31
-37
lines changed

1 file changed

+31
-37
lines changed

src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -93,32 +93,44 @@ protected function execute(InputInterface $input, OutputInterface $output)
9393
$realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir');
9494
}
9595

96+
$fs = $this->filesystem;
9697
$io = new SymfonyStyle($input, $output);
9798

9899
$kernel = $this->getApplication()->getKernel();
99100
$realCacheDir = isset($realCacheDir) ? $realCacheDir : $kernel->getContainer()->getParameter('kernel.cache_dir');
100101
// the old cache dir name must not be longer than the real one to avoid exceeding
101102
// the maximum length of a directory or file path within it (esp. Windows MAX_PATH)
102103
$oldCacheDir = substr($realCacheDir, 0, -1).('~' === substr($realCacheDir, -1) ? '+' : '~');
104+
$fs->remove($oldCacheDir);
103105

104106
if (!is_writable($realCacheDir)) {
105107
throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir));
106108
}
107109

108-
if ($this->filesystem->exists($oldCacheDir)) {
109-
$this->filesystem->remove($oldCacheDir);
110-
}
111-
112110
$io->comment(sprintf('Clearing the cache for the <info>%s</info> environment with debug <info>%s</info>', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
113111
$this->cacheClearer->clear($realCacheDir);
114112

115113
// The current event dispatcher is stale, let's not use it anymore
116114
$this->getApplication()->setDispatcher(new EventDispatcher());
117115

118-
if ($input->getOption('no-warmup')) {
119-
$this->filesystem->rename($realCacheDir, $oldCacheDir);
120-
} else {
121-
$this->warmupCache($input, $output, $realCacheDir, $oldCacheDir);
116+
$containerDir = new \ReflectionObject($kernel->getContainer());
117+
$containerDir = basename(dirname($containerDir->getFileName()));
118+
119+
// the warmup cache dir name must have the same length as the real one
120+
// to avoid the many problems in serialized resources files
121+
$warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_');
122+
123+
if ($output->isVerbose() && $fs->exists($warmupDir)) {
124+
$io->comment('Clearing outdated warmup directory...');
125+
}
126+
$fs->remove($warmupDir);
127+
$fs->mkdir($warmupDir);
128+
129+
if (!$input->getOption('no-warmup')) {
130+
if ($output->isVerbose()) {
131+
$io->comment('Warming up cache...');
132+
}
133+
$this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers'));
122134

123135
if ($this->warning) {
124136
@trigger_error($this->warning, E_USER_DEPRECATED);
@@ -127,12 +139,22 @@ protected function execute(InputInterface $input, OutputInterface $output)
127139
}
128140
}
129141

142+
$containerDir = $fs->exists($warmupDir.'/'.$containerDir) ? false : $containerDir;
143+
144+
$fs->rename($realCacheDir, $oldCacheDir);
145+
$fs->rename($warmupDir, $realCacheDir);
146+
147+
if ($containerDir) {
148+
$fs->rename($oldCacheDir.'/'.$containerDir, $realCacheDir.'/'.$containerDir);
149+
touch($realCacheDir.'/'.$containerDir.'.legacy');
150+
}
151+
130152
if ($output->isVerbose()) {
131153
$io->comment('Removing old cache directory...');
132154
}
133155

134156
try {
135-
$this->filesystem->remove($oldCacheDir);
157+
$fs->remove($oldCacheDir);
136158
} catch (IOException $e) {
137159
$io->warning($e->getMessage());
138160
}
@@ -144,34 +166,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
144166
$io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
145167
}
146168

147-
private function warmupCache(InputInterface $input, OutputInterface $output, $realCacheDir, $oldCacheDir)
148-
{
149-
$io = new SymfonyStyle($input, $output);
150-
151-
// the warmup cache dir name must have the same length than the real one
152-
// to avoid the many problems in serialized resources files
153-
$realCacheDir = realpath($realCacheDir);
154-
$warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_');
155-
156-
if ($this->filesystem->exists($warmupDir)) {
157-
if ($output->isVerbose()) {
158-
$io->comment('Clearing outdated warmup directory...');
159-
}
160-
$this->filesystem->remove($warmupDir);
161-
}
162-
163-
if ($output->isVerbose()) {
164-
$io->comment('Warming up cache...');
165-
}
166-
$this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers'));
167-
168-
$this->filesystem->rename($realCacheDir, $oldCacheDir);
169-
if ('\\' === DIRECTORY_SEPARATOR) {
170-
sleep(1); // workaround for Windows PHP rename bug
171-
}
172-
$this->filesystem->rename($warmupDir, $realCacheDir);
173-
}
174-
175169
/**
176170
* @param string $warmupDir
177171
* @param string $realCacheDir

0 commit comments

Comments
 (0)
0