store: при равной полноте точек побеждает пришедшая доставка
- байтовый порядок канонических форм остался тай-брейком только внутри одной доставки: на живом корпусе он решал 98,8% спорных координат и системно хранил меньшее значение, из-за чего step_count терял род и verify:archive был красным - правило перестало быть коммутативным осознанно, поэтому порядок свёртки приведён к журнальному: проход воркера прекращается на отложенной доставке, а свёртка вне порядка журнала пишет WARN - заведены счётчики PointsHeld и PointsErased — удержание полнотой и единственное направление, в котором правило теряет содержание
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -514,3 +515,45 @@ func TestFoldОтказРазбораНеПодделываетСчётчикП
|
||||
t.Errorf("отказ разбора записал %d пропусков как измерение", *after.SkippedEntities)
|
||||
}
|
||||
}
|
||||
|
||||
// Удержание точки правилом полноты доезжает до итога свёртки и до лога:
|
||||
// счётчик отдельный от перезаписей, координаты — без значений.
|
||||
//
|
||||
// Тела строятся из РЕАЛЬНОГО пакета: у второй доставки из каждой точки убран
|
||||
// `qty`. Так получается ровно тот вход, на котором пришедшая точка теряет
|
||||
// содержание сохранённой, — единственный случай, когда под новым тай-брейком
|
||||
// она вообще проигрывает.
|
||||
func TestFoldУдержаниеТочкиСчитаетсяОтдельно(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
f, arch, st := newFold(t)
|
||||
ctx := context.Background()
|
||||
|
||||
rich := fixture(t, "minute.json")
|
||||
poor := regexp.MustCompile(`"qty"\s*:\s*[-0-9.eE+]+\s*,\s*`).ReplaceAll(rich, nil)
|
||||
if len(poor) == len(rich) {
|
||||
t.Fatal("фикстура не содержит qty — обеднить тело нечем")
|
||||
}
|
||||
|
||||
deliver(t, arch, st, "d1", "Minutes", "auto-1", rich)
|
||||
if _, err := f.Fold(ctx, "d1"); err != nil {
|
||||
t.Fatalf("первая свёртка: %v", err)
|
||||
}
|
||||
|
||||
deliver(t, arch, st, "d2", "Minutes", "auto-1", poor)
|
||||
stats, err := f.Fold(ctx, "d2")
|
||||
if err != nil {
|
||||
t.Fatalf("вторая свёртка: %v", err)
|
||||
}
|
||||
|
||||
if stats.PointsHeld == 0 {
|
||||
t.Fatalf("удержаний 0: обеднённая точка вытеснила измерение, %+v", stats.MergeStats)
|
||||
}
|
||||
if len(stats.PointsHeldAt) == 0 {
|
||||
t.Error("координат удержания нет: счётчик без адреса неразбираем")
|
||||
}
|
||||
if stats.PointsHeld > stats.Overwrites {
|
||||
t.Errorf("удержаний %d при %d перезаписях: удержание — частный случай столкновения",
|
||||
stats.PointsHeld, stats.Overwrites)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user