using System.Collections.Concurrent; using ClaudeDo.Worker.Runner.Interfaces; namespace ClaudeDo.Worker.Runner; // Singleton in-memory registry of active live streaming sessions. // A session's lifetime matches its associated task run; dead entries are removed by the runner. public sealed class LiveSessionRegistry { private readonly ConcurrentDictionary _sessions = new(); public void Register(string taskId, ILiveSession session) { if (_sessions.TryRemove(taskId, out var existing)) { // Best-effort stop of the replaced session; don't await to avoid deadlock risk. _ = existing.StopAsync().ContinueWith(t => { if (t.IsFaulted) { /* swallow — old session is already orphaned */ } }, TaskScheduler.Default); } _sessions[taskId] = session; } public bool TryGet(string taskId, out ILiveSession session) { if (_sessions.TryGetValue(taskId, out var s)) { session = s; return true; } session = null!; return false; } public void Unregister(string taskId) => _sessions.TryRemove(taskId, out _); public async Task StopAsync(string taskId) { if (_sessions.TryRemove(taskId, out var session)) await session.StopAsync(); } }