Skip to content

Commit

Permalink
When saving yaml and markdown, create also a cached version of the fi…
Browse files Browse the repository at this point in the history
…le and recompile it in opcache
  • Loading branch information
mahagr committed Mar 30, 2022
1 parent 7c2b21f commit a092aed
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 6 deletions.
4 changes: 3 additions & 1 deletion 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
Expand Down
71 changes: 66 additions & 5 deletions system/src/Grav/Common/File/CompiledFile.php
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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);
}
}
}
Expand All @@ -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.
*
Expand Down

0 comments on commit a092aed

Please sign in to comment.