fix: Activity spinner stuck spinning forever
The viewer UI activity spinner would spin indefinitely because isAnySessionProcessing() queried all pending/processing messages in the database globally — including orphaned messages from dead sessions that no generator would ever process. These orphans caused isProcessing=true forever.
Changes
- Scoped
isAnySessionProcessing()andhasPendingMessages()to only check sessions in the active in-memory Map, so orphaned DB messages no longer affect the spinner - Added
terminateSession()method enforcing a restart-or-terminate invariant — every generator exit must either restart or fully clean up - Fixed 3 zombie paths in the
.finally()handler that previously left sessions alive in memory with no generator running - Fixed idle-timeout race condition where fresh messages arriving between idle abort and cleanup could be silently dropped
- Removed redundant bare
isProcessing: truebroadcast and eliminated double-iteration inbroadcastProcessingStatus() - Replaced inline
require()with proper accessor viasessionManager.getPendingMessageStore() - Added 8 regression tests for session termination invariant