GitHub запустил API для истории звезд репозиториев

GitHub представил новый API для истории звёзд репозиториев, который позволяет получать агрегированные данные без раскрытия личностей пользователей и снижает нагрузку на базу данных.

Раньше поддерживающим репозиториев приходилось собирать кривую роста по звёздам через GET /repos/{owner}/{repo}/stargazers. Инструменты запрашивали страницы со списком пользователей, которые поставили звезду, сохраняли время действия и отбрасывали имена. Это создавало две проблемы: открытые списки звёзд использовались для спама и фишинга, а база данных для популярных репозиториев обрабатывала тысячи записей ради одной страницы.

Для защиты пользователей GitHub сначала ограничил доступ к спискам поставивших звезду и наблюдателей, оставив их только администраторам и участникам репозиториев. Запросы без прав стали возвращать пустой ответ или 403 Forbidden. Однако это остановило работу инструментов, которые строили графики по истории звёзд и использовали эти данные как приблизительный сигнал интереса к проекту до и после релизов или анонсов.

Команда GitHub обсудила ситуацию с поддерживающими и авторами инструментов, например Star History. Выяснилось, что нужны были даты и суммарные значения, а не имена пользователей. Это позволило спроектировать новый агрегирующий endpoint, который отражает главное требование: получение динамики изменения числа звёзд с полезным временным шагом.

Изначально API GET /repos/{owner}/{repo}/stargazers создавался, чтобы отвечать на вопрос «кто поставил звезду». Модель данных по звёздам хранила текущий набор пользователей, которые отметили репозиторий, но не служила журналом событий. Если пользователь убирал звезду, запись удалялась. Для популярных проектов, таких как react/react с примерно 251 000 звёзд, для построения полной кривой роста требовалось около 2 511 запросов по 100 записей, что часто упиралось в лимиты и вело к выборочной выборке страниц.

Из-за ошибки в пагинации каждый запрос к списку звёзд сначала пересчитывал общее число звёзд, чтобы определить количество страниц, даже если клиент получал только одну страницу. Для репозиториев с большим числом звёзд это означало многократный пересчёт тысяч строк. За неделю до ограничения доступа было зафиксировано почти 37 000 медленных таких запросов со средним временем около 3 секунд, а защитные механизмы базы данных прервали свыше 1 000 из них, что приводило к тайм-аутам.

После ограничения доступа к старому endpoint число запросов к спискам звёзд в базе данных сократилось примерно на 60%, а время, затраченное на подсчёты, уменьшилось примерно на 80%. Это снизило нагрузку, но оставило задачу удобного и безопасного доступа к истории звёзд.

Первое техническое решение GitHub заключалось в том, чтобы продолжать хранить по одной записи на каждую звезду и возвращать поле времени starred_at без идентификатора пользователя для клиентов без прав участника. Это закрывало утечку идентичностей и сохраняло совместимость с существующими инструментами, но заставляло клиентов по‑прежнему постранично обрабатывать тысячи записей и опиралось на модель, спроектированную под вывод людей, а не трендов.

Следующим шагом стала агрегация: вместо одной строки на каждую звезду запрос мог группировать звёзды по дням или неделям и пагинировать уже агрегированные «корзины». Однако стандартный SQL-подход сначала отбирал все звёзды репозитория, группировал, сортировал группы, и только потом применял LIMIT и OFFSET. Для популярных репозиториев это по‑прежнему означало дорогостоящую обработку большого числа строк ради небольшой выборки.

Для react/react чтение полной истории таким способом потребовало бы обработки около 6 млн строк: каждый из 24 запросов проходил бы по всем звёздам. Чтобы снизить стоимость, нужно было сокращать объём данных до начала агрегации, а не только размер ответа.

В результате GitHub реализовал новый endpoint, который пагинирует историю звёзд по календарным неделям. На каждый запрос он переводит параметры page и per_page во временной диапазон по полю created_at, отбирает записи по этому интервалу и уже затем группирует их в ежедневные суммы. Один ответ возвращает до 30 недель данных, а увеличение номера страницы сдвигает диапазон дальше в прошлое.

При таком подходе каждая выборка обрабатывает только те недели, которые попадают в ответ, а не полный набор звёзд репозитория. Для инструментов это означает, что один запрос покрывает до 30 недель истории независимо от общего числа звёзд. Для react/react достаточно около 24 запросов вместо 2 511, и база данных просматривает каждую запись о звезде примерно один раз, суммарно около 251 000 строк.

Такой недельный шаг соответствует основному сценарию использования: поддерживающие анализируют рост по неделям или вокруг релизов, запусков и событий. Формат также выровнен с другими API активности репозиториев, например GET /repos/{owner}/{repo}/stats/commit_activity, который тоже работает с недельными интервалами.

При этом ограничение по датам не ограничивает количество звёзд внутри недели. Недели с аномально высоким числом звёзд всё ещё могут приводить к более тяжёлым запросам, хотя типичный путь обработки больше не требует сканирования всех текущих звёзд.

Сравнение старого и нового путей обработки показало и другие участки системы, где звёзды пересчитывались «на лету». Та же проблема обнаружилась на странице списка поставивших звезду на GitHub.com, которую перевели на использование кешированного количества звёзд. Число медленных запросов от этой страницы, ранее составлявшее сотни в неделю, снизилось до нуля. Аналогичные изменения позже применили и к другим API, работающим со звёздами.

Команда GitHub подчёркивает, что первичное ограничение старого endpoint решило срочную задачу защиты разработчиков и инфраструктуры. Совместная работа с поддерживающими и авторами инструментов дала более качественный результат: история звёзд стала проще в использовании, дешевле в обслуживании и безопаснее для всех, кто ставит звёзды проектам.

Новый API позволяет получить историю звёзд репозитория, а обсуждение и обратная связь доступны в GitHub Community.

Источник: GitHub

Читать новости ИИ и технологий в Telegram.


Оцените статью
Gimal-Ai