146 lines
11 KiB
Markdown
146 lines
11 KiB
Markdown
# p1ctos4ve
|
||
|
||
Проект в рамках дисциплины «Конструирование программного обеспечения»: сервис сохранения и организации медиа со внешних ресурсов
|
||
|
||
## Участники
|
||
- Железняков Марк Викторович - `5130904/30105`
|
||
- Михеев Егор Романович - `5130904/30105`
|
||
- Михальченко Владислав Сергеевич - `5130904/30105`
|
||
- Ботыгин Иван Алексеевич - `5130904/30105`
|
||
|
||
## Определение проблемы
|
||
Пользователи, сохраняющие большое количество медиафайлов (фотографий, видео, GIF) из разных источников (социальные сети, мессенджеры и другие специализированные платформы), сталкиваются с трудностями их систематизации и последующего поиска. Файлы скапливаются в беспорядке, отсутствует единая система тегов и категорий, что делает быстрый поиск нужного материала практически невозможным и требует значительных ручных усилий по организации. При этом всегда присутствует риск удаления материалов из первоисточника.
|
||
|
||
## Выработка требований
|
||
|
||
### Пользовательские истории
|
||
1. Как пользователь, я хочу добавлять медиафайлы (фото, видео, GIF) в свою библиотеку из различных источников (прямая загрузка, по ссылке, через интеграцию с Tenor/Pinterest), чтобы централизованно хранить все материалы.
|
||
2. Как пользователь, я хочу иметь мощную систему поиска по библиотеке с фильтрацией по типу файла, тегам, категориям и дате добавления, чтобы быстро находить конкретные материалы.
|
||
3. Как пользователь, я хочу иметь возможность просматривать свою медиатеку в удобном интерфейсе (галерея, список) с предпросмотром, чтобы легко ориентироваться в содержимом.
|
||
|
||
## Разработка архитектуры и детальное проектирование
|
||
|
||
### Оценка масштаба
|
||
> Оценка масштаба производится при условии нагрузки на сервис в размере 10 000 активных пользователей в сутки. При этом сервис подазумевает опцию селфхостинга, что может снизить требования к ресурсам центрального экземпляра (инстанса) сервиса.
|
||
|
||
#### Характер нагрузки
|
||
|
||
##### Соотношение R/W нагрузки
|
||
**30% на чтение и 70% на запись.** Обосновать это можно тем, что запись метаданных и загрузка файлов будет занимать большую долю операций в сервисе с пиками во время массовых импортов из Tenor/Pinterest. При этом чтение данных будет производится сильно реже
|
||
|
||
##### Трафик
|
||
Для входящего трафика предположим, что один пользователь в среднем будем генерировать 5 МБ данных. Так, 10 000 пользователей * 5 МБ = 50 ГБ/день.
|
||
|
||
##### Объемы дисковой системы
|
||
При начальном размере файла ~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](assets/API.md), а полная документация - в [Scalar](https://scalar.com/) на эндпоинте `/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` в браузере.
|
||
|