16) { $scope = substr($scope, 0, 8) . "..." . substr($scope, -8) . "-" . substr(md5($scope), 0, 8); } $scope_filename_part = $scope === null ? "" : "-$scope"; $lock_file = $dir . "/.lock$scope_filename_part-" . \NeoLibrary\NeoGlobal\unique_planck_date(); $lock_files_for_scope = function () use ($dir, $scope, $scope_filename_part) { $lock_files = \NeoLibrary\NeoGlobal\fs_glob($scope === null ? $dir . "/.lock-*" : $dir . "/.lock$scope_filename_part-*") ?: []; return $scope === null ? \NeoLibrary\NeoGlobal\array_filter_better($lock_files, fn ($filename) => substr_count(basename($filename), "-") === 1) : $lock_files; }; $touch_success = \NeoLibrary\NeoGlobal\fs_touch($lock_file); if (!$touch_success) { \NeoLibrary\NeoGlobal\throw_global_exception("Could not create lock file in synclock_dir. Path: " . $lock_file . ". Scope: $scope" . "."); } while (basename($lock_file) !== basename((function ($files) { sort($files); return $files[0] ?? ""; })($lock_files_for_scope()))) { $touch_success = \NeoLibrary\NeoGlobal\fs_touch($lock_file); if (!$touch_success) { \NeoLibrary\NeoGlobal\throw_global_exception("Could not touch lock file in synclock_dir. Path: " . $lock_file . ". Scope: $scope" . "."); } $ignore_all_warnings_and_errors(function() use ($timeout, $lock_files_for_scope) { foreach ($lock_files_for_scope() as $filename) { if (\NeoLibrary\NeoGlobal\is_cache_file_outdated($filename, $timeout)) { \NeoLibrary\NeoGlobal\fs_unlink($filename); } } }); usleep((1) * 1000); } return $callback(); } finally { if (!\NeoLibrary\NeoGlobal\fs_file_exists($lock_file)) { \NeoLibrary\NeoGlobal\global_warn_with_module_name("_global--synclock", "This PHP process took too long in synclock_dir. It was cleaned up by another PHP process. Path: $dir Scope: $scope"); } else { $ignore_all_warnings_and_errors(fn () => \NeoLibrary\NeoGlobal\fs_unlink($lock_file)); } } } finally { unset($synclocked_dirs[$synclock_dir_and_scope]); } } function wait_until_no_synclock_locks_in_subdirs($dir, $timeout = 5) { $dir = untrailingslashit($dir); if (!\NeoLibrary\NeoGlobal\fs_is_dir($dir)) { return true; } $end_time = microtime(true) + $timeout; while (true) { $lock_files = \NeoLibrary\NeoGlobal\fs_glob($dir . "/*/.lock*") ?: []; if (empty($lock_files)) { return true; } if (microtime(true) >= $end_time) { \NeoLibrary\NeoGlobal\global_warn_with_module_name("_global--synclock", "Synclock lock files still exist in cache subdirectories before clear_plugin_cache. Path: " . $dir . ". Lock files: " . implode(", ", array_map("basename", $lock_files))); return false; } usleep((50) * 1000); } }