enhancement
major
minor
major
minor
major
#30001
Entwicklungsmodus: neu geschriebene WEB-INF-Dateien sind über den FileManager erst verzögert sichtbar (Theme-Import zeigt keine Variablen, ThemeEditor_Ticket-24158_Import-export scheitert sporadisch)
Der Scripted-Test com.top_logic.demo/src/test/java/test/com/top_logic/demo/scripted/themeEditor/ThemeEditor_Ticket-24158_Import-export.script.xml scheitert sporadisch in tl-ci-pr-Builds von PRs, die weder den Theme-Editor noch das klassische Theme noch com.top_logic.demo berühren:
Table row with label 'Var' not found, available rows are . At ThemeEditor_Ticket-24158_Import-export.script.xml line 476 column 9 Action: Theme auf Vollständigkeit testen At ThemeEditor_Ticket-24158_Import-export.script.xml line 465 column 6
Vorkommen: tl-ci-pr-Builds 506 (!1986), 510 (!2002), 545 (!2013), alle 2026-10-26/27; Build 517 desselben unveränderten Stands von !1986 lief durch.
Ursache
Im Entwicklungsmodus (devel-file-cache-ide.config.xml) beantwortet MultiFileManager Anfragen nach regulären Dateien unter WEB-INF/ (getDataOverlays(), resolveFile()) aus dem IDEFileSystemCache. Dieser Cache erfährt von neu angelegten und gelöschten Dateien nur über Ereignisse des java.nio.file.WatchService (inotify), die das JDK asynchron in einem eigenen Thread zustellt. Wird eine Datei geschrieben und unmittelbar danach über den FileManager gelesen, ist das Ereignis unter Umständen noch nicht angekommen und die Datei für den FileManager nicht vorhanden; eine gelöschte Datei wird umgekehrt noch geliefert.
Der Theme-Import entpackt theme.xml und theme-settings.xml direkt per getIDEFile() und lädt das Theme sofort danach (MultiThemeFactory.putThemeConfig() -> Theme.loadLocalSettings() -> getDataOverlays(.../theme-settings.xml)). Fehlt das Ereignis noch, wird das Theme ohne Variablen erzeugt und so in der MultiThemeFactory gehalten; die Variablen-Tabelle des Theme-Editors bleibt leer. Dasselbe Rennen betrifft FileManager.createData() / delete() und alle Schreibvorgänge des Theme-Editors (Theme anlegen/löschen, Variablen, Stylesheets, Ressourcen).
Lösung
- FileSystemCache.refresh(Path): gleicht den Cache für eine Datei bzw. ein Verzeichnis synchron mit dem Dateisystem ab (vorhandene Dateien aufnehmen, Watcher für neue Verzeichnisse registrieren, verschwundene Einträge entfernen). Das später eintreffende Watch-Ereignis ändert danach nichts mehr. NoFileSystemCache tut nichts.
- FileManager.refresh(String resourceName) macht direkt (per getIDEFile()) geschriebene oder gelöschte Ressourcen (Datei oder ganzes Verzeichnis) sofort für nachfolgende Zugriffe über den FileManager sichtbar. MultiFileManager gleicht dazu den Cache in allen überlagerten Wurzelverzeichnissen ab, FileManagerDelegate / FileManagerOverlay delegieren. FileManager.createData() und MultiFileManager.delete() rufen den Abgleich selbst auf.
- Alle schreibenden bzw. löschenden Kommandos des Theme-Editors rufen nach ihren Dateioperationen FileManager.refresh() für die betroffenen Ressourcen auf: Theme-Import (alle entpackten Verzeichnisse), Theme anlegen/löschen (neuer Helfer ThemeUtil.refreshThemeFiles(theme)), Theme-Konfiguration, Theme-Variablen anlegen/ändern/löschen, Stylesheets anlegen/ändern/löschen, Ressourcen hochladen/löschen.
- Test test.com.top_logic.layout.TestFileSystemCacheRefresh (läuft in der Modul-Suite von com.top_logic): direkt geschriebene bzw. gelöschte Dateien und Verzeichnisse sowie createData() / delete() sind ohne Warten auf Dateisystem-Ereignisse sichtbar bzw. verschwunden, später eintreffende Ereignisse erzeugen keine doppelten Einträge. Ohne den Abgleich scheitern alle vier Fälle.