- секции `workouts` и `stateOfMind` покрыты разбором: тренировка лежит одной строкой вместе с маршрутом и внутренними рядами, запись — по ключу `род + id`; миграция 00007 заводит обе таблицы и возвращает в очередь `partial`-доставки с этими ключами - сущность заменяется целиком, но условно: приехавшая побеждает, если не теряет содержания сохранённой (множество ключей и длины верхнеуровневых массивов), а при равном содержании выигрывает версия из более поздней доставки ЖУРНАЛА — «побеждает приехавшая» было бы функцией порядка свёртки, и живая витрина расходилась бы с пересборкой молча - отпечаток витрины покрывает тренировки и записи и снимается одним снимком базы; отчёт `reindex` считает «было и стало» по каждой единице хранения
125 lines
3.3 KiB
JSON
125 lines
3.3 KiB
JSON
{
|
|
"data": {
|
|
"metrics": [
|
|
{
|
|
"name": "step_count",
|
|
"units": "count",
|
|
"data": [
|
|
{
|
|
"date": "2025-06-05 09:00:00 +0300",
|
|
"qty": 41.0,
|
|
"source": "Device A"
|
|
},
|
|
{
|
|
"date": "2025-06-05 09:01:00 +0300",
|
|
"qty": 17.0,
|
|
"source": "Device A"
|
|
},
|
|
{
|
|
"date": "2025-06-05 09:02:00 +0300",
|
|
"qty": 82.0,
|
|
"source": "Device A"
|
|
},
|
|
{
|
|
"date": "2025-06-05 09:03:00 +0300",
|
|
"qty": 5.0,
|
|
"source": "Device A"
|
|
},
|
|
{
|
|
"date": "2025-06-05 09:04:00 +0300",
|
|
"qty": 63.0,
|
|
"source": "Device A"
|
|
},
|
|
{
|
|
"date": "2025-06-05 09:05:00 +0300",
|
|
"qty": 28.0,
|
|
"source": "Device A"
|
|
},
|
|
{
|
|
"date": "2025-06-05 09:06:00 +0300",
|
|
"qty": 94.0,
|
|
"source": "Device A"
|
|
},
|
|
{
|
|
"date": "2025-06-05 09:07:00 +0300",
|
|
"qty": 12.0,
|
|
"source": "Device A"
|
|
},
|
|
{
|
|
"date": "2025-06-05 09:08:00 +0300",
|
|
"qty": 71.0,
|
|
"source": "Device A"
|
|
},
|
|
{
|
|
"date": "2025-06-05 09:09:00 +0300",
|
|
"qty": 36.0,
|
|
"source": "Device A"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"workouts": [
|
|
{
|
|
"id": "00000000-0000-0000-0000-000000000001",
|
|
"name": "В помещении Ходьба",
|
|
"start": "2025-06-05 08:00:00 +0300",
|
|
"end": "2025-06-05 08:30:00 +0300",
|
|
"duration": 1800,
|
|
"heartRateData": [
|
|
{
|
|
"date": "2025-06-05 08:00:07 +0300",
|
|
"Min": 91.0,
|
|
"Avg": 94.5,
|
|
"Max": 98.0,
|
|
"units": "count/min"
|
|
},
|
|
{
|
|
"date": "2025-06-05 08:00:21 +0300",
|
|
"Min": 93.0,
|
|
"Avg": 95.5,
|
|
"Max": 99.0,
|
|
"units": "count/min"
|
|
}
|
|
],
|
|
"route": [
|
|
{
|
|
"lat": 10.0,
|
|
"lon": 20.0,
|
|
"altitude": 30.0,
|
|
"timestamp": "2025-06-05 08:00:07 +0300"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"stateOfMind": [
|
|
{
|
|
"id": "00000000-0000-0000-0000-000000000002",
|
|
"start": "2025-06-05T05:12:33Z",
|
|
"end": "2025-06-05T05:12:33Z",
|
|
"kind": "momentary_emotion",
|
|
"valence": 0.25,
|
|
"labels": [
|
|
"slightly_pleasant"
|
|
],
|
|
"associations": []
|
|
}
|
|
],
|
|
"ecg": [
|
|
{
|
|
"id": "00000000-0000-0000-0000-000000000003",
|
|
"start": "2025-06-05 07:00:00 +0300",
|
|
"classification": "sinusRhythm"
|
|
}
|
|
],
|
|
"symptoms": [
|
|
{
|
|
"id": "00000000-0000-0000-0000-000000000004",
|
|
"start": "2025-06-05 06:00:00 +0300",
|
|
"name": "Головная боль",
|
|
"severity": "mild"
|
|
}
|
|
]
|
|
},
|
|
"_comment": "Рукотворная фикстура: одна доставка со всеми родами секций сразу — покрытыми (metrics, workouts, stateOfMind) и непокрытыми (ecg, symptoms). Живой поток такого не даёт: автоматизация HAE шлёт одну секцию за раз."
|
|
}
|