fix: DockerSecretsResolver - don't normalize absolute paths like /var/www/html/...
Some checks failed
Deploy Application / deploy (push) Has been cancelled
Some checks failed
Deploy Application / deploy (push) Has been cancelled
This commit is contained in:
226
docs/debugging/additional-refactoring-suggestions.md
Normal file
226
docs/debugging/additional-refactoring-suggestions.md
Normal file
@@ -0,0 +1,226 @@
|
||||
# Weitere Refactoring-Vorschläge für Discovery Cache
|
||||
|
||||
## Implementiert: Vorschlag 2 - Cache-Invalidierung bei Datei-Änderungen
|
||||
|
||||
✅ **Implementiert:**
|
||||
- `StalenessChecker::areFilesModifiedSince()` - Prüft einzelne Dateien statt nur Verzeichnisse
|
||||
- `DiscoveryCacheManager::invalidateIfFilesChanged()` - Invalidiert Cache bei Datei-Änderungen
|
||||
- `DiscoveryCacheManager::extractCriticalFilesFromRegistry()` - Extrahiert kritische Dateien aus Registry
|
||||
- Integration in `DiscoveryServiceBootstrapper` für automatische Prüfung kritischer Komponenten-Dateien
|
||||
|
||||
## Weitere Vorschläge
|
||||
|
||||
### Vorschlag 6: Automatische Datei-Erkennung für kritische Komponenten
|
||||
|
||||
**Problem:** Aktuell müssen kritische Dateien manuell in `DiscoveryServiceBootstrapper` aufgelistet werden.
|
||||
|
||||
**Lösung:** Automatische Erkennung aller Komponenten-Dateien aus der Registry:
|
||||
|
||||
```php
|
||||
// In DiscoveryCacheManager.php
|
||||
public function invalidateIfComponentFilesChanged(DiscoveryContext $context): bool
|
||||
{
|
||||
$result = $this->getStandardCache($context);
|
||||
|
||||
if (!$result->found || !$result->entry) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$criticalFiles = $this->extractCriticalFilesFromRegistry($result->entry->registry);
|
||||
|
||||
if (empty($criticalFiles)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->invalidateIfFilesChanged($context, $criticalFiles);
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Keine manuelle Wartung der Datei-Liste nötig.
|
||||
|
||||
### Vorschlag 7: Watch-Mode für Development
|
||||
|
||||
**Problem:** In Development müssen Entwickler manuell den Cache löschen.
|
||||
|
||||
**Lösung:** Watch-Mode, der automatisch auf Datei-Änderungen reagiert:
|
||||
|
||||
```php
|
||||
// In DiscoveryServiceBootstrapper.php
|
||||
public function enableWatchMode(array $watchPaths = []): void
|
||||
{
|
||||
$this->watchMode = true;
|
||||
$this->watchPaths = $watchPaths;
|
||||
|
||||
// Register file watcher
|
||||
$this->fileWatcher = new FileWatcher($watchPaths, function($changedFiles) {
|
||||
$this->invalidateCacheForFiles($changedFiles);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Automatische Cache-Invalidierung während Development.
|
||||
|
||||
### Vorschlag 8: Cache-Warming mit File-Hash-Verification
|
||||
|
||||
**Problem:** Cache könnte veraltet sein, auch wenn Datei-Modifikationszeiten gleich sind.
|
||||
|
||||
**Lösung:** File-Hash-Verification für kritische Dateien:
|
||||
|
||||
```php
|
||||
// In StalenessChecker.php
|
||||
public function verifyFileHashes(array $filePaths, array $expectedHashes): bool
|
||||
{
|
||||
foreach ($filePaths as $filePath) {
|
||||
if (!isset($expectedHashes[$filePath])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$currentHash = md5_file($filePath);
|
||||
if ($currentHash !== $expectedHashes[$filePath]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Präzisere Erkennung von Datei-Änderungen, auch bei gleichen Modifikationszeiten.
|
||||
|
||||
### Vorschlag 9: Incremental Cache Updates
|
||||
|
||||
**Problem:** Bei jeder Datei-Änderung wird der gesamte Cache neu erstellt.
|
||||
|
||||
**Lösung:** Incremental Updates - nur geänderte Komponenten werden neu geladen:
|
||||
|
||||
```php
|
||||
// In DiscoveryCacheManager.php
|
||||
public function updateCacheIncrementally(DiscoveryContext $context, array $changedFiles): bool
|
||||
{
|
||||
$result = $this->getStandardCache($context);
|
||||
|
||||
if (!$result->found || !$result->entry) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$registry = $result->entry->registry;
|
||||
|
||||
// Remove entries for changed files
|
||||
foreach ($changedFiles as $file) {
|
||||
$registry = $this->removeEntriesForFile($registry, $file);
|
||||
}
|
||||
|
||||
// Re-discover only changed files
|
||||
$newEntries = $this->discoverFiles($changedFiles);
|
||||
|
||||
// Merge new entries into registry
|
||||
$updatedRegistry = $this->mergeRegistry($registry, $newEntries);
|
||||
|
||||
// Store updated registry
|
||||
return $this->store($context, $updatedRegistry);
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Deutlich schneller bei kleinen Änderungen.
|
||||
|
||||
### Vorschlag 10: Cache-Tags für selektive Invalidierung
|
||||
|
||||
**Problem:** Bei Änderungen müssen alle Discovery-Caches gelöscht werden.
|
||||
|
||||
**Lösung:** Cache-Tags für selektive Invalidierung:
|
||||
|
||||
```php
|
||||
// In DiscoveryCacheManager.php
|
||||
public function invalidateByTag(string $tag): bool
|
||||
{
|
||||
// Invalidate only caches with specific tag
|
||||
// e.g., 'component:popover', 'route:api', etc.
|
||||
$keys = $this->findCacheKeysByTag($tag);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$this->cache->forget($key);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Selektive Invalidierung nur betroffener Caches.
|
||||
|
||||
### Vorschlag 11: Cache-Metadaten für Debugging
|
||||
|
||||
**Problem:** Schwer zu debuggen, welche Dateien im Cache enthalten sind.
|
||||
|
||||
**Lösung:** Cache-Metadaten mit Datei-Liste:
|
||||
|
||||
```php
|
||||
// In CacheEntry.php
|
||||
public function __construct(
|
||||
public readonly DiscoveryRegistry|array $registry,
|
||||
public readonly Timestamp $createdAt,
|
||||
public readonly string $version = '',
|
||||
public readonly CacheLevel $cacheLevel = CacheLevel::NORMAL,
|
||||
public readonly CacheTier $cacheTier = CacheTier::HOT,
|
||||
public readonly array $sourceFiles = [], // NEW: List of source files
|
||||
public readonly array $fileHashes = [] // NEW: File hashes for verification
|
||||
) {
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Besseres Debugging und Verifikation.
|
||||
|
||||
### Vorschlag 12: Background Cache Refresh
|
||||
|
||||
**Problem:** Cache-Refresh blockiert Request.
|
||||
|
||||
**Lösung:** Background Refresh mit stale-while-revalidate Pattern:
|
||||
|
||||
```php
|
||||
// In DiscoveryCacheManager.php
|
||||
public function getWithBackgroundRefresh(DiscoveryContext $context): ?DiscoveryRegistry
|
||||
{
|
||||
$result = $this->getStandardCache($context);
|
||||
|
||||
if ($result->found && $result->isUsable()) {
|
||||
return $result->entry->registry;
|
||||
}
|
||||
|
||||
// Return stale cache if available
|
||||
if ($result->entry !== null) {
|
||||
$this->triggerBackgroundRefresh($context);
|
||||
return $result->entry->registry;
|
||||
}
|
||||
|
||||
// No cache available, do synchronous refresh
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Keine Blockierung von Requests während Cache-Refresh.
|
||||
|
||||
## Empfohlene Implementierungsreihenfolge
|
||||
|
||||
1. ✅ **Vorschlag 2** (Cache-Invalidierung bei Datei-Änderungen) - **IMPLEMENTIERT**
|
||||
2. **Vorschlag 6** (Automatische Datei-Erkennung) - Sofortige Verbesserung
|
||||
3. **Vorschlag 11** (Cache-Metadaten) - Für besseres Debugging
|
||||
4. **Vorschlag 7** (Watch-Mode) - Für Development-Quality-of-Life
|
||||
5. **Vorschlag 9** (Incremental Updates) - Für Performance
|
||||
6. **Vorschlag 10** (Cache-Tags) - Für Skalierbarkeit
|
||||
7. **Vorschlag 12** (Background Refresh) - Für Production-Performance
|
||||
8. **Vorschlag 8** (File-Hash-Verification) - Optional, für höchste Präzision
|
||||
|
||||
## Priorisierung
|
||||
|
||||
**Hoch (sofort):**
|
||||
- Vorschlag 6: Automatische Datei-Erkennung
|
||||
- Vorschlag 11: Cache-Metadaten
|
||||
|
||||
**Mittel (nächste Iteration):**
|
||||
- Vorschlag 7: Watch-Mode
|
||||
- Vorschlag 9: Incremental Updates
|
||||
|
||||
**Niedrig (langfristig):**
|
||||
- Vorschlag 10: Cache-Tags
|
||||
- Vorschlag 12: Background Refresh
|
||||
- Vorschlag 8: File-Hash-Verification
|
||||
|
||||
216
docs/debugging/discovery-cache-refactoring.md
Normal file
216
docs/debugging/discovery-cache-refactoring.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# Discovery Cache Refactoring - Analyse und Vorschläge
|
||||
|
||||
## Problem-Analyse
|
||||
|
||||
### Identifiziertes Problem
|
||||
|
||||
Die Debug-Logs zeigen:
|
||||
```
|
||||
[DEBUG ComponentRegistry] LiveComponent: class=App\Application\LiveComponents\Popover\PopoverComponent, name=popover, arguments={"name":"popover"}
|
||||
```
|
||||
|
||||
**Befund:**
|
||||
1. ✅ Die Datei enthält korrekt `popover-live` (bestätigt durch direkte Reflection)
|
||||
2. ❌ Der Discovery-Cache enthält noch `{"name":"popover"}`
|
||||
3. ❌ Die Discovery wird nicht neu durchgeführt - es erscheint "Cached registry loaded", aber kein "Performing fresh discovery"
|
||||
4. ❌ Der Cache wird sofort nach dem Löschen neu erstellt, bevor die Discovery-Registry die Attribute aus den Dateien liest
|
||||
|
||||
### Root Cause
|
||||
|
||||
Der Discovery-Cache wird geladen, bevor die Discovery-Registry die Attribute aus den Dateien liest. Die Arguments werden aus dem Cache geladen, nicht direkt aus den Dateien.
|
||||
|
||||
**Cache-Load-Reihenfolge:**
|
||||
1. `DiscoveryCacheManager::get()` wird aufgerufen
|
||||
2. Cache wird geladen (enthält noch alte Arguments)
|
||||
3. `ComponentRegistry::buildNameMap()` verwendet die gecachten Arguments
|
||||
4. Kollision tritt auf, weil beide Komponenten als `popover` registriert werden
|
||||
|
||||
## Refactoring-Vorschläge
|
||||
|
||||
### Vorschlag 1: Staleness-Prüfung verbessern
|
||||
|
||||
**Problem:** Die Staleness-Prüfung prüft nicht auf die spezifischen Dateien, die geändert wurden.
|
||||
|
||||
**Lösung:** Erweitere `StalenessChecker` um eine Methode, die prüft, ob bestimmte Dateien geändert wurden:
|
||||
|
||||
```php
|
||||
// In StalenessChecker.php
|
||||
public function areFilesModifiedSince(array $filePaths, Timestamp $since): bool
|
||||
{
|
||||
foreach ($filePaths as $filePath) {
|
||||
if ($this->fileSystemService->exists($filePath)) {
|
||||
$modifiedTime = $this->fileSystemService->getModifiedTime($filePath);
|
||||
if ($modifiedTime->toInt() > $since->toInt()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Präzise Prüfung auf geänderte Dateien statt allgemeine Staleness-Prüfung.
|
||||
|
||||
### Vorschlag 2: Cache-Invalidierung bei Datei-Änderungen
|
||||
|
||||
**Problem:** Der Cache wird nicht automatisch invalidated, wenn Dateien geändert werden.
|
||||
|
||||
**Lösung:** Füge einen File-Watcher hinzu, der Datei-Änderungen erkennt und den Cache automatisch invalidated:
|
||||
|
||||
```php
|
||||
// In DiscoveryCacheManager.php
|
||||
public function invalidateIfFilesChanged(array $filePaths): bool
|
||||
{
|
||||
$key = $this->buildCacheKey($context);
|
||||
$entry = $this->getStandardCache($context);
|
||||
|
||||
if (!$entry->found || !$entry->entry) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cacheCreatedAt = $entry->entry->createdAt;
|
||||
|
||||
foreach ($filePaths as $filePath) {
|
||||
if ($this->fileSystemService->exists($filePath)) {
|
||||
$modifiedTime = $this->fileSystemService->getModifiedTime($filePath);
|
||||
if ($modifiedTime->toInt() > $cacheCreatedAt->toInt()) {
|
||||
$this->invalidate($context);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Automatische Cache-Invalidierung bei Datei-Änderungen.
|
||||
|
||||
### Vorschlag 3: Arguments direkt aus Dateien lesen (Bypass Cache)
|
||||
|
||||
**Problem:** Die Arguments werden aus dem Cache geladen, nicht direkt aus den Dateien.
|
||||
|
||||
**Lösung:** Füge eine Option hinzu, die Arguments direkt aus den Dateien liest, wenn der Cache als stale erkannt wird:
|
||||
|
||||
```php
|
||||
// In ComponentRegistry.php, buildNameMap()
|
||||
private function buildNameMap(): ComponentNameMap
|
||||
{
|
||||
$mappings = [];
|
||||
$liveComponentClassNames = [];
|
||||
|
||||
// Get all LiveComponent attributes from DiscoveryRegistry
|
||||
$liveComponents = $this->discoveryRegistry->attributes()->get(LiveComponent::class);
|
||||
|
||||
foreach ($liveComponents as $discoveredAttribute) {
|
||||
/** @var LiveComponent|null $attribute */
|
||||
$attribute = $discoveredAttribute->createAttributeInstance();
|
||||
|
||||
if ($attribute && ! empty($attribute->name)) {
|
||||
$className = $discoveredAttribute->className->toString();
|
||||
|
||||
// DEBUG: Log für Popover-Komponenten
|
||||
if (str_contains($className, 'Popover')) {
|
||||
// Prüfe ob Datei geändert wurde seit Cache-Erstellung
|
||||
$filePath = $discoveredAttribute->filePath?->toString();
|
||||
if ($filePath && $this->isFileModifiedSinceCache($filePath)) {
|
||||
// Lese Arguments direkt aus Datei
|
||||
$attribute = $this->readAttributeFromFile($className, LiveComponent::class);
|
||||
}
|
||||
|
||||
error_log(sprintf(
|
||||
"[DEBUG ComponentRegistry] LiveComponent: class=%s, name=%s, arguments=%s, source=%s",
|
||||
$className,
|
||||
$attribute->name,
|
||||
json_encode($discoveredAttribute->arguments),
|
||||
$filePath ?? 'unknown'
|
||||
));
|
||||
}
|
||||
|
||||
$mappings[] = new ComponentMapping($attribute->name, $className);
|
||||
$liveComponentClassNames[] = $className;
|
||||
}
|
||||
}
|
||||
|
||||
// ... rest of method
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Umgeht den Cache, wenn Dateien geändert wurden.
|
||||
|
||||
### Vorschlag 4: Cache-Versionierung
|
||||
|
||||
**Problem:** Der Cache hat keine Versionierung, die bei Änderungen der Cache-Struktur hilft.
|
||||
|
||||
**Lösung:** Füge eine Cache-Version hinzu, die bei Änderungen der Cache-Struktur erhöht wird:
|
||||
|
||||
```php
|
||||
// In CacheEntry.php
|
||||
private const int CACHE_VERSION = 2; // Erhöhe bei Cache-Struktur-Änderungen
|
||||
|
||||
public function __construct(
|
||||
public readonly DiscoveryRegistry|array $registry,
|
||||
public readonly Timestamp $createdAt,
|
||||
public readonly string $version = '',
|
||||
public readonly CacheLevel $cacheLevel = CacheLevel::NORMAL,
|
||||
public readonly CacheTier $cacheTier = CacheTier::HOT,
|
||||
public readonly int $cacheVersion = self::CACHE_VERSION
|
||||
) {
|
||||
}
|
||||
|
||||
// In DiscoveryCacheManager.php
|
||||
private function isCacheVersionValid(CacheEntry $entry): bool
|
||||
{
|
||||
return $entry->cacheVersion === CacheEntry::CACHE_VERSION;
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Automatische Cache-Invalidierung bei Cache-Struktur-Änderungen.
|
||||
|
||||
### Vorschlag 5: Discovery-Registry Refresh-Mechanismus
|
||||
|
||||
**Problem:** Die Discovery-Registry wird nicht automatisch aktualisiert, wenn Dateien geändert werden.
|
||||
|
||||
**Lösung:** Füge einen Refresh-Mechanismus hinzu, der die Discovery-Registry automatisch aktualisiert:
|
||||
|
||||
```php
|
||||
// In DiscoveryServiceBootstrapper.php
|
||||
public function refreshIfNeeded(): void
|
||||
{
|
||||
$discoveryCacheManager = $this->container->get(DiscoveryCacheManager::class);
|
||||
$context = $this->createDiscoveryContext();
|
||||
|
||||
$cachedRegistry = $discoveryCacheManager->get($context);
|
||||
|
||||
if ($cachedRegistry === null) {
|
||||
// Cache ist leer, führe Discovery durch
|
||||
$this->bootstrap();
|
||||
return;
|
||||
}
|
||||
|
||||
// Prüfe ob Registry stale ist
|
||||
if ($this->isRegistryStale($cachedRegistry, $context)) {
|
||||
// Registry ist stale, führe Discovery durch
|
||||
$this->bootstrap();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Vorteil:** Automatische Aktualisierung der Discovery-Registry bei Änderungen.
|
||||
|
||||
## Empfohlene Implementierungsreihenfolge
|
||||
|
||||
1. **Vorschlag 1** (Staleness-Prüfung verbessern) - Sofortige Verbesserung
|
||||
2. **Vorschlag 2** (Cache-Invalidierung bei Datei-Änderungen) - Langfristige Lösung
|
||||
3. **Vorschlag 3** (Arguments direkt aus Dateien lesen) - Workaround für aktuelles Problem
|
||||
4. **Vorschlag 4** (Cache-Versionierung) - Präventive Maßnahme
|
||||
5. **Vorschlag 5** (Discovery-Registry Refresh-Mechanismus) - Automatisierung
|
||||
|
||||
## Sofortige Lösung (Workaround)
|
||||
|
||||
Für das aktuelle Problem sollte **Vorschlag 3** implementiert werden, da er das Problem direkt behebt, ohne die gesamte Cache-Architektur zu ändern.
|
||||
|
||||
## Langfristige Lösung
|
||||
|
||||
**Vorschlag 2** sollte langfristig implementiert werden, da er das Problem an der Wurzel löst und verhindert, dass ähnliche Probleme in Zukunft auftreten.
|
||||
|
||||
Reference in New Issue
Block a user