From a092aed4ed71ad3a9d2ae3724d81fea6ae12e51a Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 30 Mar 2022 12:00:59 +0300 Subject: [PATCH] When saving yaml and markdown, create also a cached version of the file and recompile it in opcache --- CHANGELOG.md | 4 +- system/src/Grav/Common/File/CompiledFile.php | 71 ++++++++++++++++++-- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4565f9f0d0..59f4a11290 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ # v1.7.33 ## mm/dd/2022 -1. [](#bugfix) +1. [](#improved) + * When saving yaml and markdown, create also a cached version of the file and recompile it in opcache +2. [](#bugfix) * Fixed missing changes in yaml & markdown files if saved multiple times during the same second because of a caching issue # v1.7.32 diff --git a/system/src/Grav/Common/File/CompiledFile.php b/system/src/Grav/Common/File/CompiledFile.php index ce133a600e..9393ab70fe 100644 --- a/system/src/Grav/Common/File/CompiledFile.php +++ b/system/src/Grav/Common/File/CompiledFile.php @@ -10,6 +10,8 @@ namespace Grav\Common\File; use Exception; +use Grav\Common\Debugger; +use Grav\Common\Grav; use Grav\Common\Utils; use RocketTheme\Toolbox\File\PhpFile; use RuntimeException; @@ -61,9 +63,13 @@ public function content($var = null) ) { // Attempt to lock the file for writing. try { - $file->lock(false); + $locked = $file->lock(false); } catch (Exception $e) { - // Another process has locked the file; we will check this in a bit. + $locked = false; + + /** @var Debugger $debugger */ + $debugger = Grav::instance()['debugger']; + $debugger->addMessage(sprintf('%s(): Cannot obtain a lock for compiling cache file for %s: %s', __METHOD__, $this->filename, $e->getMessage()), 'warning'); } // Decode RAW file into compiled array. @@ -77,14 +83,17 @@ public function content($var = null) ]; // If compiled file wasn't already locked by another process, save it. - if ($file->locked() !== false) { + if ($locked) { $file->save($cache); $file->unlock(); // Compile cached file into bytecode cache - if (function_exists('opcache_invalidate')) { + if (function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN)) { + $lockName = $file->filename(); + // Silence error if function exists, but is restricted. - @opcache_invalidate($file->filename(), true); + @opcache_invalidate($lockName, true); + @opcache_compile_file($lockName); } } } @@ -99,6 +108,58 @@ public function content($var = null) return parent::content($var); } + /** + * Save file. + * + * @param mixed $data Optional data to be saved, usually array. + * @return void + * @throws RuntimeException + */ + public function save($data = null) + { + // Make sure that the cache file is always up to date! + $key = md5($this->filename); + $file = PhpFile::instance(CACHE_DIR . "compiled/files/{$key}{$this->extension}.php"); + try { + $locked = $file->lock(); + } catch (Exception $e) { + $locked = false; + + /** @var Debugger $debugger */ + $debugger = Grav::instance()['debugger']; + $debugger->addMessage(sprintf('%s(): Cannot obtain a lock for compiling cache file for %s: %s', __METHOD__, $this->filename, $e->getMessage()), 'warning'); + } + + parent::save($data); + + if ($locked) { + $modified = $this->modified(); + $filename = $this->filename; + $class = get_class($this); + $size = filesize($filename); + + // Decode data into compiled array. + $cache = [ + '@class' => $class, + 'filename' => $filename, + 'modified' => $modified, + 'size' => $size, + 'data' => $data + ]; + + $file->save($cache); + $file->unlock(); + + // Compile cached file into bytecode cache + if (function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN)) { + $lockName = $file->filename(); + // Silence error if function exists, but is restricted. + @opcache_invalidate($lockName, true); + @opcache_compile_file($lockName); + } + } + } + /** * Serialize file. *