docs: MAM baseline 0.8.4 — best-effort archival and offline repair
Document the 'archive redo baseline changed in place' failure, the runtime session isolation, the offline storage-checkpoint repair, and the Prosody native-format comparison (list_append in-place vs list_store atomic rename).
This commit is contained in:
1 parent
100005379b
commit
75bb730d3c
3 files changed
+99
-27
No files matched your search
@@ -235,7 +235,7 @@ bind2_archive_latency_network.py, archive_edges.rs, session_routing_isolation.rs
|
||||
После изменений обновляйте точные границы совместимости и результаты проверки.
|
||||
Не перезаписывайте исторические отчёты как будто они относятся к новой сборке.
|
||||
В передаваемый ZIP включайте AGENTS.md, workflow, vendor reference, исходники,
|
||||
документацию и scripts; исключайте target, demo data, bin, .git, __pycache__, pyc
|
||||
документацию и scripts; исключайте target, demo data, bin, .git, **pycache**, pyc
|
||||
и секреты. Сохраняйте executable bits shell scripts и проверяйте содержимое ZIP.
|
||||
|
||||
## Durable message IO 0.8.3
|
||||
@@ -298,3 +298,34 @@ Final binary SHA-256: 8ceb8de3a2d02bc4399b8ae817dff7e3c3fe9bff83dc0c6669b7f19210
|
||||
Подробные samples/границы — docs/VALIDATION-0.8.3.md. Checksum и JSON syntax всех frames
|
||||
проверяются при SM replay, но Record создаётся только для последнего
|
||||
snapshot. Recovery WAL sync до публикации обязателен; EIO fixture защищает это.
|
||||
|
||||
## Monal MAM baseline 0.8.4
|
||||
|
||||
Баг: «archive redo baseline changed in place» на живом сервере — внешняя
|
||||
перезапись native `.list` поверх зафиксированного redo-baseline (бакап/копия
|
||||
data_path/Prosody/старая версия) делала каждый `archive_for_user` Err, `?` ронял
|
||||
session, клиент (Monal-iOS) реконнектился и не доставлял сообщение. Причина не в
|
||||
обычном append — baseline ломает только перезапись первых `base` байт в обход
|
||||
`.rredo`; наш Rust-append пишет только в конец.
|
||||
|
||||
Фикс (commit 1000053): 1) MAM-архивация на личной доставке (отправитель,
|
||||
получатель, входящая федерация) стала best-effort `archive_message_best_effort` —
|
||||
storage-ошибка не роняет session и не роняет доставку, в лог `mam-archive-skipped`
|
||||
(санитизированный `sanitized_label`, без payload); 2) offline `storage-checkpoint`
|
||||
теперь ремонтирует непроверенный baseline: `prepare_rewrite` через
|
||||
`is_untrusted_redo` считает текущий синхронизированный native авторитетным и
|
||||
удаляет неприменимый журнал (`retire_redo`). Живой append остаётся fail-closed.
|
||||
Новые tests: `archive.rs` `runtime_append_fails_closed_...`/
|
||||
`offline_checkpoint_retires_...`, сетевой `tests/mam_broken_baseline_network.py`
|
||||
(перезапись baseline не роняет доставку; checkpoint возвращает MAM).
|
||||
|
||||
Сравнение с Prosody: `util/datamanager.lua` `list_append` пишет в конец, а
|
||||
`list_store` (перезапись) делает atomic rename — меняет первые bytes baseline;
|
||||
`plugins/mod_storage_internal.lua` `archive:append` для MUC/`key` и trim/delete
|
||||
делает `list_store` (полная перезапись). Prosody не понимает `.rredo` sidecar. Наш
|
||||
native `.list` сохраняет Prosody-совместимый `item(...)` формат.
|
||||
|
||||
Операционный ремонт пользователя: остановить сервер, `./target/release/rust-xmpp
|
||||
storage-checkpoint CONFIG`, запустить снова. `--experimental` не снимать. Полная
|
||||
замена Prosody требует реального CI, внешней федерации, настоящих клиентов/push,
|
||||
deployment/UID/TLS, rollback и длительной нагрузки — см. COMPATIBILITY.md.
|
||||
+28
-17
@@ -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,14 @@ 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).
|
||||
|
||||
### Внешний перезапись MAM baseline
|
||||
|
||||
Внешняя перезапись native `.list` поверх зафиксированного redo-baseline (бакап,
|
||||
копия data_path, Prosody, старая версия) давала «archive redo baseline changed
|
||||
in place»: каждый MAM-append падал и через `?` ронял session, клиент
|
||||
реконнектился, сообщение не доставлялось. В 0.8.4 MAM-архивация на личной
|
||||
доставке стала best-effort (storage-ошибка не роняет session и не роняет доставку;
|
||||
в лог — `mam-archive-skipped`), а `storage-checkpoint` получил ремонт непроверенного
|
||||
baseline: текущий синхронизированный native считается авторитетным и неприменимый
|
||||
журнал удаляется. Живой append остаётся fail-closed: журнал не удаляется молча.
|
||||
@@ -66,20 +66,50 @@ in-place append при активном redo считается незаверш
|
||||
Редактирование baseline in place без handoff не поддержано. Anchor проверяет
|
||||
последние 4 KiB baseline, не является checksum всего старого архива.
|
||||
|
||||
## Внешний перезапись baseline: «archive redo baseline changed in place»
|
||||
|
||||
Если какой-либо writer (бакап-восстановление, копия data_path, Prosody, старая
|
||||
версия сервера) перезаписал native `.list` поверх зафиксированного baseline без
|
||||
handoff, `.rredo` перестаёт совпадать со своим anchor. Каждый вызов
|
||||
`archive_for_user` возвращал `Err`, и через `?` ошибка роняла session
|
||||
(`connection-closed reason=protocol-or-transport-error`) — клиент (напр. Monal)
|
||||
реконнектился по кругу, сообщение не доставлялось.
|
||||
|
||||
Начиная с 0.8.4 MAM-архивация на трёх местах личной доставки (отправитель,
|
||||
получатель, входящая федерация) стала best-effort: при storage-ошибке исходная
|
||||
stanza всё равно маршрутизируется, обе сессии остаются живы, в лог пишется
|
||||
санитизированный `mam-archive-skipped`. Живой append остаётся fail-closed:
|
||||
непроверенный журнал не удаляется молча, а сохраняется для явного handoff.
|
||||
|
||||
Ремонт выполняется той же командой offline handoff:
|
||||
|
||||
```bash
|
||||
rust-xmpp storage-checkpoint /etc/prosody/prosody.cfg.lua
|
||||
```
|
||||
|
||||
Теперь `prepare_rewrite` распознаёт непроверенный baseline (changed in place,
|
||||
shorter, missing, journal exceeds bound), считает текущий durably-синхронизированный
|
||||
native авторитетным, синхронизирует его и удаляет неприменимый журнал. После этого
|
||||
MAM history снова читается, а новые append создадут свежий redo поверх нового
|
||||
baseline. Сверку совместимости native-формата см. в исходниках Prosody
|
||||
(`util/datamanager.lua` `list_append`/`list_store`, `plugins/mod_storage_internal.lua`
|
||||
`archive:append`): Prosody пишет `item(...)` и при полной перезаписи применяет
|
||||
atomic rename — что и меняет первые bytes baseline, оставляя Rust-журнал устаревшим.
|
||||
|
||||
## Диагностика
|
||||
|
||||
`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. Это серверные этапы, не время
|
||||
|
||||
Reference in new issue
Block a user