Better handling of cached file map

This commit is contained in:
Pavel Shevaev 2025-04-17 11:38:51 +03:00
parent 7b6d342469
commit c4ca9831f1
3 changed files with 50 additions and 34 deletions

View File

@ -289,7 +289,11 @@ class ConfigCacheFileMap
function update(array $added, array $removed) function update(array $added, array $removed)
{ {
foreach($added as $file) foreach($added as $file)
$this->file2deps[$file] = []; {
//TODO: are we sure about this check?
if(isset($this->file2deps[$file]))
$this->file2deps[$file] = [];
}
foreach($removed as $file) foreach($removed as $file)
unset($this->file2deps[$file]); unset($this->file2deps[$file]);
} }
@ -361,6 +365,8 @@ class ConfigCacheUpdateParams
function splitFilesByChunks(int $max_workers, bool $sort = true) : array function splitFilesByChunks(int $max_workers, bool $sort = true) : array
{ {
$flat = $this->affected_files->getFlatArray(); $flat = $this->affected_files->getFlatArray();
if(!$flat)
return array();
if($sort) if($sort)
usort($flat, fn($a, $b) => $a[1] <=> $b[1]); usort($flat, fn($a, $b) => $a[1] <=> $b[1]);

View File

@ -75,13 +75,19 @@ class ConfigManager
} }
function getFileMap() : ConfigCacheFileMap function getFileMap() : ConfigCacheFileMap
{
return $this->_getFileMap(null);
}
private function _getFileMap(?ConfigDirFiles $files = null) : ConfigCacheFileMap
{ {
if($this->file_map === null) if($this->file_map === null)
{ {
$map = $this->_tryLoadMap(); $map = $this->_tryLoadMap();
if($map === null) if($map === null)
$map = $this->_makeMap($this->scanFiles(extension: '.js')); $map = self::_makeMap($files ?? $this->scanFiles(extension: '.js'));
$this->file_map = $map; $this->file_map = $map;
$this->_saveFileMap();
} }
return $this->file_map; return $this->file_map;
} }
@ -103,7 +109,7 @@ class ConfigManager
$added_files = []; $added_files = [];
$removed_files = []; $removed_files = [];
$fs_cache_map = $this->_checkFileMap( $this->_checkFileMap(
$update_mode, $update_mode,
$input_files, $input_files,
$added_files, $added_files,
@ -113,7 +119,6 @@ class ConfigManager
$affected_files = $this->_getAffectedFiles( $affected_files = $this->_getAffectedFiles(
$update_mode, $update_mode,
$result_bundle_file, $result_bundle_file,
$fs_cache_map,
$input_files, $input_files,
$removed_files $removed_files
); );
@ -121,6 +126,8 @@ class ConfigManager
//NOTE: at this poine taking into account only config files //NOTE: at this poine taking into account only config files
$affected_files->filter(fn($file) => str_ends_with($file, '.conf.js')); $affected_files->filter(fn($file) => str_ends_with($file, '.conf.js'));
config_log("Affected files: {$affected_files->count()}");
$update_params = new ConfigCacheUpdateParams( $update_params = new ConfigCacheUpdateParams(
globals: $this->globals, globals: $this->globals,
affected_files: $affected_files, affected_files: $affected_files,
@ -131,6 +138,8 @@ class ConfigManager
$this->cache->clear(); $this->cache->clear();
$fs_cache_map = $this->getFileMap();
//TODO: traverse all affected files and update file map //TODO: traverse all affected files and update file map
foreach($affected_files as $file) foreach($affected_files as $file)
{ {
@ -141,39 +150,27 @@ class ConfigManager
if($affected_files->count() > 0 || $added_files || $removed_files) if($affected_files->count() > 0 || $added_files || $removed_files)
{ {
$fs_cache_map->update($added_files, $removed_files); $fs_cache_map->update($added_files, $removed_files);
$this->_saveMap($fs_cache_map); $this->_saveFileMap();
} }
return $update_result; return $update_result;
} }
private function _checkFileMap(ConfigUpdateMode $update_mode, ConfigDirFiles $input_files, array &$added_files, array &$removed_files) : ConfigCacheFileMap private function _checkFileMap(ConfigUpdateMode $update_mode, ConfigDirFiles $input_files, array &$added_files, array &$removed_files)
{ {
$fs_cache_map = $this->file_map; $fs_cache_map = $this->_getFileMap($update_mode != ConfigUpdateMode::ChangedOnly ? $input_files : null);
//NOTE: if there's no map so far we need to create one
if($fs_cache_map === null)
{
//let's re-use the input files
if($update_mode === ConfigUpdateMode::Full || $update_mode === ConfigUpdateMode::RelativeToBundle)
$tmp_files = $input_files;
else
$tmp_files = $this->scanFiles(extension: '.js');
$fs_cache_map = $this->_makeMap($tmp_files);
$this->file_map = $fs_cache_map;
}
if($update_mode === ConfigUpdateMode::Full || $update_mode === ConfigUpdateMode::RelativeToBundle) if($update_mode === ConfigUpdateMode::Full || $update_mode === ConfigUpdateMode::RelativeToBundle)
{ {
list($added_files, $removed_files) = $fs_cache_map->compare($input_files->getAllFiles()); list($added_files, $removed_files) = $fs_cache_map->compare($input_files->getAllFiles());
config_log("File map added: ".count($added_files).", removed: ".count($removed_files)); config_log("File map added: ".count($added_files).", removed: ".count($removed_files));
} }
return $fs_cache_map;
} }
private function _getAffectedFiles(ConfigUpdateMode $update_mode, ?string $result_bundle_file, ConfigCacheFileMap $fs_cache_map, ConfigDirFiles $input_files, array $removed_files) : ConfigDirFiles private function _getAffectedFiles(ConfigUpdateMode $update_mode, ?string $result_bundle_file, ConfigDirFiles $input_files, array $removed_files) : ConfigDirFiles
{ {
$fs_cache_map = $this->getFileMap();
$affected_files = null; $affected_files = null;
if($update_mode === ConfigUpdateMode::Full) if($update_mode === ConfigUpdateMode::Full)
@ -185,7 +182,7 @@ class ConfigManager
if($result_bundle_file === null) if($result_bundle_file === null)
throw new Exception("result_bundle_file argument is required"); throw new Exception("result_bundle_file argument is required");
$affected_files = $this->newDirFiles(); $affected_files = ConfigDirFiles::makeFor($this);
foreach($input_files->getMap() as $base_dir => $files) foreach($input_files->getMap() as $base_dir => $files)
{ {
@ -217,17 +214,26 @@ class ConfigManager
} }
} }
} }
else else if($update_mode === ConfigUpdateMode::ChangedOnly)
throw new Exception("Unknown update mode: {$update_mode->value}"); {
$affected_files = ConfigDirFiles::makeFor($this);
foreach($input_files as $file)
{
$affected_files->addFile($file, unique: true);
if(!str_ends_with($file, '.conf.js'))
{
$affected_by_file = $fs_cache_map->getAffectedFiles($file);
foreach($affected_by_file as $dep)
$affected_files->addFile($dep, unique: true);
}
}
}
return $affected_files; return $affected_files;
} }
function newDirFiles() : ConfigDirFiles
{
return new ConfigDirFiles([], $this->globals->base_dirs);
}
function parseFile(string $file) : ConfigParseResult function parseFile(string $file) : ConfigParseResult
{ {
return config_parse($this->globals->base_dirs, $file); return config_parse($this->globals->base_dirs, $file);
@ -250,18 +256,17 @@ class ConfigManager
return ConfigCacheFileMap::unserialize(ensure_read($this->_getMapPath())); return ConfigCacheFileMap::unserialize(ensure_read($this->_getMapPath()));
} }
private function _makeMap(ConfigDirFiles $files) : ConfigCacheFileMap private static function _makeMap(ConfigDirFiles $files) : ConfigCacheFileMap
{ {
config_log("Creating file map"); config_log("Creating file map");
$map = new ConfigCacheFileMap(); $map = new ConfigCacheFileMap();
$map->update($files->getAllFiles(), []); $map->update($files->getAllFiles(), []);
$this->_saveMap($map);
return $map; return $map;
} }
private function _saveMap(ConfigCacheFileMap $map) private function _saveFileMap()
{ {
ensure_write($this->_getMapPath(), ConfigCacheFileMap::serialize($map)); ensure_write($this->_getMapPath(), ConfigCacheFileMap::serialize($this->getFileMap()));
} }
} }

View File

@ -22,6 +22,11 @@ class ConfigDirFiles implements \ArrayAccess, \Countable, \Iterator
$this->base_dirs = $base_dirs; $this->base_dirs = $base_dirs;
} }
static function makeFor(ConfigManager $mgr) : ConfigDirFiles
{
return new ConfigDirFiles([], $mgr->getGlobals()->base_dirs);
}
function clear() function clear()
{ {
$this->base_dir2files = array(); $this->base_dir2files = array();