Archived
1
0
This repository has been archived on 2025-11-29. You can view files and clone it, but cannot push or open issues or pull requests.
Files
app/README.md

11 KiB
Raw Blame History

p1ctos4ve

Проект в рамках дисциплины «Конструирование программного обеспечения»: сервис сохранения и организации медиа со внешних ресурсов

Участники

  • Железняков Марк Викторович - 5130904/30105
  • Михеев Егор Романович - 5130904/30105
  • Михальченко Владислав Сергеевич - 5130904/30105
  • Ботыгин Иван Алексеевич - 5130904/30105

Определение проблемы

Пользователи, сохраняющие большое количество медиафайлов (фотографий, видео, GIF) из разных источников (социальные сети, мессенджеры и другие специализированные платформы), сталкиваются с трудностями их систематизации и последующего поиска. Файлы скапливаются в беспорядке, отсутствует единая система тегов и категорий, что делает быстрый поиск нужного материала практически невозможным и требует значительных ручных усилий по организации. При этом всегда присутствует риск удаления материалов из первоисточника.

Выработка требований

Пользовательские истории

  1. Как пользователь, я хочу добавлять медиафайлы (фото, видео, GIF) в свою библиотеку из различных источников (прямая загрузка, по ссылке, через интеграцию с Tenor/Pinterest), чтобы централизованно хранить все материалы.
  2. Как пользователь, я хочу иметь мощную систему поиска по библиотеке с фильтрацией по типу файла, тегам, категориям и дате добавления, чтобы быстро находить конкретные материалы.
  3. Как пользователь, я хочу иметь возможность просматривать свою медиатеку в удобном интерфейсе (галерея, список) с предпросмотром, чтобы легко ориентироваться в содержимом.

Разработка архитектуры и детальное проектирование

Оценка масштаба

Оценка масштаба производится при условии нагрузки на сервис в размере 10 000 активных пользователей в сутки. При этом сервис подазумевает опцию селфхостинга, что может снизить требования к ресурсам центрального экземпляра (инстанса) сервиса.

Характер нагрузки

Соотношение R/W нагрузки

70% на чтение и 30% на запись. Обосновать это можно тем, что запись метаданных и загрузка файлов будет занимать большую долю операций в сервисе с пиками во время массовых импортов из Tenor/Pinterest. При этом чтение данных будет производится сильно реже

Трафик

Для входящего трафика предположим, что один пользователь в среднем будем генерировать 10 МБ данных. Так, 10 000 пользователей * 10 МБ = 100 ГБ/день.

Объемы дисковой системы

При начальном размере файла ~5 МБ и 10 загрузках на пользователя в день: 10 000 * 10 * 5 МБ = 500 ГБ/день. Поэтому может потребоваться дешевое S3-хранилище.

Диаграммы C4 Model

Контекст

assets/c4-1context.jpg

Контейнеры

assets/c4-2containers.jpg

Компоненты

assets/c4-3components.jpg

Контракты API

Краткая информация о методах API доступна в assets/API.md, а полная документация - в Scalar на эндпоинте /openapi.

Схема БД и оправдание с точки зрения нефункциональных требований

assets/db.png

Нефункциональные требвания

Оптимизация индексов и связей

В схеме присутствуют индексы на полях, которые часто участвуют в поисковых запросах, например, userId, visibility, shareUrl, tags. Это повышает производительность выборок и операций поиска.

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

Масштабируемость и расширяемость

Пользователи, сессии и аккаунты разделены по разным таблицам - это упрощает работу и интеграцию способов авторизации пользователей в сервисе.

Безопасность и уникальность данных

Схема предотвращает дублирование данных посредством использования уникальных индексов. Например, на email и token в сессиях, shareUrl в сейвах.

Схема масштабирования сервиса при росте нагрузки в 10 раз

Для возможности масштабирования можно использовать следующие подходы:

  • Размещение бекенда за балансировщиком нагрузки (например, Nginx, Traefik или Caddy): трафик будет распределяться равномерно между двумя или более экземплярами API
  • Репликация БД - основная база принимает запись, а одна или несколько реплик получают изменения по журналу (WAL) и обслуживают преимущественно чтение.
  • Кеширование частозапрашиваемых данных через Redis: результаты чтения (например, списки, карточки по ID, агрегации, результаты поиска с популярными фильтрами) складываются в KV хранилище с некоторым TTL, что позволяет сократить время ответа на повторяющиеся запросы

Кодирование и отладка

Для разработки сервиса был использован следующий набор технологий:

Бекенд

  • Bun в качестве рантайма
  • Бекенд-фреймворк Elysia
  • Drizzle ORM для работы с базой данных PostgreSQL
  • Фреймворк Better Auth для авторизации и аутентификаци пользователей
  • SeaweedFS для хранения UGC
  • Redis для кеширования частозапрашиваемых данных

Фронтенд

  • Фреймворк и библиотеки Expo для реализации мобильного клиента сервиса
  • Tailwind + Nativewind для стилизации
  • Набор иконок Lucide

Для запуска в режиме разработки нужно:

Бекенд

  • Установить зависимости: bun i
  • В директории apps/backend заполнить файл .env на основе .env.example
  • Прописать bun dev в директории бекенда или bun backend:dev в корне репозитория

Фронтенд

  • В директории apps/frontend заполнить файл .env на основе .env.example
  • Прописать bun start в директории фронтенда. Приложение можно отлаживать на мобильном устройстве через песочницу Expo Go.

Unit-тестирование

В проекте есть тесты, проверяющие корректность работы отдельных элементов сервисов бекенда:

  • s3.service.test.ts - проверяет корректность работы автоопределения типов медиа
  • saves.service.test.ts - моковые тесты для проверки работы сервиса сейвов
  • scraper.service.test.ts - тесты для проверки работы вычисления типов медиа на основе URL

Для запуска требуется прописать bun run test:unit из директории apps/backend.

Интеграционное тестирование

Также реализованы e2e-тесты для проверки авторизации и сейвов.

Предварительно запустив бекенд, из директории бекенда нужно запустить bun run test:e2e.

Сборка и запуск

Для запуска бекенда и его зависимостей на продакшене достаточно выполнить:

git clone https://git.inkling.su/p1ctos4ve/app p1ctos4ve
cd p1ctos4ve
chmod +x ./scripts/run.sh
./scripts/run.sh

Скрипт run.sh:

  • Запустит PostgreSQL, SeaweedFS и Redis;
  • Соберет образ бекенда в Docker-контейнер;
  • Запустит unit и e2e-тесты;
  • Поднимет сервер бекенда на localhost:3000

В дальнейшем для взаимодействия с API можно открыть Scalar на localhost:3000/openapi в браузере.