Операции сессий

Многопоточная синхронизация: блокировки, heartbeat, mirror sync, list/delete.

Не даёт двум процессам creo писать в одну сессию одновременно.

sequenceDiagram
    participant TUI
    participant Bus
    participant Sync as SyncService
    participant DB

    TUI->>Bus: SessionLockRequest{sid, pid, staleAfter}
    Bus->>Sync: обработка
    Sync->>DB: UPDATE sessions SET locked_by=pid WHERE locked_by IS NULL OR stale
    DB-->>Sync: acquired/denied
    Sync->>Bus: SessionLockResult{sid, acquired, lockedBy, dataVersion}
    Bus->>TUI: SessionLockResultMsg

TUI каждые 2 секунды шлёт sync request для продления блокировки и проверки изменений от других процессов.

sequenceDiagram
    participant TUI
    participant Bus
    participant Sync as SyncService
    participant DB

    loop Каждые 2 сек
        TUI->>Bus: SessionSyncRequest{sid, pid, turnActive}
        Bus->>Sync: обработка
        Sync->>DB: продлить lock heartbeat
        Sync->>DB: проверить running, pending, data_version
        DB-->>Sync: состояние
        Sync->>Bus: SessionSyncResult{sid, locked, pendingIDs, ...}
        Bus->>TUI: SessionSyncResultMsg
    end
Поле Значение
locked true если другой процесс держит lock
lockedPID PID владельца
otherActive владелец запускает turn (running=1)
lockAcquired TUI был locked, но захватил lock (stale/free)
pendingIDs ID pending сообщений в БД
dataVersion версия данных (для mirror sync)
entryCount кол-во записей

Когда TUI locked другим процессом, но пользователь отправляет сообщение — TUI пытается перехватить lock если владелец idle.

sequenceDiagram
    participant TUI
    participant Bus
    participant Sync as SyncService
    participant DB

    TUI->>TUI: handleSubmit → SessionLocked=true
    TUI->>Bus: SessionTakeoverRequest{sid, pid}
    Bus->>Sync: обработка
    Sync->>DB: UPDATE sessions SET locked_by=pid WHERE running=0 AND locked_by=otherPID
    DB-->>Sync: success/fail
    Sync->>Bus: SessionTakeoverResult{sid, success}
    Bus->>TUI: результат
    alt success
        TUI->>TUI: SessionLocked=false
        TUI->>TUI: отправка сообщения
    end

Устанавливает флаг running (1/0) в БД. Sync tick поддерживает его актуальным на основе TurnActive. Предотвращает takeover race: если агент стартовал, running=1 не даёт другому процессу перехватить lock.

Когда TUI locked другим процессом, но хочет видеть изменения в реальном времени: SessionSyncResult несёт dataVersion и entryCount. При изменении TUI перезагружает сессию из БД и добавляет новые сообщения в чат.

Soft-delete / restore. Обрабатывается SyncService → БД.

Запрос списка сессий для дерева /sessions. Результат несёт SessionInfo — DTO без DB-типов.