Monitor 1.8.1: поставка и проверка
Состояние на 27.10.2026, 00:36 МСК: функционал поставлен, 30-минутный прогон и заключительная приёмка новой фразы активной записи прошли. Все три тестовых микрофона выключены, три записи подтверждены полными. Отдельный FAIL остаётся у внешнего пути LinTO (linto_stream_error); остальные проверенные backend работают.
Что изменено
- Живой режим включён по умолчанию, включая старые ссылки. Пауза фиксирует снимок и сохраняется как
live=0. Короткие уведомления после commit передают только ID через существующую подписку Monitor. Обновления объединяются за 250 мс; одновременно выполняется одна сверка и хранится один флаг необходимости повторить её. Независимые видимые ресурсы внутри сверки читаются параллельно; очередь уведомлений не накапливается. - Списки обновляются на месте. Фильтры, раскрытые секции, положение чтения и плеер сохраняются. Скрытая вкладка снимает подписки; возврат и восстановление связи вызывают одну сверку. Графики и результаты ограничены по объёму; свёрнутые графики не рисуются.
- Полный UUID сессии переносится в левой колонке. Вернулись User-Agent, начало, последняя активность, число событий и индикатор подключения. Ширина колонок меняется мышью и клавиатурой, сохраняется локально, сбрасывается двойным нажатием. На узком экране колонки располагаются последовательно.
- Удалены полосы локальной навигации и дублирующие блоки событий сообщения / вызовов модели внутри повтора. Технические данные доступны в существующем выполнении, журнале и JSON. Секции получили одинаковые рамки, полосы заголовков и отступы в обеих темах.
- Завершение архива повторяется ограниченно и идемпотентно; ошибка не проглатывается. Фоновая сверка проверяет финальный манифест, завершение владельца, последовательности, размеры, координаты и хеши всех блоков. Только подтверждённый
recording_owner_lostисправляется автоматически; прочие ошибки сохраняются. - Доступность фразы и её настроек отделена от завершения всего потока. Проверяются выбранные блоки и контекст; недописанный правый контекст требует ожидания. Полный replay разрешён для завершённой проверенной записи.
- Захват сохраняет полный requested/actual. Неуказанное requested обозначено «По умолчанию браузера», неизвестное actual — «Браузер не сообщил». Включение/выключение показано как состояние захвата.
- Loader показывает этап, объём и процент, поддерживает отмену, ошибку и повтор. Waveform рисуется независимо от PCM. Совместимый параметр
batch_bytesограничен 128 КиБ; каждый исходный блок проверяется. Длинная запись начинает с 4 секунд, затем читается порциями. Запоздалые ответы игнорируются, Blob URL освобождаются. input_listвыполняет один сбор на вызов; повторная доставка использует сохранённый результат. Повторная сериализация убрана, DOM-ссылки коллектора освобождаются, служебные карты ограничены без удаления сохранённой истории.
Новых сервисов, таблиц, постоянных счётчиков, соединений NATS и AudioContext не добавлено. Инфраструктура, DNS, SSH и PostgreSQL не перенастраивались.
Проверки
| Проверка | Результат / доказательство |
|---|---|
| Python | PASS: 247 тестов, 13 subtests; 99 интеграционных сценариев пропущены в unit-job, необходимые интеграционные тесты проверены отдельным job |
| Frontend | PASS: 60 файлов, 429 тестов, TypeScript, build и runtime |
| Пять обязательных CI checks | PASS на 13efe271 — pipeline 5410 |
| Архив с PostgreSQL и NATS | PASS: поздний манифест, повторное завершение, потерянный finalize, owner_lost, повреждённые блоки, активная фраза и ожидание правого контекста; job 23869, 80 интеграционных тестов, включая 13 storage-тестов |
| Реальные текстовые запросы при 0 / 1 / 3 потоках | PASS: c0ed749e…, 1d0a4b51…, f65352aa… появились без ручного обновления и остановки микрофона. На финальном Gateway повторено: afeec8f7… при трёх потоках |
| Контексты вкладок | PASS: A вернула 2 поля, B — 3 поля; общая история содержит источник страницы |
| Три одновременных подключения | PASS: единый серверный снимок содержит два stream_id с одной session_id и третий с другой session_id |
| Историческая запись пользователя | PASS: 5d531bae… стала полной после проверки; фраза 1839876f… доступна в диапазоне 118.520–120.448 с, настройки показаны |
| Пауза / возврат в live | PASS: запрос ee1bfc93… отсутствовал в фиксированном снимке и появился после возобновления |
| Завершение одного потока при продолжающихся соседних | PASS на финальном Gateway: 301a1a1e… завершён, 283,709 с, запись «Полная»; 69353e7e… продолжает принимать и сохранять PCM. production-finalize-isolation.txt |
| Живой экран | PASS: уровни, waveform, счётчики каналов и длина архива обновляются при работающем микрофоне |
| 90 мс, 1 с, 3 с, повтор и границы порций | PASS в реальном Chrome: шесть сценариев; после остановки за 1,8 с — 0 timeupdate и 0 записей currentTime |
| Loader, отмена, повтор | PASS в production; запоздалые ответы и смена источника также проверены тестами |
| Навигация и компоновка | PASS: старые ссылки, Back/Forward, очистка выбора при смене сессии; resize 340→350 px клавиатурой, 340→444 px мышью, сброс до 340; обе темы при viewport 390 px без горизонтального переполнения |
| 30-минутный прогон | PASS: 1800 с, 60 циклов открытия аудио, 2569 обновлений; после закрытия 0 подписок, таймеров, RAF и Blob URL |
| Физическая речь и повтор активной фразы | PASS на финальном Gateway: новая фраза fd3b76d6… появилась без ручного обновления. Аудио 1787,416–1789,760 с и настройки доступны при статусе «Идёт запись». Replay с контекстом 5,344 с завершён за 10,01 с при трёх живых подключениях; слот освобождён. production-new-active-voice-replay.json и .txt |
| Завершение трёх длинных записей | PASS: 69353e7e… — 1943,237 с; a23be5d5… — 1576,596 с; d43e6424… — 1861,462 с. Все три — «Полная»; активных подключений 0, кнопки микрофонов выключены |
Модели: отдельно от интерфейса
При трёх подключённых микрофонах replay одной и той же фразы с контекстом 4,928 с завершился:
| Backend | Итог | Время всего | Что измерялось |
|---|---|---|---|
| Whisper Turbo | PASS | 11,87 с | Подготовка 0,88 с; предзагрузка/подключение 4,58 с; PCM 4,93 с; завершение 1,30 с |
| Whisper Russian | PASS | 11,69 с | Подготовка 0,87 с; предзагрузка/подключение 4,37 с; PCM 4,93 с; завершение 1,32 с |
| GigaAM v3 RNNT | PASS | 12,21 с | Подробные фактические этапы и очередь модели сохранены в production-backends.json |
| LinTO | FAIL внешнего пути | 11,73 с | linto_stream_error; UI показал причину, соединение закрыто, слот освобождён |
После окончательного Gateway 13efe271 повтор Whisper Turbo при трёх живых потоках прошёл за 11,14 с: подготовка 0,94 с, предзагрузка/подключение 3,78 с, PCM 4,93 с, завершение ASR 1,30 с; закрытие соединения и освобождение слота подтверждены журналом.
Заключительный повтор новой фразы из ещё записываемого потока прошёл за 10,01 с: подготовка 0,85 с, предзагрузка/подключение 2,32 с, PCM 5,35 с, завершение ASR 1,31 с. Живое распознавание выдало «Ответь одним словом. Проверка.», повтор — «Отвечу одним словом. Проверка.». Эта разница распознавания сохранена в доказательствах; совпадение текста не заявляется. Очередь модели в журнале — 0,1 мс, отдельные вызовы Decoder — 148,4–157,5 мс. Три stream_id со статусом receiving подтверждены одним серверным снимком во время проверки.
Это единичные функциональные прогоны, а не статистика медианы/p95 модели. Ускорение загрузки Monitor не приписывается нейросетям. Отмена полного replay 182,101 с проверена: «Повтор отменён», слот освобождён.
Поставка
Исходная база: f89d8bdc0f26327dcd412c087ce350d26abdcf47.
Основной функционал первоначально поставлен как 61da43c6ca858d11155809311430434c13839253. Финальный main: 13efe271e90c3f26dc1ca1423930f4c140ab3a2f; он включает исправления завершения архива, раннего манифеста и привязок исходных строк. Все пять checks этого SHA прошли. Окончательная адресная поставка Gateway и Front завершена; Audio WS Ingress остаётся на 61da43c6.
Поставлены только API Gateway, Audio WS Ingress и Front. Задействован src_shared.monitor: его новый необязательный параметр потребляет Gateway. Core и Agent импортируют соседние общие типы, но не исполняют команду monitor и не используют изменённое поле. Проверка поставки подтвердила фактический Image ID, revision, digest, healthy / 1 replica / completed и неизменность соседних service specs/tasks. Приём аудио снова открыт.
| Сервис | Версия пакета / OCI build | Revision | SHA256 образа |
|---|---|---|---|
| API Gateway | 6.10 / 1.0.0.1004 | 13efe271 |
b26fee7ee18a7921f34b1fbf35702e64b27e78ea5ad65ef372648bb15ffcaf66 |
| Audio WS Ingress | 3.6 / 1.0.0.1000 | 61da43c6 |
bb27c27c93ed16b740c062b112ba356f75187e0a5e635a5db823d67a34e967d8 |
| Front | 5.13 / 1.0.0.1004 | 13efe271 |
1e9409fcff5c7efa7017c371894cf63a71eb3b04aa005cf1a33ffe7d30f94b2a |
Финальные Gateway rollout и Front rollout — PASS на SHA 13efe271, pipeline 5410. Preflight 23892, сборки Gateway 23882 / Front 23887 и пять обязательных checks прошли. Последовательная поставка проверила точный образ, рабочую task и неизменность соседних сервисов.
Первоначальные Backend rollout и Frontend rollout — PASS. Build/release pipeline: 5406. У него все пять обязательных checks и адресная поставка PASS; общий статус содержит отказ необязательной загрузки ZIP-артефакта из-за DNS runner. Это отдельно от успешной серверной поставки.
Расширение 1.8.1 установлено в прежний локальный источник; ID, permissions, host_permissions и CSP сохранены. Пользователь подтвердил reload. ZIP опубликован и скачан обратно для проверки SHA-256: [пакет 1.8.1](<https://git.giscloud.ru/voice-chat/webrtc-komaroff/-/packages/1>). Размер 841990 байт, SHA-256376c47b2bd63c0b0be5005f45c270ca9a02852cad5a3b3e9de54a34e305e6a92`. DNS runner не менялся.
Итог diff от согласованной базы: 36 файлов, +763 / −210 строк, включая тесты и документацию. Работа выполнена одним writer в изолированном checkout; основная копия не редактировалась.
Измерения
Контролируемый Chrome-стенд использовал реальные компоненты Monitor, три потока, 10 событий графика/с, обновления запросов примерно каждые 700 мс и задержку RPC 20 мс. В исходном коде автоматические обновления запросов отсутствовали: задержка «до» и процент её уменьшения не определены. После изменений медиана — 306 мс, p95 — 315,7 мс, отображено 2569 обновлений.
| Метрика | Было → стало | Абсолютная разница | Изменение |
|---|---|---|---|
| Готовность начального аудио, медиана стенда | 3100,7 → 165,1 мс | −2935,6 мс | −94,68% |
| Готовность начального аудио, p95 стенда | 3141,5 → 198,5 мс | −2943,0 мс | −93,68% |
| RPC начальной загрузки с метаданными, стенд | 129 → 5 | −124 | −96,12% |
| Начальные запросы Monitor без живых потоков | 4 → 4 | 0 | 0% |
| Начальный буфер PCM | 3 072 000 → 384 000 байт | −2 688 000 байт | −87,5% |
| Получение PCM исторической записи, production | 16 115,6 → 2541,7 мс | −13 573,9 мс | −84,23% |
| RPC PCM исторической записи, production | 137 → 4 | −133 | −97,08% |
| Сбор 100 полей, медиана | 4,2 → 3,4 мс | −0,8 мс | −19,05% |
| Сбор 100 полей, p95 | 6,8 → 4,7 мс | −2,1 мс | −30,88% |
| DOM-ссылки после закрытия коллектора | 100 → 0 | −100 | −100% |
Открытие Monitor без живых потоков требует тех же четырёх чтений: сессии, записи, потоки и запросы. Дополнительных выборок для удалённых дублирующих секций нет. Снимок с тремя живыми потоками содержал пятое чтение сессий от отдельного уведомления; он не используется для сравнения начальной загрузки.
Загрузка сравнивает прежний начальный участок 32 с с новым 4 с: это время до готовности плеера, а не ускорение передачи одинакового объёма. Production — единичный наблюдаемый запуск, не медиана/p95. В изолированном сборе полей выполнено 100 вызовов, ровно 100 сборов в каждой версии; повторная доставка инструмента проверена отдельно.
Прогон выполнялся на frontend 61da43c6; последующая правка Front меняет только два номера строк в ссылках на исходники и не затрагивает проверенные обработчики, графики или плеер.
За последние 15 минут нагрузки: 1 подписка, 2–3 таймера, 1 RAF, 1 Blob URL, 8995–9000 точек истории, 128 результатов, ровно 1193 DOM-узла. JS heap менялся от 10,07 до 17,31 МБ; после очистки — 10,63 МБ. Снимки heap сами по себе не доказывают отсутствие всех возможных утечек; измеренные коллекции ограничены и ресурсы освобождаются. Дополнительный production-замер 4 мин 37 с: heap 9,55 → 5,54 МБ, обработчики 85 → 79, DOM-узлы CDP 775 → 645.
Плеер после остановки: прежнее наблюдение пользователя — около 960 событий за 1,8 с; исправленный плеер — 0 событий и 0 присваиваний currentTime за тот же интервал во всех шести сценариях.
Исходные данные: metrics-final.json, soak-final.json, fields.json, production-audio-before.json, production-audio-after.json, player-chrome.json.
Ошибки, обнаруженные при заключительной приёмке
- Полная проверка архива выполнялась в двухсекундном RPC под общей блокировкой записи. На синтетическом архиве 86,4 МБ / 15 мин воспроизведены тайм-аут завершения и тайм-аут соседнего append. В production при завершении длинных записей соседний архив получил
recording_unavailable, хотя живое аудио продолжалось. После исправления end marker сохраняется за 3,84 мс, проверка проходит отдельно; 30 соседних append успешны (медиана 4,70 мс, p95 5,51 мс). Проверка 172,8 МБ / 30 мин прошла за 14,87 с, finalize — 3,93 мс; 30 соседних append успешны, p95 4,88 мс. Для фоновой проверки действует отдельный лимит 60 с и курсор на 32 блока, foreground RPC сохраняет лимит 2 с. Ошибочные тестовые записи не были выданы за полные. - При доставке манифеста раньше PCM он оставался в ожидающих событиях до finalize. Реальная фраза активного потока получила
audio_archive_manifest_missing. Теперь один SQL-запрос атомарно переносит ожидающий манифест в вставляемый блок. Число запросов записи не увеличено; оба порядка доставки проверены с PostgreSQL. Новых фоновых задач и очередей нет.
В production финальный Gateway читает PCM продолжающейся записи 69353e7e…: статус «Идёт запись», 297,792 с сохранено, в памяти только 0–4 с, загрузка успешна до finalize. Исторические записи 88a3b999… (705,572 с) и b7c5d8d8… (713,957 с) подтверждены полными.
Регрессии сначала воспроизвели оба отказа, затем прошли на исправленном коде; полный адресный набор — 43 теста и 4 subtests PASS. Доказательства: archive-finalize-regression-before.log, archive-finalize-regression-after.log, archive-parallel-benchmark.json, archive-30-minute-after.json, manifest-before-pcm-before.log, manifest-before-pcm-after.log.
Заключительная проверка в Chrome
27.10.2026 в 00:32:40 новая физическая фраза создала запрос fd3b76d6-fef5-5f4c-9e20-7bfc9f98c537 в общей сессии d46de968-2756-4000-97b7-d0d11fbc7d70. В другой сессии появился отдельный голосовой запрос a10dbc30-3c51-50a5-beb9-bb6df709ec35. Monitor показал изменения без нажатия «Обновить»; точная задержка этого production-события не измерялась.
Для первой фразы до остановки микрофона были доступны PCM16 / 48000 Hz / mono, 2,344 с, и снимок настроек: NS и EC requested/actual включены; AGC requested — «По умолчанию браузера», actual — включён. Диапазон replay 1785,416–1790,760 с успешно проверен и обработан. В момент проверки одновременно работали 69353e7e…, a23be5d5… и d43e6424…. После replay число запросов общей сессии осталось 31, число её потоков — 12; диагностический прогон не появился как новое сообщение или исходная запись.
После последовательного выключения микрофонов все три записи прошли проверку и получили статус «Полная». Завершение первой записи не отключило соседний поток. Итоговые состояния сохранены в production-final-shared-archives.txt, production-final-other-archive.txt, production-final-acceptance.json. Снимок результата активной фразы: production-new-active-voice-replay.png.