Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
343
src/Framework/Discovery/Storage/FileSystemDiscoveryStorage.php
Normal file
343
src/Framework/Discovery/Storage/FileSystemDiscoveryStorage.php
Normal file
@@ -0,0 +1,343 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Discovery\Storage;
|
||||
|
||||
use App\Framework\Async\FiberManager;
|
||||
use App\Framework\Filesystem\Directory;
|
||||
use App\Framework\Filesystem\File;
|
||||
use App\Framework\Filesystem\FileMetadata;
|
||||
use App\Framework\Filesystem\PermissionChecker;
|
||||
use App\Framework\Filesystem\Storage;
|
||||
use SplFileInfo;
|
||||
|
||||
/**
|
||||
* Implementierung des DiscoveryStorage-Interfaces, die das Filesystem-Modul nutzt
|
||||
* und die Discovery-spezifischen Methoden implementiert.
|
||||
*
|
||||
* Diese Klasse verwendet Composition, um die Funktionalität des Storage-Interfaces
|
||||
* zu delegieren und erweitert sie um Discovery-spezifische Funktionen.
|
||||
*/
|
||||
final class FileSystemDiscoveryStorage implements DiscoveryStorage
|
||||
{
|
||||
public readonly PermissionChecker $permissions;
|
||||
|
||||
public readonly FiberManager $fiberManager;
|
||||
|
||||
/**
|
||||
* @param Storage $storage Basis-Storage-Implementierung für Delegation
|
||||
* @param PermissionChecker $permissions Permissions-Checker
|
||||
* @param FiberManager $fiberManager Fiber-Manager für asynchrone Operationen
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly Storage $storage,
|
||||
?PermissionChecker $permissions = null,
|
||||
?FiberManager $fiberManager = null
|
||||
) {
|
||||
$this->permissions = $permissions ?? new PermissionChecker($storage);
|
||||
$this->fiberManager = $fiberManager ?? new FiberManager(
|
||||
new \App\Framework\DateTime\SystemClock(),
|
||||
new \App\Framework\DateTime\SystemTimer()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get(string $path): string
|
||||
{
|
||||
return $this->storage->get($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function put(string $path, string $content): void
|
||||
{
|
||||
$this->storage->put($path, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists(string $path): bool
|
||||
{
|
||||
return $this->storage->exists($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function delete(string $path): void
|
||||
{
|
||||
$this->storage->delete($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function copy(string $source, string $destination): void
|
||||
{
|
||||
$this->storage->copy($source, $destination);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function size(string $path): int
|
||||
{
|
||||
return $this->storage->size($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function lastModified(string $path): int
|
||||
{
|
||||
return $this->storage->lastModified($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMimeType(string $path): string
|
||||
{
|
||||
return $this->storage->getMimeType($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isReadable(string $path): bool
|
||||
{
|
||||
return $this->storage->isReadable($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isWritable(string $path): bool
|
||||
{
|
||||
return $this->storage->isWritable($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function listDirectory(string $directory): array
|
||||
{
|
||||
return $this->storage->listDirectory($directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createDirectory(string $path, int $permissions = 0755, bool $recursive = true): void
|
||||
{
|
||||
$this->storage->createDirectory($path, $permissions, $recursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function file(string $path): File
|
||||
{
|
||||
return $this->storage->file($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function directory(string $path): Directory
|
||||
{
|
||||
return $this->storage->directory($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function batch(array $operations): array
|
||||
{
|
||||
return $this->storage->batch($operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMultiple(array $paths): array
|
||||
{
|
||||
return $this->storage->getMultiple($paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function putMultiple(array $files): void
|
||||
{
|
||||
$this->storage->putMultiple($files);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMetadataMultiple(array $paths): array
|
||||
{
|
||||
return $this->storage->getMetadataMultiple($paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function findChangedFiles(string $directory, array $fileMetadata): array
|
||||
{
|
||||
// Finde alle Dateien mit dem Muster
|
||||
$allFiles = $this->findFiles($directory, '*.php');
|
||||
$changedFiles = [];
|
||||
$newFiles = [];
|
||||
$modifiedFiles = [];
|
||||
|
||||
// Prüfe jede Datei auf Änderungen
|
||||
foreach ($allFiles as $file) {
|
||||
$filePath = $file->getPathname();
|
||||
|
||||
// Neue Datei (nicht in Metadaten)
|
||||
if (! isset($fileMetadata[$filePath])) {
|
||||
$newFiles[] = $file;
|
||||
$changedFiles[] = $file;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prüfe auf Änderungen mit detaillierten Metadaten
|
||||
try {
|
||||
$storedMetadata = FileMetadata::fromArray($fileMetadata[$filePath]);
|
||||
|
||||
if ($storedMetadata->hasChanged($filePath, $this)) {
|
||||
$modifiedFiles[] = $file;
|
||||
$changedFiles[] = $file;
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
// Bei Problemen mit Metadaten, behandle als geändert
|
||||
$changedFiles[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
return $changedFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function incrementalScan(string $directory, array $fileMetadata): array
|
||||
{
|
||||
$changedFiles = $this->findChangedFiles($directory, $fileMetadata);
|
||||
$updatedMetadata = $fileMetadata;
|
||||
|
||||
// Aktualisiere Metadaten für geänderte Dateien
|
||||
foreach ($changedFiles as $file) {
|
||||
$filePath = $file->getPathname();
|
||||
|
||||
try {
|
||||
$metadata = $this->getDiscoveryMetadata($filePath, true);
|
||||
$updatedMetadata[$filePath] = $metadata->toArray();
|
||||
} catch (\Throwable) {
|
||||
// Bei Fehlern, entferne die Metadaten
|
||||
unset($updatedMetadata[$filePath]);
|
||||
}
|
||||
}
|
||||
|
||||
// Entferne gelöschte Dateien aus Metadaten
|
||||
$allFiles = $this->findFiles($directory, '*.php');
|
||||
$existingPaths = array_map(fn (SplFileInfo $file) => $file->getPathname(), $allFiles);
|
||||
|
||||
foreach (array_keys($updatedMetadata) as $path) {
|
||||
if (! in_array($path, $existingPaths)) {
|
||||
unset($updatedMetadata[$path]);
|
||||
}
|
||||
}
|
||||
|
||||
return $updatedMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function findFiles(string $directory, string $pattern): array
|
||||
{
|
||||
$result = [];
|
||||
$this->findFilesRecursive($directory, $pattern, $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rekursive Hilfsmethode für findFiles
|
||||
*/
|
||||
private function findFilesRecursive(string $directory, string $pattern, array &$result): void
|
||||
{
|
||||
if (! is_dir($directory)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = scandir($directory);
|
||||
if ($files === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = $directory . DIRECTORY_SEPARATOR . $file;
|
||||
|
||||
if (is_dir($path)) {
|
||||
$this->findFilesRecursive($path, $pattern, $result);
|
||||
} elseif ($this->matchesPattern($file, $pattern)) {
|
||||
$result[] = new SplFileInfo($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob ein Dateiname einem Muster entspricht
|
||||
*/
|
||||
private function matchesPattern(string $filename, string $pattern): bool
|
||||
{
|
||||
return fnmatch($pattern, $filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDiscoveryMetadata(string $filePath, bool $calculateChecksum = true): FileMetadata
|
||||
{
|
||||
return FileMetadata::fromFile($filePath, $this, $calculateChecksum);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDiscoveryMetadataMultiple(array $filePaths, bool $calculateChecksum = true): array
|
||||
{
|
||||
$operations = [];
|
||||
|
||||
foreach ($filePaths as $path) {
|
||||
$operations[$path] = fn () => $this->getDiscoveryMetadata($path, $calculateChecksum);
|
||||
}
|
||||
|
||||
return $this->batch($operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function registerFileSystemEvents(string $directory, callable $callback): bool
|
||||
{
|
||||
// Implementierung hängt von der konkreten Event-System-Unterstützung ab
|
||||
// Hier eine einfache Implementierung, die immer false zurückgibt
|
||||
// In einer realen Implementierung würde hier ein Filesystem-Watcher registriert
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user