Skip to content
07КейсSW · 07 из 10

Async-first музыкальный маркетплейс, построенный в два слоя для оператора, владеющего каталогом.

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

КлиентКонфиденциально
Год2022
Длительность1 yrs
СтекPHP · Symfony · Postgres · Redis · InfluxDB
Hero image for ugc-music-platformFIG 01 · Главное изображение

Маркетплейс, а не стриминговый сервис. Эта разница важна архитектурно.

Оператор строил не стриминговый сервис, где артисты загружают ради охвата, а доход приходит позже как доля от рекламы. Артисты владеют своим контентом. Слушатели за него платят. Платформа — это маркетплейс: листинги товаров, корзина, оформление, история заказов, отчёты по продажам. Бизнес-модель живёт в этом потоке.

Это различие меняет архитектуру. Самая сложная задача стримингового сервиса — пропускная способность приёма и задержка воспроизведения. Самая сложная задача маркетплейса — коммерческая поверхность: конкурентные операции с корзиной, согласованность заказов, оформление, которое не теряет покупку, если фоновый воркер медлит. Ошибитесь в этом — и вы теряете реальные транзакции от артистов, которые и так скептичны к новой платформе.

У оператора также был план на мобильный клиент — iOS и Android, который будет построен позже — и он хотел, чтобы API-слой был к нему готов. Не дооснащён задним числом. Готов с самого начала, с версионированными DTO-эндпоинтами и чётким разделением Admin/Mobile. Мобильное приложение не вышло в окне 2022 года. API-слой — вышел.

Бриф: полноценная коммерческая поверхность для каталога, принадлежащего артистам, асинхронное ядро, которое не блокирует оформление фоновой работой, и API-слой, который не придётся переосмысливать, когда появится мобильный клиент.

Два слоя, шина сообщений и три хранилища с разными задачами.

Система с первого дня делилась на два приложения Symfony. Монорепозиторий — админка и веб-UI — отвечал за управление профилями артистов, листинги товаров, загрузку обложек и бэк-офис оператора. API-слой был построен отдельно, как REST-сервис с версионированием через DTO и пространствами маршрутов /Mobile/v1/ и /Admin/v1/, 96 мобильных эндпоинтов и 130 админских, задокументированный и готовый к мобильному клиенту, когда бы тот ни появился.

Потоки корзины и заказов идут через Symfony Messenger, а не через синхронные записи. AddToCartController отправляет сообщение; обработчик обрабатывает мутацию корзины асинхронно. Записи заказов — Order и ProductOrder, с количеством и общей стоимостью, отслеживаемыми по каждой строке — следуют тому же паттерну. Оформление не блокируется записями телеметрии, обработкой обложек или чем-либо ещё, идущим по шине. Операционная база данных остаётся быстрой, потому что веерное распределение записей управляемо.

Три хранилища, у каждого — одна зона ответственности. PostgreSQL — каноническое состояние: 25 сущностей, более 40 индексов на горячих таблицах — пользователи, товары, заказы, позиции корзины, жанры, теги, связи «артист — товар». Redis работает и как брокер очереди Messenger, и как слой кэша для горячих чтений. InfluxDB хранит телеметрию действий пользователей. Высокочастотные поведенческие события никогда не касаются операционной базы данных.

Профили артистов и описания товаров — названия альбомов, имена треков, метки жанров, новости — переводимы на уровне схемы через KnpLabs DoctrineBehaviors. Добавление локали — это миграция данных, а не изменение кода. Веб-UI использовал Plyr для воспроизведения аудио и видео; CropperJS отвечал за обрезку и загрузку обложек прямо на странице.

F · 01Корзина и оформление через Messenger
Мутации корзины и обработка заказов идут через Symfony Messenger, а не синхронные записи. Оформление подтверждается мгновенно; шина берёт на себя веерное распределение записей.
F · 02Двухслойная архитектура
Монорепозиторий (админка и веб-UI) и отдельный API-сервис с версионированием через DTO и пространствами /Mobile/v1/ и /Admin/v1/ — 96 мобильных эндпоинтов и 130 админских — построенный до того, как появился мобильный клиент.
F · 03Разделение на три хранилища
PostgreSQL для канонического состояния (25 сущностей, более 40 индексов), Redis для брокера очереди и кэша, InfluxDB для телеметрии действий пользователей. У каждого хранилища одна задача.
F · 04Переводимый контент на уровне схемы
KnpLabs DoctrineBehaviors на описаниях товаров, профилях артистов, метках жанров и новостях. Добавление локали — это миграция, а не изменение кода.
F · 05Конвейер телеметрии InfluxDB
События действий пользователей идут через обработчики Messenger в InfluxDB. Конвейер спроектирован под полную телеметрию проигрывания, перемотки и пропуска, не касаясь операционной базы данных.
F · 06Асинхронная обработка заказов
Сущности Order и ProductOrder отслеживают покупки с количеством и стоимостью по каждой строке. Мутации заказов идут через шину сообщений, чтобы коммерческие операции не конкурировали друг с другом.

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

Решение направить мутации корзины через Symfony Messenger, а не через синхронные записи, было не про масштаб. Оно было про корректность. Операции с корзиной в маркетплейсе включают проверки склада, валидацию состояния товара и обработку конкурентных сессий. Вынос их на шину сообщений отвязывает подтверждение для пользователя от веерного распределения записей. Слушатель получает ответ; платформа догоняет. Операционная база данных никогда не соревнуется с коммерческой поверхностью.

Тот же принцип проходит и через воспроизведение. PlayFileHandler и PlayedFileService отвязывают события воспроизведения от операционной базы данных. Телеметрия действий пользователей пишется в InfluxDB через шину сообщений — всего 21 обработчик в API-слое. Конвейер InfluxDB спроектирован под полную телеметрию проигрывания, перемотки и пропуска; подключение этих дополнительных событий — следующий шаг, который оператор может сделать, ничего не переархитектуривая.

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

API-слой был намеренно избыточен для 2022 года. /Mobile/v1/ существовал с 96 эндпоинтами до того, как была написана хоть строчка кода мобильного приложения. Мобильный клиент не вышел в окне 2022 года, но оператор унаследовал API-сервис, который уже был версионирован, задокументирован и отделён от админ-поверхности. Цена сделать это позже — с живым продуктом, реальными данными пользователей и разошедшейся схемой — несопоставима с ценой сделать это один раз в начале.

Восемь месяцев. Три репозитория. Коммерческая поверхность, которую оператор может расширять.

Восемь месяцев активной разработки. 494 коммита в трёх репозиториях — монорепозиторий, API-слой и минимальный лендинг на HTML/Gulp. Система вышла с полноценной коммерческой поверхностью «артист — слушатель»: листинги товаров, корзина, оформление, история заказов и отчёты по продажам. Асинхронная архитектура — шина Messenger, брокер Redis, конвейер телеметрии InfluxDB — была в продакшене с первого публичного релиза.

Мобильный клиент был единственной запланированной поверхностью, не вышедшей в окне 2022 года. API-слой, построенный, чтобы его принять, цел. Пространство /Mobile/v1/, контракты DTO, обработка аутентификации — всё это ждёт клиента, а не наоборот.

У архитектуры, которую унаследовал оператор, три чёткие границы: Postgres для состояния, Redis для очереди и кэша, InfluxDB для временных рядов. Каждый может отказать, быть обновлён или масштабирован независимо. Следующему инженеру не нужна шестичасовая вводная. Интересная задача — асинхронная коммерческая поверхность — решена. Всё после этого — продуктовая работа.

Цитата / 04
Мы строили под мобильный клиент до того, как он появился. Когда он выйдет, платформа этого не заметит.
ОсновательМузыкальный маркетплейс
Outcome
Active development
8 months
Commits across 3 repos
494
Symfony Messenger handlers
21
Entities in canonical schema
25
NEXTКейс 08SW · 08 из 10
Fintech2022 — 2026

Календарь отчётностей и SPX-экспозиция по гамме, сплавленные в одну панель.