Spaces:
Running
Загрузка данных и кеширование
Этот документ описывает текущую реализацию загрузки данных и кеширования во frontend HiveTrace Guardrail Leaderboard.
У реализации три основные цели:
- хранить приватный Hugging Face token только на сервере SvelteKit;
- не скачивать и не адаптировать повторно неизменившиеся payload-файлы bucket;
- ускорить повторные переходы между страницами и сохранить предсказуемое окно актуальности данных.
Архитектура
Browser
-> SvelteKit page или __data.json request
-> Node process в Hugging Face Space
-> private Hugging Face bucket
-> latest/manifest.json
-> payload-файлы, указанные в manifest
Браузер не обращается к приватному bucket напрямую. Все запросы в bucket выполняет сервер
SvelteKit с помощью server-only переменной HF_TOKEN.
Источник данных
Bucket настраивается runtime-переменными:
HF_TOKEN=<private read token>
HF_BUCKET_ID=hivetrace/leaderboard_frontend_v2
HF_BUCKET_PREFIX=latest
HF_BUCKET_REQUEST_TIMEOUT_MS=60000
HF_BUCKET_REQUEST_RETRIES=2
HF_BUCKET_ENDPOINT=https://huggingface.co
HF_BUCKET_ENDPOINT, HF_BUCKET_REQUEST_TIMEOUT_MS и HF_BUCKET_REQUEST_RETRIES опциональны.
Выше указаны их значения по умолчанию.
HF_BUCKET_CACHE_TTL_MS по-прежнему управляет обычным in-memory кешем manifest и прямым helper
Tools snapshot. Основной поток page data для Ranking, Details и Visualizations после промаха
браузерного кеша явно обновляет manifest, поэтому эта переменная не добавляет еще одну задержку
актуальности при обычных переходах по страницам.
Manifest как указатель версии
latest/manifest.json является единственным указателем версии для frontend. Основные поля:
snapshot_id: идентификатор опубликованного набора данных;files: пути ко всем payload-файлам;hashes: SHA-256 хеши payload-файлов;schema_version: версия контракта bucket;- количества моделей, групп и датасетов для валидации.
Frontend определяет изменение payload по snapshot_id. Каждая новая публикация обязана иметь
новый уникальный snapshot_id.
Изменение payload-файлов или хешей без изменения snapshot_id не поддерживается. В таком случае
frontend считает snapshot прежним и может использовать старый in-memory payload до перезапуска
процесса Space.
Маршруты и payload-файлы
| Маршрут | Server loader | Данные bucket |
|---|---|---|
/ |
getHfBucketRankingState() |
catalog, leaderboard и details matrix |
/details |
getHfBucketDetailsState() |
catalog, leaderboard и details matrix |
/tools |
getHfBucketToolsState() |
catalog, leaderboard, drilldown index, radar, scatter, heatmap, grouped bars, Pareto, performance и robustness |
/methodology |
нет bucket page loader | payload из bucket не используется |
Ranking также использует details matrix, потому что статус модели partial вычисляется по
условию metrics_evaluated_samples < sample_count.
Корневой +layout.server.ts отдельно читает manifest и возвращает публичный статус bucket:
дату snapshot, количество моделей и другие общие поля. Этот статус использует обычный кеш
manifest. Он является метаданными layout и не управляет актуальностью page data.
Клиентская навигация
SvelteKit перехватывает внутренние ссылки главного меню и запрашивает данные маршрутов через endpoint вида:
/__data.json
/details/__data.json
/tools/__data.json
Локализованные варианты также распознаются, например /ru/details/__data.json.
Оптимизация response в src/hooks.server.ts применяется только к этим трем page-data
маршрутам. Она не применяется к Methodology, статическим файлам, ошибкам и произвольным API
response.
Браузерный кеш
Успешный page-data response получает заголовок:
Cache-Control: private, max-age=300
Это означает:
- браузер может повторно использовать response маршрута в течение пяти минут;
- response не попадает в общий CDN или shared proxy cache;
- окно
stale-while-revalidateотсутствует; - после пяти минут следующий переход обязан обратиться к серверу SvelteKit до отрисовки маршрута.
Кеш привязан к URL response, включая внутренние query-параметры SvelteKit. Поэтому Ranking, Details и Visualizations имеют отдельные записи браузерного кеша.
Уже открытая страница сама не обновляется. Новые данные применяются при следующем переходе или полной перезагрузке страницы.
Gzip-сжатие
Тот же hook сжимает page-data response, когда выполнены все условия:
- response успешный и содержит body;
- заявленный размер не меньше 1 024 bytes;
- клиент поддерживает
gzip.
Сжатый response содержит:
Content-Encoding: gzip
Vary: Accept-Encoding
Content-Length удаляется, потому что сжатый body передается потоком. Клиенты без поддержки
gzip получают исходный body с тем же приватным кешем на пять минут.
Примерные измеренные размеры для текущего набора данных:
| Данные маршрута | Без сжатия | Gzip |
|---|---|---|
| Ranking | 171 KB | 58 KB |
| Details | 643 KB | 158 KB |
| Visualizations | 709 KB | 122 KB |
Размеры зависят от содержимого bucket и будут меняться при добавлении моделей и датасетов.
Поток server request
Если в браузере нет свежего page-data response, сервер выполняет следующие шаги:
- Page loader вызывает соответствующую state-функцию Ranking, Details или Tools.
- State-функция вызывает
fetchBucketRankingSnapshot({ refreshManifest: true }). refreshManifest: trueобходит обычный TTL manifest и читает актуальный небольшойmanifest.jsonиз Hugging Face.- Если полученный
snapshot_idсовпадает с in-memory ranking snapshot, catalog и leaderboard используются повторно без скачивания payload. - Если
snapshot_idизменился, catalog и leaderboard скачиваются параллельно, проверяются их хеши и schema, после чего ranking snapshot заменяется. - Данные конкретного маршрута переиспользуются или пересобираются для нового
snapshot_id. - SvelteKit сериализует адаптированные данные маршрута, а server hook добавляет приватный кеш и gzip-сжатие.
Разница между параметрами snapshot:
refreshManifest: trueвсегда проверяет manifest, но переиспользует payload при неизменномsnapshot_id;forceRefresh: trueтакже отключает переиспользование payload и пересобирает ranking snapshot.
Обычные переходы по страницам используют refreshManifest, а не forceRefresh.
In-memory кеши сервера
Все серверные кеши хранятся в памяти работающего Node process. Они принадлежат одному replica Space и очищаются при перезапуске, засыпании контейнера или новом deploy.
Кеш manifest
src/lib/server/hf-bucket/cache.ts хранит:
- распарсенный manifest;
- время его получения;
- время истечения кеша;
- один общий in-flight request manifest.
Обычные callers используют HF_BUCKET_CACHE_TTL_MS, по умолчанию пять минут. Page-data refresh
использует принудительное чтение manifest, описанное выше. Одновременные принудительные проверки
подключаются к одному in-flight request, если пересекаются по времени.
Ranking snapshot
Ranking snapshot содержит manifest, catalog и leaderboard. Он кешируется по snapshot_id.
Одновременные загрузки одного snapshot используют общий promise. In-flight request также
привязан к snapshot_id, поэтому запрос нового опубликованного snapshot не использует по ошибке
загрузку предыдущего snapshot.
Details snapshot
Details snapshot добавляет details_matrix к ranking snapshot и кешируется по snapshot_id.
Этот кеш общий для Ranking и Details. Ranking использует matrix для определения partial, поэтому
после открытия Ranking страница Details не скачивает и не валидирует details_matrix повторно.
Одновременные запросы одного details snapshot также используют общий promise.
Адаптированные Ranking и Details
Готовые для UI объекты Ranking и Details кешируются по snapshot_id. Если manifest не изменился,
сервер возвращает уже адаптированный объект. Новый snapshot парсится, валидируется и адаптируется
один раз на Node process.
Visualizations snapshot и адаптированный Tools dataset
Для нового snapshot файлы визуализаций скачиваются параллельно. Raw visualization snapshot и
адаптированный Tools dataset кешируются отдельно по snapshot_id.
Прямой helper getHfBucketToolsSnapshot() сохраняет свой быстрый путь на основе TTL. Страница
/tools использует state-путь, который обновляет manifest после промаха браузерного кеша.
Валидация
Payload используется повторно только после проверки версии manifest. Новый payload проходит:
- JSON parsing;
- schema parsing;
- проверку SHA-256 при наличии хеша;
- сверку количеств из manifest;
- проверку ссылок на модели, группы и датасеты;
- проверку полноты matrix и дублирующихся пар;
- проверку ссылок в данных визуализаций.
Ошибка валидации обрабатывается так же, как другая ошибка обновления.
Гарантия актуальности данных
Предположим, что корректный новый snapshot опубликован в момент T, а bucket доступен.
Response маршрута уже находится в браузерном кеше
Старый response может использоваться до истечения его индивидуального max-age в пять минут.
Первый переход на этот маршрут после истечения кеша читает свежий manifest. Если snapshot_id
изменился, тот же переход ожидает загрузку нового payload и получает новые данные.
Ожидаемая гарантия:
Не позднее первого перехода после истечения пятиминутного браузерного кеша маршрута пользователь получает новый snapshot.
Дополнительного окна выдачи stale response нет.
Response маршрута отсутствует в браузерном кеше
Переход сразу обращается к серверу и проверяет manifest. Если новый payload уже находится в памяти сервера, он используется повторно. Иначе переход ожидает скачивание и адаптацию нового snapshot.
Полная перезагрузка страницы
Пятиминутная политика применяется к SvelteKit navigation response __data.json. Обычный полный
HTML request не покрывается этим page-data кешем и снова запускает server page loader.
Исключения
Пятиминутное ожидание неприменимо, если:
- Hugging Face или сеть недоступны;
- новый payload не проходит parsing, проверку хеша или валидацию;
- publisher повторно использовал старый
snapshot_id; - manifest опубликован раньше, чем стали доступны все указанные в нем файлы.
Поведение при ошибках
Кеш также обеспечивает устойчивость:
- если refresh завершился ошибкой и готовые данные маршрута существуют, сервер возвращает кеш;
- если новый manifest доступен, но новый payload невалиден или недоступен, route state становится
stale, и UI может показать предупреждение; - если пригодного кеша нет, маршрут возвращает состояние
unavailableс пустым fallback dataset; - одновременные запросы используют общую in-flight работу и не дублируют загрузку bucket.
Важная деталь текущей реализации: если принудительное чтение manifest завершилось ошибкой, но в
памяти есть предыдущий manifest, слой manifest может вернуть его как stale. После этого сервер
продолжит выдавать предыдущие route data. Текущий route state не во всех случаях пробрасывает
именно этот fallback manifest как видимое предупреждение stale.
Публикация нового snapshot
Producer должен выполнять публикацию атомарно с точки зрения frontend:
- Сгенерировать все payload-файлы.
- По возможности использовать immutable или snapshot-specific пути.
- Рассчитать и записать SHA-256 хеши.
- Загрузить каждый payload-файл и проверить, что он доступен для чтения.
- Создать manifest с новым уникальным
snapshot_id, корректными путями, хешами, количествами и версией schema. - Последним загрузить
latest/manifest.json.
Публикация manifest последним не позволяет frontend увидеть новую версию, которая ссылается на еще недоступные файлы.
Cold start и replicas
После перезапуска или cold start Space in-memory snapshot отсутствует. Первый request должен прочитать manifest и все payload-файлы, необходимые выбранному маршруту. Следующие запросы используют подготовленные данные повторно.
Если Space работает с несколькими replicas, каждая имеет собственный кеш в памяти и прогревается независимо. Браузерный кеш остается локальным для каждого пользователя.
Операционная проверка
Для проверки заголовков page-data response нужен авторизованный запрос к Space:
curl -sS \
-H "Authorization: Bearer $HF_TOKEN" \
-H "Accept-Encoding: gzip" \
-D - \
-o /dev/null \
"https://<space-domain>/details/__data.json"
Ожидаемые заголовки:
Cache-Control: private, max-age=300
Content-Encoding: gzip
Vary: Accept-Encoding
curl не воспроизводит navigation cache браузера без отдельной настройки собственного кеша.
Поэтому повторные curl-запросы доходят до сервера и могут повторно запускать проверку manifest.
При проверке новой публикации нужно убедиться, что:
- manifest содержит новый
snapshot_id; - каждый указанный файл существует;
- хеши соответствуют опубликованному содержимому;
- в логах Space нет ошибок валидации bucket;
- первый переход после истечения браузерного кеша показывает новый snapshot.
Карта реализации
| Ответственность | Файл |
|---|---|
| HTTP client bucket и server-only token | src/lib/server/hf-bucket/client.ts |
| Обычный кеш manifest и in-flight request | src/lib/server/hf-bucket/cache.ts |
| Загрузка и валидация Ranking snapshot | src/lib/server/hf-bucket/ranking-snapshot.ts |
| Общий Details snapshot | src/lib/server/hf-bucket/details-snapshot.ts |
| Загрузка Visualization snapshot | src/lib/server/hf-bucket/tools-snapshot.ts |
| Кеш адаптированного Ranking | src/lib/server/hf-bucket/ranking-cache.ts |
| Кеш адаптированного Details | src/lib/server/hf-bucket/details-cache.ts |
| Raw и адаптированный кеш Tools | src/lib/server/hf-bucket/tools-cache.ts |
| Заголовки браузерного кеша и gzip | src/hooks.server.ts |
| Публичный статус bucket в root layout | src/routes/+layout.server.ts |
| Оркестрация маршрутов | src/routes/+page.server.ts, src/routes/details/+page.server.ts, src/routes/tools/+page.server.ts |