Document unreconciled DM media expiry after SQL failure
This commit is contained in:
1 parent
3dc5eb502d
commit
dda4a780e3
3 files changed
+77
-1
No files matched your search
@@ -380,3 +380,63 @@ burst1/1,load8/8 PASS,134217728байт,exit0,175с. Строгие273 JSON/9452
|
||||
Санитайзеры после rebase не повторялись:DM runtime не менялся,общий call_audio.h
|
||||
в upstream изменяет только комментарий;новые платформенные Android callers этим
|
||||
DM-профилем не проверяются. Upstream задачи/отчёты Android mute сохранены целиком.
|
||||
|
||||
10. Продолжение mailbox: SQL-ошибка оставляет завершённое TTL-назначение активным
|
||||
|
||||
База продолжения:3dc5eb502db6964fc6467385cc65db9d1df83c44,рабочее дерево было чистым.
|
||||
Повторно сверены dm_mailbox.c/.h,dm_mailbox_media.c/.h и относящиеся к квитанциям,
|
||||
контролю и TTL функции dm_media. Приём PUT проверяет точное тело,роль S и общую
|
||||
группу;квитанция текста и удаление pending объединены транзакцией. Это чтение
|
||||
соответствующих путей,не полная проверка всех SQL/allocator/платформенных отказов.
|
||||
|
||||
Подтверждён новый дефект:dm_mailbox_media_recv в EXPIRED сначала делает
|
||||
UPDATE dm_media_holders SET released=1,затем отдельным statement обновляет job:
|
||||
holder=0,stored=0,expired=1,retry_at=0. При отказе второго statement первое изменение
|
||||
остаётся в БД. Таймер при недоступном B видит прежние holder и stored=1,поэтому
|
||||
не выбирает нового M,не повторяет STORE и не сверяет expires с текущим временем.
|
||||
На M custody уже удалена;dm_custody_done хранит tombstone,но таймер эту таблицу
|
||||
не сканирует и не повторяет уведомление EXPIRED сам по себе.
|
||||
|
||||
Стенд:/tmp/dm-expiry-audit.c/.mk — отдельный вариант штатного test_dm_media.
|
||||
Настоящие4 ядра A/B/S/M с подписанными мемберскими/административными блоками,
|
||||
разными SQLite,реальными UDP/BGP/file_transfer и прежними проверками доставки.
|
||||
Штатные quota-fault проверки идут в обоих прогонах одинаково;новая инъекция только
|
||||
на S и только на UPDATE завершения EXPIRED,однократно SQLITE_IOERR в sqlite3_step.
|
||||
Рабочие C,штатные тесты,объекты и libutun не подменялись;данные только в/tmp.
|
||||
|
||||
Оба прогона сначала проходят прямую доставку,offline custody и восстановление
|
||||
S/M с выключенным A,побайтную доставку B и удаление промежуточной копии.
|
||||
Затем B снова выключен;для третьего файла настроен TTL1с на M. M успевает принять
|
||||
98385байт ciphertext,подтвердить хранение,по TTL удалить custody и послать EXPIRED.
|
||||
|
||||
Контроль без новой инъекции:phase9 PASS,exit0,allocations0->0. Для seq3 на S
|
||||
holder0,stored0,expired1;назначение released1. На M нет custody,есть expired tombstone.
|
||||
Fault:UPDATE завершается rc10,hit1,ошибка логируется вместе с точным SQL. После
|
||||
ещё16 календарных секунд тестовых часов и нескольких успешных повторов PUT:
|
||||
на S holder723190674248656275,stored1,expired0,expires1793032708,receiptNULL,body сохранён;
|
||||
для того же UUID E20AC64A2660882CE73D68D48E2AFFA0 назначение этого M released1.
|
||||
На M custody0,expired tombstone1. Phase8 FAIL,exit1,allocations0->0.
|
||||
В runtime released=2 считает также прежнее успешно доставленное назначение;
|
||||
независимый readonly SQL JOIN отдельно подтвердил released1 для проверяемого UUID.
|
||||
Остановка/освобождение owners штатные,не маскируют сохранённое расхождение.
|
||||
|
||||
Окно отсутствия восстановления16с проверено исполнением;отсутствие пути восстановления
|
||||
при продолжающемся offline B следует также из ветки таймера. Restart после этой
|
||||
инъекции,возврат B и дополнительный storage не запускались;потеря до TTL не заявляется.
|
||||
Это нарушение согласованности durable состояния после SQL-отказа,а не ошибка самого
|
||||
удаления по TTL:копия M удалена в предусмотренный срок.
|
||||
|
||||
Направление исправления:идемпотентный восстанавливаемый переход EXPIRED с согласованным
|
||||
состоянием job/holder;подтверждённое назначение проверять таймером по сохранённому expires.
|
||||
Одного BEGIN/COMMIT вокруг двух UPDATE недостаточно:при rollback событие уже потреблено,
|
||||
а M не повторит EXPIRED после удаления custody. Нужны отказные проверки обоих statement,
|
||||
commit и восстановления после restart;поздний STORED не должен отменить завершение.
|
||||
Сходная последовательность REJECT/DELETE_ACK замечена при чтении,но отдельный runtime
|
||||
её отказов в этом продолжении не выполнен. Конкретная реализация пока не менялась.
|
||||
|
||||
Сборка отдельного стенда PASS. Логи:/tmp/dm-expiry-audit-{build,control,fault,validation}.log;
|
||||
полные журналы сохранены,DM-выборки без транспортного шума — *-control-dm.log/*-fault-dm.log.
|
||||
Прежний check205/санитайзеры относятся к исправлению UTF-8 и не покрывали этот отказ.
|
||||
Новые fullcheck/sanitizer/GUI/Android/Windows/FreeBSD проверки не выполнялись.
|
||||
По AGENTS.md:10 дальнейший аудит остановлен;задача открыта в doc/tasks.md.
|
||||
В продолжении только комментарий контракта и отчёт/задача;частичные отметки сохранены.
|
||||
@@ -4,6 +4,20 @@
|
||||
|
||||
## Текущие задачи
|
||||
|
||||
[ ] **DM media: восстанавливать завершение TTL после SQL-отказа при EXPIRED** — подтверждено 26.10.2026.
|
||||
На S обработчик сначала сохраняет released=1, затем отдельно сбрасывает holder/stored и ставит expired=1.
|
||||
Однократный SQLITE_IOERR второго UPDATE оставляет stored=1,holder=M,expired=0 при уже удалённом файле M.
|
||||
Настоящие A/B/S/M, UDP/file_transfer и TTL1с:контроль phase9 PASS;отказ phase8 FAIL после16с повторов,
|
||||
allocations0->0 в обоих прогонах. Независимое readonly чтение обеих БД подтвердило точный UUID/состояния.
|
||||
Существующий таймер при offline B не пересматривает stored по expires и не повторяет STORE;
|
||||
M уже удалил custody и сохранил tombstone, поэтому повтор EXPIRED от его таймера не возникает.
|
||||
Нужен идемпотентный восстанавливаемый переход и сверка подтверждённых назначений по сохранённому expires;
|
||||
одной транзакции недостаточно, если EXPIRED уже потреблён и последующее событие не придёт.
|
||||
Добавить отказы обоих UPDATE/commit, повтор/restart, поздний STORED и корректное удаление без ложных квитанций.
|
||||
Стенд /tmp/dm-expiry-audit.c/.mk;логи /tmp/dm-expiry-audit-{build,control,fault,validation}.log.
|
||||
Подробности: [dm_audit_findings.txt](dm_audit_findings.txt),раздел10. По AGENTS.md:10 аудит остановлен;
|
||||
runtime и штатные тесты не менялись, остальные отказные ветки REJECT/DELETE_ACK ещё не проверены отдельно.
|
||||
|
||||
[+] **DM: сохранять границы UTF-8 при усечении имени собеседника** — исправлено 26.10.2026.
|
||||
Единый предел DM_PEER_NAME_MAX=63 байта; создание, загрузка, входящее автосоздание и JSON
|
||||
копируют только целые code points. Повреждённый суффикс отбрасывается с WARN и точным смещением.
|
||||
|
||||
@@ -24,7 +24,9 @@ int dm_mailbox_media_register(struct dm_mb_media* media, uint64_t group, uint64_
|
||||
/* После проверки router-подписи и размера команды в dm_media: group/source — доверенные поля router.
|
||||
* body заимствован на время вызова; RECEIPT=152, STORED=24, DELETE_ACK/EXPIRED=16, REJECT=17 байт.
|
||||
* STORED/REJECT/ACK относятся к сохранённому назначению M; RECEIPT проверяется отдельно подписью B.
|
||||
* SQL-ошибки оставляют задачу для повторов; отдельные обновления здесь не объединены в транзакцию. */
|
||||
* SQL-ошибки логируются; отдельные обновления здесь не объединены в транзакцию.
|
||||
* Известный дефект: отказ сброса job после EXPIRED оставляет stored/holder при released=1;
|
||||
* пока B offline, таймер не восстанавливает переход. См. doc/dm_audit_findings.txt, раздел10. */
|
||||
void dm_mailbox_media_recv(struct dm_mb_media* media, uint64_t group, uint64_t source,
|
||||
uint8_t cmd, const uint8_t* body, size_t len);
|
||||
/* Проверить 152-байтовую квитанцию и попытаться отправить доступным S общей группы.
|
||||
|
||||
Reference in new issue
Block a user