Версия 0.8.3 удерживала глобальный Store.slots mutex на весь durable
Test, build and publish / All tests and Linux binary (push) Failing after 19s
Test, build and publish / Container smoke test and Gitea publish (push) Skipped

commit
(включая fsync/append). fsync одного канала задерживал SM-коммиты всех
остальных
сессий; при медленном диске и нескольких пользователях это выглядело как
«сервер
перестал отвечать на запросы» и секундная доставка сообщений.

- Глобальная блокировка разделена: короткий lock `slots` теперь только
  валидирует token/limits и резервирует слот; сам append+fsync идёт под
  per-session `wal` lock. Один медленный канал больше не блокирует
  остальных.
- Ротация/compaction/GC сериализуются отдельным `maintenance` lock вне
  любого
  per-session lock — очереди append и compaction для одного WAL не
  гонки,
  дедлоков нет, инварианты durable и crash-тесты сохранены.
- Все существующие crash/latency/recovery regressions зелёные без
  изменений.

Для genuinely медленного диска (VPS с медленным fsync) добавлена опция
как в
Prosody, где исходящие SM-stanza живого клиента идут в in-memory smqueue
без
fsync, а durable пишутся счётчик/h и переход в hibernation.

- `smacks_online_durable = false` (strict — default): live-сессии не
  fsync на
  каждый outbound/ack, а помечают `dirty`; фоновый проход
  `smacks_flush_interval` (default1с) и offline-переход фиксируют
  durable.
- Offline/hibernating цели в любом режиме фиксируются durable ДО
  доставки —
  сохраняются критичные инварианты («Alice отправила, Bob ещё не
  авторизован»)
  и crash-регрессии; отзыв токенов/expiry остаётся durable.
- Pre-ACK durable гарантию даёт строгий режим; deferred — компромисс
  Prosody
  «низкая задержка» в обмен на ограниченное окно потери для
  online-пиров.

- `cargo test --locked --release`: 54 binary, 336 passed, 11 ignored (0
  fail).
- Strict crash (`slow_storage_crash_network`), latency
  (`slow_storage_latency`),
  `sm_restart`, `journal_recovery_sync`, личная доставка — все зелёные.
- Новые регрессии: `tests/deferred_sm_online_network.py` (wire, deferred
  режим:
  offline durable до ACK, online доставка + flush persist), два Rust
  unit-теста
  в `tests/sm_journal.rs` (deferred online commit/flush, offline
  durable).
- `push_latency_network.py` в этой среде падает на TLS CA `keyUsage`
  из-за более
  строгого TLS в Python 3.14 (до SM-кода, не связано с этим изменением).

Документация: [docs/DURABLE-MESSAGE-IO.md](docs/DURABLE-MESSAGE-IO.md),
[docs/COMPATIBILITY.md](docs/COMPATIBILITY.md).
This commit is contained in:
wt committed 2026-10-21 14:43:59 +07:00
1 parent bff609097b
commit 821e1c3e2f
11 files changed
+656 -88

No files matched your search

+32 -17
View File
@@ -7,23 +7,23 @@
неизвестные явно включённые MUC-модули отклоняются при запуске.
Это не означает полного совпадения поведения с Prosody.
| Область | Что реализовано | Существенные пределы |
|---|---|---|
| Конфигурация | Lua/JSON/YAML/YML/TOML, Include, глобальные и локальные области, наследование модулей | Lua VM ограничена; не все функции окружения конфигуратора Prosody доступны. Runtime обслуживает один VirtualHost и его компоненты |
| Хранилище | internal `.dat`, `.list`, бинарные строки, смешанные ключи Lua, атомарные записи, потоковые архивы, инвалидирование `.lidx` | SQL, external storage остальных модулей и произвольные драйверы не реализованы; S3 uploads поддержаны. Каталог блокируется между процессами Rust; Prosody в блокировке не участвует |
| Аккаунты, saslauth | internal_hashed SHA-1/SHA-256, SASLprep, PLAIN внутри TLS, SCRAM и PLUS с tls-exporter/tls-server-end-point, SSDP, SASL2 | Только internal_hashed; опциональный sasl2_bind2 (alias bind2) поддерживает inline bind/SM/CSI/Carbons. SASL2 inline SM resume и takeover живого транспорта реализованы; Bind2/MAM metadata читает endpoints без полного scan; полные MAM queries всё ещё могут сканировать историю |
| Сообщения и presence | локальная маршрутизация, приоритеты ресурсов, контакты/подписки/probes, offline, carbons, блокировки | Полная совместимость всех пограничных сценариев маршрутизации ещё не подтверждена |
| MAM | личный и комнатный MAM2, prefs, формы, RSM, фильтры времени/контакта/ID, extended queries, metadata, stanza-id, expiry | Нет доказательства совпадения каждой ошибки и порядка результатов при всех комбинациях запроса |
| MUC | комнаты, несколько ресурсов, роли/affiliations, owner/admin, конфигурация, приглашения, история без MAM и MAM, occupant-id/avatar, hats, PM/presence policies, регистрация, административные ad-hoc команды; журнал конфигурации, членства и истории до ответа, crash recovery persistent/temporary комнат | Rust-журнал авторитетен, native config/state — экспорт. Без SM восстановление требует новой аутентификации точного полного JID; grace по умолчанию 300 с, `muc_recovery_grace_period` 1..604800. Действующая приватная SM-запись восстанавливает логическое членство до listeners. Произвольные Lua-модули не запускаются; [MUC-RECOVERY.md](MUC-RECOVERY.md) |
| PEP/pubsub | persistent nodes/items, ACL, subscriptions, publish/retract/purge/delete, owner/configuration, caps, OMEMO XML как payload | Не все необязательные политики узлов Prosody реализованы; OMEMO шифруют клиенты, криптография OMEMO не часть сервера |
| private/bookmarks/vCard | private XML, старые и новые закладки, vCard/temp-vCard4 и avatar-переходы | Межклиентное поведение нужно дополнительно проверить настоящими клиентами |
| SM/push | acknowledgements после обработки, resumable XEP-0198 sessions, replay, ограниченные очереди, приватный durable snapshot, heartbeat и shutdown checkpoint; legacy SASL/SASL2 resume после restart; native регистрации push | Нужны новый TLS/SASL-транспорт и токен того же владельца; TCP/TLS-сокеты не сохраняются. SM-снимок не native Prosody: 256 MiB суммарно, 8 MiB/4096 stanza на сессию. При неопределённой отправке возможен replay. Есть coalescing и watchdog первого push; реальный APNs/FCM цикл не подтверждён |
| CSI | active/inactive, ограниченный буфер, native importance function + runtime defaults для OMEMO/receipts/markers, delay, flush при клиентской активности и grace period | Defaults0.8.2 важнее по доставке, чем строгая native policy; явный csi_important_payloads заменяет defaults. Событие socket drain приближено завершением записи; необязательные расширенные XPath-фильтры поддержаны не полностью |
| Федерация | входящие/исходящие STARTTLS, CA/DNS-ID, SASL EXTERNAL, DNS SRV, проверка домена каждого stanza, ограниченный пул соединений | Нет dialback/DANE/OtherName-only/SRV-ID/bidi/direct TLS |
| HTTP upload | Несколько XEP-0363 components, Host/path isolation, local/S3 gateway, multipart/SigV4, streaming PUT, GET/HEAD/range/conditional, квоты/expiry, native metadata/JWT; offline local↔S3/S3↔S3 migration с SHA-256/resume; intent/exact-key recovery и quarantine; реальный 10 GiB PUT/GET через MinIO проверен | MinIO single-node с описанным netlink adapter тестовой среды; AWS/distributed deployment не проверены. Миграция требует остановки сервера и временного места под один файл; source сохраняется. Потерянные ownership metadata и неопределённый Complete требуют отдельного разбора; HTTP-UPLOAD.md |
| WebSocket/BOSH | WS/WSS и HTTP/HTTPS, общая XMPP-сессия, origin rules, BOSH RID/retry/hold/reorder/restart; http_altconnect XRD/JRD discovery; http_paths, HTTP Host/fallback, внешний URL, доверенные IP/CIDR и forwarded headers для TLS reverse proxy | Один VirtualHost с компонентами; нет PROXYv1/v2, произвольных Lua HTTP-приложений и горячей перенастройки. См. HTTP-PROXY.md |
| admin_shell | протокол admin socket, status/version/uptime, списки, основные операции аккаунтов | Нет произвольного Lua, горячей загрузки модулей и полного набора prosodyctl |
| Остальные модули | disco, ping, time, version, uptime, register, TURN extdisco/HMAC, каталог seclabels | Нет встроенного TURN. Coturn работает отдельно. `pep_simple` пуст в предоставленном исходнике |
| Область | Что реализовано | Существенные пределы |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Конфигурация | Lua/JSON/YAML/YML/TOML, Include, глобальные и локальные области, наследование модулей | Lua VM ограничена; не все функции окружения конфигуратора Prosody доступны. Runtime обслуживает один VirtualHost и его компоненты |
| Хранилище | internal `.dat`, `.list`, бинарные строки, смешанные ключи Lua, атомарные записи, потоковые архивы, инвалидирование `.lidx` | SQL, external storage остальных модулей и произвольные драйверы не реализованы; S3 uploads поддержаны. Каталог блокируется между процессами Rust; Prosody в блокировке не участвует |
| Аккаунты, saslauth | internal_hashed SHA-1/SHA-256, SASLprep, PLAIN внутри TLS, SCRAM и PLUS с tls-exporter/tls-server-end-point, SSDP, SASL2 | Только internal_hashed; опциональный sasl2_bind2 (alias bind2) поддерживает inline bind/SM/CSI/Carbons. SASL2 inline SM resume и takeover живого транспорта реализованы; Bind2/MAM metadata читает endpoints без полного scan; полные MAM queries всё ещё могут сканировать историю |
| Сообщения и presence | локальная маршрутизация, приоритеты ресурсов, контакты/подписки/probes, offline, carbons, блокировки | Полная совместимость всех пограничных сценариев маршрутизации ещё не подтверждена |
| MAM | личный и комнатный MAM2, prefs, формы, RSM, фильтры времени/контакта/ID, extended queries, metadata, stanza-id, expiry | Нет доказательства совпадения каждой ошибки и порядка результатов при всех комбинациях запроса |
| MUC | комнаты, несколько ресурсов, роли/affiliations, owner/admin, конфигурация, приглашения, история без MAM и MAM, occupant-id/avatar, hats, PM/presence policies, регистрация, административные ad-hoc команды; журнал конфигурации, членства и истории до ответа, crash recovery persistent/temporary комнат | Rust-журнал авторитетен, native config/state — экспорт. Без SM восстановление требует новой аутентификации точного полного JID; grace по умолчанию 300 с, `muc_recovery_grace_period` 1..604800. Действующая приватная SM-запись восстанавливает логическое членство до listeners. Произвольные Lua-модули не запускаются; [MUC-RECOVERY.md](MUC-RECOVERY.md) |
| PEP/pubsub | persistent nodes/items, ACL, subscriptions, publish/retract/purge/delete, owner/configuration, caps, OMEMO XML как payload | Не все необязательные политики узлов Prosody реализованы; OMEMO шифруют клиенты, криптография OMEMO не часть сервера |
| private/bookmarks/vCard | private XML, старые и новые закладки, vCard/temp-vCard4 и avatar-переходы | Межклиентное поведение нужно дополнительно проверить настоящими клиентами |
| SM/push | acknowledgements после обработки, resumable XEP-0198 sessions, replay, ограниченные очереди, приватный durable snapshot, heartbeat и shutdown checkpoint; legacy SASL/SASL2 resume после restart; native регистрации push | Нужны новый TLS/SASL-транспорт и токен того же владельца; TCP/TLS-сокеты не сохраняются. SM-снимок не native Prosody: 256 MiB суммарно, 8 MiB/4096 stanza на сессию. При неопределённой отправке возможен replay. Есть coalescing и watchdog первого push; реальный APNs/FCM цикл не подтверждён |
| CSI | active/inactive, ограниченный буфер, native importance function + runtime defaults для OMEMO/receipts/markers, delay, flush при клиентской активности и grace period | Defaults0.8.2 важнее по доставке, чем строгая native policy; явный csi_important_payloads заменяет defaults. Событие socket drain приближено завершением записи; необязательные расширенные XPath-фильтры поддержаны не полностью |
| Федерация | входящие/исходящие STARTTLS, CA/DNS-ID, SASL EXTERNAL, DNS SRV, проверка домена каждого stanza, ограниченный пул соединений | Нет dialback/DANE/OtherName-only/SRV-ID/bidi/direct TLS |
| HTTP upload | Несколько XEP-0363 components, Host/path isolation, local/S3 gateway, multipart/SigV4, streaming PUT, GET/HEAD/range/conditional, квоты/expiry, native metadata/JWT; offline local↔S3/S3↔S3 migration с SHA-256/resume; intent/exact-key recovery и quarantine; реальный 10 GiB PUT/GET через MinIO проверен | MinIO single-node с описанным netlink adapter тестовой среды; AWS/distributed deployment не проверены. Миграция требует остановки сервера и временного места под один файл; source сохраняется. Потерянные ownership metadata и неопределённый Complete требуют отдельного разбора; HTTP-UPLOAD.md |
| WebSocket/BOSH | WS/WSS и HTTP/HTTPS, общая XMPP-сессия, origin rules, BOSH RID/retry/hold/reorder/restart; http_altconnect XRD/JRD discovery; http_paths, HTTP Host/fallback, внешний URL, доверенные IP/CIDR и forwarded headers для TLS reverse proxy | Один VirtualHost с компонентами; нет PROXYv1/v2, произвольных Lua HTTP-приложений и горячей перенастройки. См. HTTP-PROXY.md |
| admin_shell | протокол admin socket, status/version/uptime, списки, основные операции аккаунтов | Нет произвольного Lua, горячей загрузки модулей и полного набора prosodyctl |
| Остальные модули | disco, ping, time, version, uptime, register, TURN extdisco/HMAC, каталог seclabels | Нет встроенного TURN. Coturn работает отдельно. `pep_simple` пуст в предоставленном исходнике |
## Особенности именно вашего конфига
@@ -172,3 +172,18 @@ ad-hoc destroy/set-affiliation. Общие и host `modules_disabled` приме
MAM/SM используют authoritative redo sidecars. Перед сменой writer или откатом
на старую версию требуется offline `storage-checkpoint CONFIG`; после аварии
нельзя просто удалить sidecars. Подробности — [DURABLE-MESSAGE-IO.md](DURABLE-MESSAGE-IO.md).
## Deferred online SM durability0.8.4
Строгий (по умолчанию) режим фиксирует каждый исходящий SM-stanza снаружи
глобальной блокировки store (per-session redo mutex), поэтому медленное IO одной
сессии не останавливает обработку сообщений остальных. На медленном диске
Per-message fsync всё ещё суммируется в секунды.
Добавлена Prosody-совместимая опция `smacks_online_durable = false`: живые
(online) сессии не делают durable commit на каждый stanza, а помечаются и
сбрасываются фоновым проходом `smacks_flush_interval` (default 1с) и на offline
переходе. Offline/hibernating цели по-прежнему фиксируются durable ДО доставки
независимо от опции, так что критичная регрессия «Alice отправляет, Bob offline»
сохраняется. Опция не ослабляет safe-инварианты отзыва токенов/expiry.
Подробности — [DURABLE-MESSAGE-IO.md](DURABLE-MESSAGE-IO.md).
+31 -9
View File
@@ -71,15 +71,15 @@ in-place append при активном redo считается незаверш
`message-processing-slow` по-прежнему имеет threshold 250 мс, duration_ms, route
и connection. Новые поля в integer milliseconds:
|Поле|Измеряемый этап|
|---|---|
|pre_routing_ms|Работа до личного MAM; для MUC/ранних выходов — обработка до handled|
|sender_mam_ms|Политика и архивирование отправителя|
|recipient_mam_ms|Проверка аккаунта, политика и архивирование получателя|
|delivery_ms|Маршрутизация, targets, mutex и transmit|
|carbons_ms|Выбор ресурсов и отправка carbon|
|offline_push_ms|Offline commit и подготовка/enqueue push|
|handled_ms|Session mutex и durable mark_handled|
| Поле | Измеряемый этап |
| ---------------- | -------------------------------------------------------------------- |
| pre_routing_ms | Работа до личного MAM; для MUC/ранних выходов — обработка до handled |
| sender_mam_ms | Политика и архивирование отправителя |
| recipient_mam_ms | Проверка аккаунта, политика и архивирование получателя |
| delivery_ms | Маршрутизация, targets, mutex и transmit |
| carbons_ms | Выбор ресурсов и отправка carbon |
| offline_push_ms | Offline commit и подготовка/enqueue push |
| handled_ms | Session mutex и durable mark_handled |
Неисполненные этапы равны 0. target_count — выбранные локальные ресурсы,
carbon_count — успешные carbon transmit. Это серверные этапы, не время
@@ -101,3 +101,25 @@ partial tails, corruption, ротацию, tombstones, migration и offline hand
Медленный диск не становится быстрым от сокращения числа sync. Проверка на
loopback не устанавливает причину каждого production warning; новые phase
fields позволяют проверить это на целевой системе.
## 0.8.4: разблокировка и deferred online durability
Глобальный `Store.slots` mutex ранее удерживался на весь commit (включая fsync),
так что fsync одной сессии блокировал durable-коммиты всех остальных — при
медленном диске и нескольких пользователях это выглядело как «сервер перестал
отвечать на запросы». Теперь речь накладывает короткий lock `slots` только на
валидацию/резервирование, а сам append+fsync идёт под per-session `wal` lock.
Ротация/compaction/GC сериализуются отдельным `maintenance` lock вне любого
`sessions` `wal` lock — дедлоков нет и инварианты durable сохранены.
Для genuinely медленного диска добавлена Prosody-совместимая опция
`smacks_online_durable = false` (strict — default). В режиме live-сессии с
открытым transport не fsync на каждый outbound/ack, а помечают `dirty`;
фоновый проход `smacks_flush_interval` (default1с) и offline-переход фиксируют
состояние durable. Offline/hibernating цели фиксируются durable ДО доставки в
любом режиме (сохранены crash-инварианты и регрессия Bob-online-не-авторизован).
Резюме wire-проверки: strict crash/latency тесты зелёные; deferred прошел
`tests/deferred_sm_online_network.py`; семантику store проверяют два новых Rust
unit-теста в tests/sm_journal.rs. Полную durable-гарантию пред-ACK даёт строгий
режим; deferred — это компромисс «максимальная совместимость с Prosody и
низкая задержка» в обмен на ограниченное окно потери для online-пиров.