Каким образом доставить сообщение тем пользователям, сокет которых не активен?
Всем доброго времени суток. Постигая азы Socket.io столкнулся с проблемой.
Предположим, что есть определенная комната( информация о которой хранится в базе, а так же хранятся ID и Socket.id каждого клиента, и при переподключении сокет.id обновляется ).
Пользователи при аутентификации на сервере и вызове ивента joinRoom, присоеденяется к комнате, и при дисконекте, он покидает комнату( формально отключается от сервера, и именно этот сокет покидает комнату, но не пользователь ).
Предположим что какой-то сокет бродкастит сообщение в комнату. Сообщение понятное дело доставится сразу всем онлайн пользователям чем сокет сейчас известен, ну и сохранится в базу. А как быть с теми пользователями, которые сейчас не онлайн, но их сокет станет известен при подсоеденении? Не совсем понимаю как отслеживать этот момент.
При логине в комнату посылать сообщения, которые не были доставлены, например. Сервер же знает что пользователь соединился и может запустить цепочку поиска и досылки сообщений
А, т.е. по факту нужно отслеживать статус сообщения для каждого пользователя? Т.е. например в базе у меня хранятся предположим 4 сообщения, который отправлены в конкретную комнату, со статусом доставки для каждого пользователя верно? Например, когда пользователь конектится, то при ивенте конект происходит проверка в базе по этой комнате( вытаскиваются все сообщения из базы, которые были отправлены ). И из этих сообщений происходит выборка всех тех, статус которых по айдишнику именно этого пользователя например равен recieved=false? Примерно так?
Иван Шумов, Не совсем понял про клиент. Т.е на клиенте предположим у нас мобильный клиент, хранить например айдишник последнего полученного сообщения, и при конекте отправлять это состояние. И этот айдишник будет как бы начальной точкой после которой нужно доотправить все сообщения?
mint_candy, сервер не должен знать ничего про клиента. Все клиенты не зависят друг от друга и имеют право иметь в отсутствие сети разный набор сообщений. Если одна система получила сообщение то и другая обязана получить
а нет. Это было сказано к тому, что например, клиент чатился с мобильного приложения, и состояние последнего сообщения сохранилось на клиенте предположим. И после этого скажем, он зашел с веб версии, но там например сохранено более ранее состояние( с последнего визита с веба ), и как быть в этом случае? Или все же статус сообщения отслеживать?
И еще у меня к вам вопрос, как в таком случае в Socket.io отправить сообщения в руме но только конкретным пользователям?
mint_candy, вы в любом случае при нескольких клиентах обязаны сделать stateless backend и перенести логику запросов сообщений на клиента. Сообщения модно посылать как угодно. Но лучше точечно ибо в группу посылают только в случае когда отключившиеся клиенты больше никогда не участвуют в получении информации
Иван Шумов, А, я вас видимо не правильно понял. Т.е. вы предлагаете вместо того чтобы использовать румы, отправлять каждому клиенту сообщение точечно, но с присутствующим в сообщении roomId( чтобы клиенту идентифицировать из какого чата пришло сообщение), так?
Иван Шумов, Хм. Ну что-то вроде понятно. Но по-сути я думаю, что если взять в расчет всю информацию, которая обсуждалась ранее, то можно предложить следующий вариант доставки, но я не уверен что он правильный.
1. Клиент выходит из комнаты.
2. После реконекта, клиент отправляет стейт последнего полученного им сообщения на сервере и на основе этого досылаются не прочитанные сообщения.
3. Эти сообщения можно досылать следующим образом - создать какой-то ивент в контексте комнаты, через который будут отправляться сообщения снова всем в комнату, но те клиенты, которые уже прочитали и отрендерили список сообщений, могут забить на этот ивент в принципе. Но по сути, почему я не могу хранить статус сообщения на сервере? Просто представьте тот же WhatsApp. Там если зайти в информацию о сообщении, то можно увидеть кто получил сообщение, а кто нет. И я думаю что эта информация хранится на сервере. И по сути на основе этой информафции можно и делать выводы о досылке сообщений не прочитавшим пользователям.
mint_candy, нельзя перепослать всем сообщение. По тому что это:
- трата сухого трафика
- трата чужих ресурсов
- потенциальное место налажать
- не безопасно
Хранить на сервере нельзя по тому что вам надо гарантированно идентифицировать клиента (а не пользователя)
Перепослать сообщения нужно стандартным механизмом - пришел клиент, получили для него сообщения с последнего стейта, послали сообщения как и всегда
Проверку на клиенте на дубль сообщения делать обязательно. Возможность переполучить что-то в сокете высока
Иван Шумов, Но я в таком случае не совсем понимаю для чего тогда вообще нужны rooms в Socket.io, через которые можно бродкастить??? Если по факту можно реализовать доставку сообщений как бы из комнаты, но точечно. По сути это ли не нагружает сервер сильнее, как бы циклично придется на каждый сокет отправлять сообщение? Или я чего-то не понимаю?
mint_candy, это для других задач. Например, представьте анонимный чатик где люди общаются только пока не оборвалось соединение) я сейчас утрировал, но примерно так. В целом - каждой задаче свой инструмент
Иван Шумов, Извиняюсь, что поздно. Переписали обмен данными с групой пользователей на точечную отправку. Но у меня все же вопрос, можете подсказать. Как если не хранить статус сообщения на сервере, можно понять какие сообщения прочитаны клиентом, а какие нет?
Ну для примера смотрите. Клиент переписывался через мобильное приложение, и вышел. Статус последнего прочитанного сообщения сохранился в кэше мобилки. Пока он был офлайн ему пришло пару сообщений. Он решил зайти с веб приложения( впервые ), и в веб приложении еще нет никаких данных о статусе прочитанных сообщений. Каким образом мне понимать, что сообщения новые для клиента, если в веб версии приложения еще нет никаких данных о статусе?
mint_candy, так. перестаньте употреблять слово клиент как пользователь. клиент - это сферический скрипт в вакууме, который работает с сокетом. каждый из таких клиентов хранит свой стейт. Если стейт пуст то вы присылаете Х последних сообщений и по мере промотки ленты запрашиваете с сервера другие (до какого-то момента)
Иван Шумов, Но как узнать например что X последних сообщений, это новые сообщения для пользователя? Ну вы же знаете как Телеграм например работает.
Даже если я с нового устройства зайду, не имея никакого стейта последних сообщений, он мне все равно вернет список, и те сообщения которые не прочитаны ни на одном устройстве будут новыми для этого нового устройства. Т.е. в этом случае получается нужно хранить стейт на сервере? Или как мне понимать с нового устройства, что сообщения новые?
Иван Шумов, Ну вот. А вы говорите о стейтлес. Я вам изначально задавал данный вопрос, а вы писали про то чтобы всю логику запросов перенести на клиент)