Воспроизведение и лимиты
Relevant source files
The following files were used as context for generating this wiki page:
Система воспроизведения в Music Service управляет доступом пользователей к аудио-контенту и обеспечивает соблюдение бизнес-ограничений в зависимости от типа подписки пользователя. Основная цель данного модуля — регистрация фактов прослушивания в истории и контроль суточных лимитов для пользователей с бесплатным типом подписки.
Логика разделена между сервисом треков, который проверяет лимиты прослушивания через Redis, и сервисом плейлистов, ограничивающим количество создаваемых коллекций.
Механизм воспроизведения треков
Воспроизведение трека инициируется через вызов метода Play в TrackService. Процесс включает проверку статуса трека, валидацию лимитов для FREE пользователей и сохранение события в базу данных.
Алгоритм работы
- Проверка активности: Система проверяет флаг
is_activeв базе данных. Если трек деактивирован, воспроизведение прерывается. - Проверка лимитов (Redis): Для пользователей с
subscription_type == "FREE"система запрашивает текущий счетчик из Redis по ключуuser:{id}:daily_play_count:{date}. - Инкремент: Если лимит не превышен, счетчик увеличивается, и устанавливается TTL 24 часа.
- История прослушиваний: Факт воспроизведения сохраняется в таблицу
listening_historyв PostgreSQL.
Sources: internal/features/tracks/service/play.go:19-75, internal/features/tracks/repository/postgres/track_repository.go:132-138
Схема процесса воспроизведения
Данная диаграмма описывает последовательность действий при запросе на прослушивание трека.
Система лимитов по типам подписки
Проект предусматривает жесткие ограничения для пользователей без платной подписки (FREE), которые настраиваются через переменные окружения.
Типы ограничений
- Суточный лимит прослушиваний: Ограничивает количество треков, которые пользователь может прослушать за один календарный день.
- Лимит плейлистов: Ограничивает общее количество созданных пользователем плейлистов.
| Параметр лимита | Ключ конфигурации | Значение по умолчанию |
|---|---|---|
| Ежедневные прослушивания (FREE) | FREE_DAILY_PLAY_LIMIT | 10 |
| Макс. плейлистов (FREE) | FREE_PLAYLIST_LIMIT | 3 |
Sources: internal/core/config/config.go:42-43, internal/features/playlists/service/create.go:13-26
Логика ограничений плейлистов
При создании плейлиста PlaylistService выполняет проверку:
- Выполняется запрос
COUNT(*)в таблицеplaylistsдля конкретногоuser_id. - Если текущее количество >=
playlistLimitFREE, возвращается ошибкаErrPlaylistLimitExceeded. - Для пользователей с подпиской
PREMIUMпроверка пропускается.
Sources: internal/features/playlists/service/create.go:13-26, internal/features/playlists/service/service.go:12-13
Хранение данных прослушиваний
История прослушиваний хранится в реляционной базе данных для последующего анализа и отображения пользователю.
Для оптимизации запросов к истории используется индекс по пользователю и времени прослушивания:
CREATE INDEX idx_listening_history_user_listened_at ON listening_history (user_id, listened_at DESC);
Sources: migrations/001_init.up.sql:101-111
Техническая реализация в коде
Обработка лимитов в Redis
Использование Redis позволяет эффективно сбрасывать лимиты каждые сутки без необходимости сложной очистки основной БД. Ключи формируются на основе текущей даты в формате YYYY-MM-DD.
dateStr := time.Now().Format("2006-01-02")
redisKey := fmt.Sprintf("user:%d:daily_play_count:%s", userID, dateStr)
Sources: internal/features/tracks/service/play.go:35-36
Обработка ошибок
Система использует специфичные ошибки для уведомления клиента о достижении лимитов:
ErrDailyLimitExceeded: Возвращается, когда достигнут порог в 10 прослушиваний (по умолчанию) в день.ErrPlaylistLimitExceeded: Возвращается при попытке создать 4-й плейлист на бесплатном аккаунте.
Sources: internal/features/tracks/service/play.go:14, internal/features/playlists/service/service.go:12
Заключение
Система воспроизведения и лимитов обеспечивает монетизационную модель приложения, разделяя доступ к функционалу. Использование Redis для оперативных счетчиков прослушиваний снижает нагрузку на PostgreSQL, обеспечивая высокую производительность при проверке прав доступа к аудио-потоку.