reindex: пересборка витрины проигрыванием журнала
- `healthlog reindex` собирает витрину из журнала (тела архива + учёт доставок) в ОТДЕЛЬНЫЙ файл базы, строго по `(received_at, id)`; рабочую базу читает без наката миграций и не трогает вовсе. Подмену делает человек при остановленном сервисе: переименование поверх открытого дескриптора портит базу молча. - Журналом считается архив, а не таблица доставок: тело без учётной записи заводится заново (метка из ULID, размер и хеш по распакованному телу), запись без тела переносится, но не сворачивается. Оракул сходимости встроен — два отпечатка и «объектов было/стало»; пустой журнал успехом не считается. - Прогон живого архива переехал на новый пакет: второго проигрывателя журнала в проекте не осталось, а его утверждение о ключе сна перестало быть константой, протухающей с каждой доставкой.
This commit is contained in:
@@ -312,6 +312,17 @@ func (s *Service) fail(ctx context.Context, deliveryID string, cause error, unco
|
||||
}
|
||||
}
|
||||
|
||||
// ReadBody читает тело из архива с той же границей размера, что и свёртка.
|
||||
//
|
||||
// Экспортировано ради пересборки: ей нужно прочесть тело, у которого ещё нет
|
||||
// учётной записи, чтобы посчитать размер и хеш. Своей копией чтения это делать
|
||||
// нельзя — граница обязана быть общей, иначе тело, принятое приёмом со `200`,
|
||||
// начнёт вечно отказывать на каждой пересборке, и договорённость «предел тот
|
||||
// же» ничем не проверяется.
|
||||
func (s *Service) ReadBody(rawPath string) ([]byte, error) {
|
||||
return s.readBody(rawPath)
|
||||
}
|
||||
|
||||
func (s *Service) readBody(rawPath string) ([]byte, error) {
|
||||
r, err := s.arch.Open(rawPath)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user