Какие данные будут приходить через сокет: весь список или только обновленные сообщения
Что проверяют
Умеете ли вы проектировать синхронизацию данных, а не просто открыть сокет. Вопрос часто звучит на мобильном system design чата, и сильный кандидат задаёт его сам, как уточнение требований. Следом спрашивают, что будет после обрыва соединения и как не потерять сообщения.
Как отвечать
Рабочая схема почти всегда комбинированная: снимок данных берут отдельно, а по сокету идут только изменения.
- начальная загрузка: при открытии чата клиент берёт историю через REST постранично, на Android это удобно делать через Paging 3 с
RemoteMediator; - события по сокету: новое сообщение, правка, удаление, статус «прочитано», «печатает». Каждое событие несёт id сообщения и порядковый номер (
seq), который выдаёт сервер; - догонка после переподключения: клиент хранит последний полученный
seqи при восстановлении соединения просит всё, что было после него. Если разрыв слишком большой, сервер отвечает «делай полную пересинхронизацию»; - идемпотентность: события могут прийти дважды, поэтому запись в Room делается через upsert по id (
@UpsertилиOnConflictStrategy.REPLACE).
Room при этом служит единственным источником правды: сокет пишет в базу, а UI подписан на Flow из DAO и не знает, откуда пришли данные. Сам сокет обычно на WebSocket из OkHttp или на клиенте Ktor, живёт в слое данных, а не в Activity, переподключается с экспоненциальной задержкой. В фоне соединение не держат: система его всё равно прибьёт, а о новых сообщениях сообщает пуш через FCM.
Весь список по сокету имеет смысл только для маленьких и редко меняющихся наборов, например список онлайн-участников комнаты.
Где спотыкаются
Предлагают слать полный список при каждом изменении. Растёт трафик, а DiffUtil каждый раз пересчитывает весь список.
Не думают о разрывах. Без номера последовательности сообщения, пришедшие во время переключения с Wi-Fi на мобильную сеть, теряются молча.
Сортируют по времени устройства. Часы на телефонах расходятся, порядок должен задавать сервер.