feat: разбор и хранение тренировок и состояния разума
- секции `workouts` и `stateOfMind` покрыты разбором: тренировка лежит одной строкой вместе с маршрутом и внутренними рядами, запись — по ключу `род + id`; миграция 00007 заводит обе таблицы и возвращает в очередь `partial`-доставки с этими ключами - сущность заменяется целиком, но условно: приехавшая побеждает, если не теряет содержания сохранённой (множество ключей и длины верхнеуровневых массивов), а при равном содержании выигрывает версия из более поздней доставки ЖУРНАЛА — «побеждает приехавшая» было бы функцией порядка свёртки, и живая витрина расходилась бы с пересборкой молча - отпечаток витрины покрывает тренировки и записи и снимается одним снимком базы; отчёт `reindex` считает «было и стало» по каждой единице хранения
This commit is contained in:
+12
-11
@@ -548,10 +548,11 @@ func FuzzParse(f *testing.F) {
|
||||
})
|
||||
}
|
||||
|
||||
// Половина живого потока состоит из непокрытых секций целиком (48 доставок из
|
||||
// 99: workouts и stateOfMind). Без списка они неотличимы от разобранной
|
||||
// доставки с пустой секцией метрик, и ретеншен, ориентируясь на статус, срезал
|
||||
// бы тела, которые для stateOfMind единственный источник.
|
||||
// Непокрытая секция неотличима от разобранной доставки с пустой секцией
|
||||
// метрик, если её не назвать: ретеншен, ориентируясь на статус, срезал бы
|
||||
// тела, которые для секций без экспорта Apple единственный источник. С тех пор
|
||||
// как workouts и stateOfMind стали покрытыми, роль непокрытой в фикстуре
|
||||
// играют секции, которых поток ещё не приносил.
|
||||
func TestParseПеречисляетНепокрытыеСекции(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -560,7 +561,7 @@ func TestParseПеречисляетНепокрытыеСекции(t *testing.
|
||||
t.Fatalf("разбор: %v", err)
|
||||
}
|
||||
|
||||
want := []string{"stateOfMind", "workouts"}
|
||||
want := []string{"ecg", "symptoms"}
|
||||
if !slices.Equal(res.Uncovered, want) {
|
||||
t.Errorf("непокрытые %v, ожидались %v", res.Uncovered, want)
|
||||
}
|
||||
@@ -578,11 +579,11 @@ func TestParseНепокрытыеСекцииГраницыИДетермини
|
||||
t.Run("доставка из одной непокрытой секции", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
res, err := hae.Parse([]byte(`{"data":{"stateOfMind":[{"x":1}]}}`), hae.Meta{})
|
||||
res, err := hae.Parse([]byte(`{"data":{"ecg":[{"x":1}]}}`), hae.Meta{})
|
||||
if err != nil {
|
||||
t.Fatalf("разбор: %v", err)
|
||||
}
|
||||
if !slices.Equal(res.Uncovered, []string{"stateOfMind"}) {
|
||||
if !slices.Equal(res.Uncovered, []string{"ecg"}) {
|
||||
t.Errorf("непокрытые %v", res.Uncovered)
|
||||
}
|
||||
if len(res.Points) != 0 {
|
||||
@@ -609,11 +610,11 @@ func TestParseНепокрытыеСекцииГраницыИДетермини
|
||||
t.Parallel()
|
||||
|
||||
bodies := []string{
|
||||
`{"data":{"workouts":[],"stateOfMind":[],"ecg":[]}}`,
|
||||
`{"data":{"ecg":[],"workouts":[],"stateOfMind":[]}}`,
|
||||
`{"data":{"stateOfMind":[],"ecg":[],"workouts":[],"ecg":[]}}`,
|
||||
`{"data":{"symptoms":[],"medications":[],"ecg":[]}}`,
|
||||
`{"data":{"ecg":[],"symptoms":[],"medications":[]}}`,
|
||||
`{"data":{"medications":[],"ecg":[],"symptoms":[],"ecg":[]}}`,
|
||||
}
|
||||
want := []string{"ecg", "stateOfMind", "workouts"}
|
||||
want := []string{"ecg", "medications", "symptoms"}
|
||||
for _, b := range bodies {
|
||||
res, err := hae.Parse([]byte(b), hae.Meta{})
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user