Skip to content

vasiaplaton/GithubParserAPI

Repository files navigation

README

Репозиторий с решением тестового задания для Backend Developer (Python+SQL)

Описание задания

Проект состоит из двух частей:

  1. API-приложение:

    • Реализует RESTful API с двумя эндпоинтами:
      • GET /api/repos/top100 — возвращает топ 100 публичных репозиториев из PostgreSQL, отсортированных по количеству звезд (с возможностью сортировки по другим полям).
      • GET /api/repos/{owner}/{repo}/activity — возвращает активность репозитория по коммитам за указанный промежуток времени.
    • Окружение приложения настроено через docker-compose (см. секцию ниже).
    • Используемые технологии: Python 3.11, FastAPI, asyncpg, PostgreSQL.
    • Запросы к базе данных написаны на чистом SQL.
  2. Парсер данных:

    • Парсит данные с GitHub и сохраняет их в PostgreSQL:
      • Топ 100 репозиториев по количеству звезд.
      • Информацию об активности коммитов для каждого репозитория.
    • Разработан с учетом запуска в Яндекс.Облаке (например, через cloud function) с прокинутыми переменными окружения для подключения к базе данных.

Основные возможности

  • API-приложение:

    • Эндпоинты:
      • /api/repos/top100 — поддерживает сортировку по полям stars, forks, open_issues, watchers.
      • /api/repos/{owner}/{repo}/activity — поддерживает выборку активности по диапазону дат (since и until).
    • Архитектура с Dependency Injection для переиспользования кода.
  • Парсер:

    • Обновляет топ 100 репозиториев:
      • Каждый день парсер сравнивает данные текущих репозиториев в базе с результатами запроса к GitHub API.
      • Сохраняются изменения, включая новую позицию в рейтинге, количество звезд, форков и другие метрики.
    • Обновляет активность по коммитам:
      • Для каждого репозитория проверяется последняя дата активности в базе.
      • Если данных нет, парсер загружает коммиты за последние 30 дней. Если данные есть, загружаются только новые изменения.

Почему выбран интервал в один день?

Интервал в один день выбран для балансировки между актуальностью данных и нагрузкой на GitHub API. Частые запросы могут:

  1. Привести к превышению лимитов GitHub API (5000 запросов в час для аутентифицированных пользователей).
  2. Создать ненужную нагрузку на базу данных и сам сервис.

Одного обновления в сутки достаточно, чтобы:

  • Поддерживать актуальность данных для большинства случаев использования.
  • Уменьшить нагрузку на инфраструктуру.

Запуск приложения

1. Запуск API-приложения через Docker Compose

  1. Создайте файл .env на основе .env_example и укажите реальные параметры подключения к PostgreSQL:

    POSTGRES_USER=admin
    POSTGRES_PASSWORD=admin
    POSTGRES_DB=test_db
    POSTGRES_URL=db
    POSTGRES_PORT=5432

    Или передайте в переменные окружения данные параметры

  2. Соберите контейнеры:

    docker-compose build
  3. Запустите приложение:

    docker-compose up
  4. Приложение будет доступно по адресу http://localhost:8080.

Примеры запросов:

  1. Получить топ 100 репозиториев:

    curl -X GET "http://localhost:8080/api/repos/top100?sort_by=stars"
  2. Получить активность репозитория:

    curl -X GET "http://localhost:8080/api/repos/example-owner/example-repo/activity?since=2024-11-01&until=2024-12-01"

2. Подключение парсера

  1. Установите зависимости для парсера(requirements.txt)
  2. Передайте параметры подключения к базе данных через переменные окружения(они аналогичны тем, что выше).
    export $(grep -v '^#' .env | xargs)
    Также, можно добавить данные для подключения к Github
    GITLAB_BASE_URL=https://api.github.com
    GITLAB_TOKEN=**your_personal_access_token**
    GITLAB_BASE_URL дефолтится к https://api.github.com, TOKEN можно не передавать
  3. Для запуска парсера создайте отдельный скрипт или функцию в облаке (например, Яндекс.Облако), которая запускает файл parser/main.py.
    python3 -m parser.main

Разработка и отладка

Отладка через docker-compose-dev

  1. Запустите полную инфраструктуру, включая API, парсер и базу:

    docker-compose -f docker-compose-dev.yaml up --build
  2. Парсер настроен на запуск по расписанию через cron, но его также можно запустить вручную:

    docker exec -it <parser-container-id> python /app/parser/main.py

Работа с БД

  • Для локальной разработки необходимо создать таблицы, определенные в create_tables.sql (молюсь чтобы они были такие же)
  • CREATE TABLE IF NOT EXISTS top100 (
        repo TEXT NOT NULL,
        owner TEXT NOT NULL,
        position_cur INT NOT NULL,
        position_prev INT NOT NULL,
        stars INT NOT NULL,
        watchers INT NOT NULL,
        forks INT NOT NULL,
        open_issues INT NOT NULL,
        language TEXT,
        PRIMARY KEY (repo, owner)
    );
    
    CREATE TABLE IF NOT EXISTS activity (
        date DATE NOT NULL,
        commits INT NOT NULL,
        authors TEXT[] NOT NULL,
        repo TEXT NOT NULL,
        owner TEXT NOT NULL,
        PRIMARY KEY (date, repo, owner)
    );

Обоснование решения для такой отладки

  1. Отказ от Terraform/CLI Яндекс.Облака:

    • Не хватило времени на изучение CLI или Terraform для работы с Яндекс.Облаком.
    • Также невозможно стартовать бесплатный аккаунт без юридического лица.
    • Для тестирования и отладки парсер настроен в контейнере с cron.
  2. Инструкция для облака:

    • Парсер можно развернуть в Яндекс.Облаке через cloud function, прокинув переменные окружения для подключения к БД.
    • Скрипт парсера сам запускает обновление данных.

Приложение готово к запуску и тестированию.

Таблица top100

top100.png

Таблица activity

activity.png

Тестовый прогон

test_run.jpg

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published