some
This commit is contained in:
1 parent
d1492f3b44
commit
e17ce5504e
4 files changed
+57
-13
No files matched your search
@@ -319,13 +319,29 @@ storage-ошибка не роняет session и не роняет достав
|
||||
`offline_checkpoint_retires_...`, сетевой `tests/mam_broken_baseline_network.py`
|
||||
(перезапись baseline не роняет доставку; checkpoint возвращает MAM).
|
||||
|
||||
Критическое уточнение 0.8.4-followup: **живой append больше НЕ fail-closed** — это
|
||||
и было корневой причиной seconds-уровневых `message-processing-slow` у Luma и
|
||||
непрерывных `mam-archive-skipped` на сервере пользователя. В `src/archive.rs`
|
||||
`recover_redo` теперь сам зареТирует неприменимый журнал при первом же сбое
|
||||
(ранняя проверка anchor по первым 96 байтам header до чтения кадров) и продолжит
|
||||
работу на синхронизированном native как Prosody, который вообще не хранит `.rredo`.
|
||||
Чтение сломанного журнала больше не стоит O(журнал) на каждый access: проверяется
|
||||
только header, неподключённый журнал удаляется один раз, последующие access быстры
|
||||
(см. `untrusted_redo_baseline_is_retired_once_and_recovers`). Полная коррупция
|
||||
header-checksum или неполный baseline по-прежнему блокируют startup (инвариант
|
||||
durability 0.8.3) — они НЕ матчатся `is_untrusted_redo` и остаются fail-closed.
|
||||
|
||||
Сравнение с 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` не снимать. Полная
|
||||
Операционный ремонт пользователя: с этим фиксом ручной `storage-checkpoint` для
|
||||
починки рассинхронизированного baseline больше не требуется — журнал
|
||||
зареТиров согласуется automatically при первом доступе, и append продолжает
|
||||
работу на скорости Prosody. Offline `storage-checkpoint CONFIG` остаётся
|
||||
доступным (и идемпотентным) для штатного durable handoff перед сменой writer.
|
||||
`--experimental` не снимать. Полная
|
||||
замена Prosody требует реального CI, внешней федерации, настоящих клиентов/push,
|
||||
deployment/UID/TLS, rollback и длительной нагрузки — см. COMPATIBILITY.md.
|
||||
@@ -182,4 +182,11 @@ in place»: каждый MAM-append падал и через `?` ронял sess
|
||||
доставке стала best-effort (storage-ошибка не роняет session и не роняет доставку;
|
||||
в лог — `mam-archive-skipped`), а `storage-checkpoint` получил ремонт непроверенного
|
||||
baseline: текущий синхронизированный native считается авторитетным и неприменимый
|
||||
журнал удаляется. Живой append остаётся fail-closed: журнал не удаляется молча.
|
||||
журнал удаляется.
|
||||
|
||||
С 0.8.4-followup живой append больше НЕ fail-closed: `recover_redo` при первом же
|
||||
неприменимом baseline читает только header и сам удаляет журнал, принимая synced
|
||||
native (как Prosody), восстанавливая append на скорости Prosody без секундных
|
||||
`message-processing-slow` и прекращая `mam-archive-skipped`. Полная коррупция
|
||||
header-checksum или неполный baseline по-прежнему блокируют startup (fail-closed,
|
||||
инвариант 0.8.3) и не матчатся `is_untrusted_redo`.
|
||||
@@ -78,20 +78,30 @@ handoff, `.rredo` перестаёт совпадать со своим anchor.
|
||||
Начиная с 0.8.4 MAM-архивация на трёх местах личной доставки (отправитель,
|
||||
получатель, входящая федерация) стала best-effort: при storage-ошибке исходная
|
||||
stanza всё равно маршрутизируется, обе сессии остаются живы, в лог пишется
|
||||
санитизированный `mam-archive-skipped`. Живой append остаётся fail-closed:
|
||||
непроверенный журнал не удаляется молча, а сохраняется для явного handoff.
|
||||
санитизированный `mam-archive-skipped`.
|
||||
|
||||
Ремонт выполняется той же командой offline handoff:
|
||||
Критическое уточнение (0.8.4-followup): живой append больше НЕ fail-closed.
|
||||
`recover_redo` при первом же untrusted-baseline сбое читает только 96-байтовый
|
||||
header (ранняя anchor-проверка до чтения/валидации кадров) и сам зареТирует
|
||||
неподключённый журнал (`retire_redo`), принимая синхронизированный native как
|
||||
Prosody. Это устраняет O(журнал) чтение+checksum на каждый access при больших
|
||||
сломанных журналах (секунды `message-processing-slow`) и возвращает append на
|
||||
скорость Prosody. Полная коррупция header-checksum или неполный baseline по-прежнему
|
||||
блокируют startup (инвариант 0.8.3): они не матчатся `is_untrusted_redo` и остаются
|
||||
fail-closed, чтобы не потерять committed redo frames без цели.
|
||||
|
||||
Ручной `storage-checkpoint` для этого больше не требуется; offline handoff
|
||||
остаётся идемпотентным способом штатного durable handoff перед сменой writer:
|
||||
|
||||
```bash
|
||||
rust-xmpp storage-checkpoint /etc/prosody/prosody.cfg.lua
|
||||
```
|
||||
|
||||
Теперь `prepare_rewrite` распознаёт непроверенный baseline (changed in place,
|
||||
`prepare_rewrite` по-прежнему распознаёт непроверенный baseline (changed in place,
|
||||
shorter, missing, journal exceeds bound), считает текущий durably-синхронизированный
|
||||
native авторитетным, синхронизирует его и удаляет неприменимый журнал. После этого
|
||||
MAM history снова читается, а новые append создадут свежий redo поверх нового
|
||||
baseline. Сверку совместимости native-формата см. в исходниках Prosody
|
||||
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-журнал устаревшим.
|
||||
|
||||
+14
-3
@@ -158,11 +158,15 @@ fn byte_limit_rotates_before_frame_count_limit() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_native_atomic_handoff_and_missing_baseline_fail_closed() {
|
||||
fn explicit_native_atomic_handoff_and_missing_baseline_never_drops_live_access() {
|
||||
let t = tempfile::tempdir().unwrap();
|
||||
append(t.path(), "old");
|
||||
let p = path(t.path());
|
||||
archive::checkpoint_all(t.path()).unwrap();
|
||||
// An external writer replaces the native file in place (Prosody `list_store`
|
||||
// rewrite), invalidating the committed redo baseline. On first access the
|
||||
// untrusted journal is retired and the synced native is adopted as
|
||||
// authoritative — exactly what Prosody sees (it has no redo sidecar).
|
||||
storage::atomic_write(
|
||||
&p,
|
||||
b"item({name='message';attr={};key='native';when=42});\n",
|
||||
@@ -171,6 +175,7 @@ fn explicit_native_atomic_handoff_and_missing_baseline_fail_closed() {
|
||||
assert_eq!(ids(t.path()), ["native"]);
|
||||
append(t.path(), "rust");
|
||||
assert_eq!(ids(t.path()), ["native", "rust"]);
|
||||
// A dirty, uncommitted native suffix is never surfaced.
|
||||
fs::OpenOptions::new()
|
||||
.append(true)
|
||||
.open(&p)
|
||||
@@ -178,9 +183,15 @@ fn explicit_native_atomic_handoff_and_missing_baseline_fail_closed() {
|
||||
.write_all(b"item(bad uncommitted);")
|
||||
.unwrap();
|
||||
assert_eq!(ids(t.path()), ["native", "rust"]);
|
||||
// The durable baseline cannot be reconstructed from suffix-only frames.
|
||||
// Once the untrusted journal has been retired (native adopted as
|
||||
// authoritative), externally removing the archive yields the empty history
|
||||
// Prosody would return — never a panic or a hang.
|
||||
fs::remove_file(&p).unwrap();
|
||||
assert!(archive::load(t.path(), "example.org", "alice").is_err());
|
||||
assert!(
|
||||
archive::load(t.path(), "example.org", "alice")
|
||||
.unwrap()
|
||||
.is_empty()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user