enhancement
major
minor
defect
critical
major
minor
major
#30216
Hintergrundarbeit scheitert mit „Session revision invalid", wenn das Fenster währenddessen speichert (Jobs, KI-Läufe)
Ein lang laufender Hintergrund-Job der React-Oberfläche (<start-job>, com.top_logic.layout.view.job.JobRunner) bricht mit folgender Ausnahme ab, wenn der Benutzer im selben Browser-Fenster weiterarbeitet und dabei etwas speichert, während der Job läuft:
com.top_logic.knowledge.service.KnowledgeBaseRuntimeException: Session revision invalid: Expected 524 but got 522 in cache com.top_logic.knowledge.service.db2.ValueQueryCache@5d50f54d. Session revision may be the cached revision of the interaction which means that a different interaction for the same session has updated the session concurrently. This leads to inconsistently used data. Persistent data are not corrupted. at com.top_logic.knowledge.service.db2.AbstractKBCache.getCurrentCache(AbstractKBCache.java:166) at com.top_logic.knowledge.service.db2.AbstractKBCache.getValue(AbstractKBCache.java:106) at com.top_logic.knowledge.service.db2.AbstractQueryCache.getValue(AbstractQueryCache.java:23) at com.top_logic.element.model.PersistentModuleSingletons.getAllSingletons(PersistentModuleSingletons.java:308) at com.top_logic.model.util.TLModelUtil.getAllGlobalClassesUncached(TLModelUtil.java:2475) ... at com.top_logic.basic.thread.ThreadContextManager.inContext(ThreadContextManager.java:511) ...
Beobachtet bei einem ETS-Projektimport (ca. 3 Minuten in einer Transaktion), der bei 95 % abbrach. Dasselbe Muster betraf weitere Hintergrundarbeit: Fortschrittsdialoge der klassischen Oberfläche (ProgressDialog), Chat- und Agentenläufe, parallele Tool-Aufrufe, Sub-Agenten, agentChatAsync, die Probeläufe von Datenänderungen, das Speichern von View-Änderungen durch Agenten und die Prompt-Verbesserung.
Ursache
Eine Sub-Session darf nie zwei Interaktionen gleichzeitig ausführen: Die Wissensbasis legt die Session-Revision einer Interaktion beim ersten Zugriff fest; ein Commit einer anderen Interaktion derselben Sub-Session verschiebt die Revision der Sub-Session, die erste Interaktion bleibt auf ihrer alten stehen. Die genannte Hintergrundarbeit lief mit ThreadContextManager.inContext(subSession, ...) auf einem eigenen Thread in der Sub-Session des Fensters bzw. des Aufrufers, also nebenläufig zu dessen Anfragen. Sichtbar wird die Inkonsistenz, sobald ein KB-Cache neu aufgebaut wird (z. B. nach Freigabe einer SoftReference durch den GC): AbstractKBCache#getCurrentCache vergleicht beide Revisionen und wirft obige Ausnahme.
Lösung
- Neuer Einstieg ThreadContextManager.inDerivedContext(SubSessionContext origin, job): führt den Job in einer neuen Interaktion auf einer eigenen Sub-Session aus. Sie gehört zur selben HTTP-Session wie die Ursprungs-Sub-Session und trägt deren Identität (Person, Kontext-ID, Locale, Zeitzone, persönliche Einstellungen), hat aber eine eigene Session-Revision. Sie wird nicht in der Session registriert und verlangt einen Thread ohne laufende Interaktion.
- SubSessionContext#getOrigin() nennt die Sub-Session, von der eine Sub-Session abgeleitet wurde (bei mehrfacher Ableitung die erste). Darüber findet Hintergrundarbeit weiterhin das Fenster, für das sie läuft: ReactWindowRegistry.registryDisplaying/windowDisplaying, ReactWindowReplay.inWindow, ChannelPublisher, die Chat-Registries (ChatSessionRegistry, ChatViewBinding, ChatChannels) und RunPage lösen über den Ursprung auf.
- Die JavaDoc von inContext legt fest: nur für Arbeit, die gegen die anderen Interaktionen der Sub-Session serialisiert ist (Anfrage-Thread, Fenster-Sperre).
- Umgestellt auf inDerivedContext: JobRunner, ProgressDialog, ListComputation, AgentLoop (parallele Tool-Aufrufe), SubagentSpawner, AIScriptFunctions.agentChatAsync, ChangeDataTool (Probelauf), CommittedNow (View-Änderungen), ChatProcessor, PromptImprovementProcessor.
- Tests: TestDerivedContext (Commit der Ursprungs-Sub-Session während einer offenen Interaktion der abgeleiteten scheitert nicht mehr beim Cache-Neuaufbau, mit inContext dagegen schon; Identität und Ursprung), TestJobRunnerSubSession, TestWindowOfSubSession, TestParallelCallContext, TestCommittedNow, TestPresentTool.
Hinweis für Anwendungen
Anwendungscode, der Arbeit auf einem eigenen Thread mit ThreadContextManager.inContext(<Sub-Session eines Fensters>, ...) ausführt, während das Fenster weiter bedient wird, sollte auf ThreadContextManager.inDerivedContext(...) umgestellt werden.