[FrameworkBundle] Make cache:clear "atomic" and consistent with cache:warmup

This commit is contained in:
Haralan Dobrev 2017-11-22 17:01:26 +02:00 committed by Nicolas Grekas
parent cd6690dacd
commit 8b88d9fc36
1 changed files with 31 additions and 37 deletions

View File

@ -93,6 +93,7 @@ EOF
$realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir');
}
$fs = $this->filesystem;
$io = new SymfonyStyle($input, $output);
$kernel = $this->getApplication()->getKernel();
@ -100,25 +101,36 @@ EOF
// the old cache dir name must not be longer than the real one to avoid exceeding
// the maximum length of a directory or file path within it (esp. Windows MAX_PATH)
$oldCacheDir = substr($realCacheDir, 0, -1).('~' === substr($realCacheDir, -1) ? '+' : '~');
$fs->remove($oldCacheDir);
if (!is_writable($realCacheDir)) {
throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir));
}
if ($this->filesystem->exists($oldCacheDir)) {
$this->filesystem->remove($oldCacheDir);
}
$io->comment(sprintf('Clearing the cache for the <info>%s</info> environment with debug <info>%s</info>', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
$this->cacheClearer->clear($realCacheDir);
// The current event dispatcher is stale, let's not use it anymore
$this->getApplication()->setDispatcher(new EventDispatcher());
if ($input->getOption('no-warmup')) {
$this->filesystem->rename($realCacheDir, $oldCacheDir);
} else {
$this->warmupCache($input, $output, $realCacheDir, $oldCacheDir);
$containerDir = new \ReflectionObject($kernel->getContainer());
$containerDir = basename(dirname($containerDir->getFileName()));
// the warmup cache dir name must have the same length as the real one
// to avoid the many problems in serialized resources files
$warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_');
if ($output->isVerbose() && $fs->exists($warmupDir)) {
$io->comment('Clearing outdated warmup directory...');
}
$fs->remove($warmupDir);
$fs->mkdir($warmupDir);
if (!$input->getOption('no-warmup')) {
if ($output->isVerbose()) {
$io->comment('Warming up cache...');
}
$this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers'));
if ($this->warning) {
@trigger_error($this->warning, E_USER_DEPRECATED);
@ -127,12 +139,22 @@ EOF
}
}
$containerDir = $fs->exists($warmupDir.'/'.$containerDir) ? false : $containerDir;
$fs->rename($realCacheDir, $oldCacheDir);
$fs->rename($warmupDir, $realCacheDir);
if ($containerDir) {
$fs->rename($oldCacheDir.'/'.$containerDir, $realCacheDir.'/'.$containerDir);
touch($realCacheDir.'/'.$containerDir.'.legacy');
}
if ($output->isVerbose()) {
$io->comment('Removing old cache directory...');
}
try {
$this->filesystem->remove($oldCacheDir);
$fs->remove($oldCacheDir);
} catch (IOException $e) {
$io->warning($e->getMessage());
}
@ -144,34 +166,6 @@ EOF
$io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
}
private function warmupCache(InputInterface $input, OutputInterface $output, $realCacheDir, $oldCacheDir)
{
$io = new SymfonyStyle($input, $output);
// the warmup cache dir name must have the same length than the real one
// to avoid the many problems in serialized resources files
$realCacheDir = realpath($realCacheDir);
$warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_');
if ($this->filesystem->exists($warmupDir)) {
if ($output->isVerbose()) {
$io->comment('Clearing outdated warmup directory...');
}
$this->filesystem->remove($warmupDir);
}
if ($output->isVerbose()) {
$io->comment('Warming up cache...');
}
$this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers'));
$this->filesystem->rename($realCacheDir, $oldCacheDir);
if ('\\' === DIRECTORY_SEPARATOR) {
sleep(1); // workaround for Windows PHP rename bug
}
$this->filesystem->rename($warmupDir, $realCacheDir);
}
/**
* @param string $warmupDir
* @param string $realCacheDir