В СУБД хранится тред/чатик. Физически хранится ПОЧТИ как массив языка Си (побитый на блоки, возможно, а блоки, возможно, лежат в других дата-центрах, но реализация не меняет сути). Логически как std::vector
или как []
в js/python, скажем. Список не сортирован дополнительно никак, кроме порядка добавления в его конец. Там нет поля timestamp_nanosec и какого-то индекса по нему: кого раньше добавили в массив, тот и раньше. В объекте «сообщение» может быть конечно timestamp, но на него всем похрен и нужно оно только чтобы клиент видел какое-то время сообщения.
Из СУБД сообщения треда можно доставать по индексу (номеру от начала списка с нуля). Причём, индекс совершенно честный - как в тупом массиве на Си: если в треде было 1 млн сообщений, а потом модератор дропнул 100 с начала (0…99), то все индексы съехали на 100 вниз - называвшийся ранее 500 стал называться 400.
Данная СУБД отлично всех устраивает, особенно экономически, поддерживая сотни тысяч запросов/сек на самой дешёвой бомжатской виртуалке. Главное, чем она интересна, это как раз экономика и дубовая простота.
Опишем сценарий, когда это выходит боком.
Клиент залогинился в чатик, СУБД отдала ему 10 сообщений с конца. Причём, на каждом сообщении, при передаче на клиент, наклеен его индекс в массиве/списке - чтобы клиент знал в каком месте треда находится. Предположим, в треде было 1000 сообщений. На клиенте окажутся сообщения с индексами [989…999]. Клиент крутит чатик вверх, упирается в конец простыни и хочет подгрузить ещё штук 10 сверху. Шлёт серверу запрос R1: «дай [978…988]».
И тут наступает жепь-ебрилло:
Пока запрос R1 летел на сервер по сети, на сервере было дропнуто первых 2 сообщения и все индексы съехали. Клиент получит дубли пары сообщений (те, что у него уже были на сервере попадут в интервал R1 в результате съезда индексов). Это пережить можно - получил дубль - выкинул. Жепь-ебрилло похлеще: пока летел R1 на сервере дропнули сразу первых 100 сообщений. На клиент придёт ответ: «not found» вообще. Уже потом конечно до клиента долетит нотифайка про «drop 0…99» и клиент всё поймёт, но инфаркт в клиенте уже произошёл и всё умерло.
В общем, сгенерите какую-нибудь идею о борьбе с данным рассинхроном.
Если посмотреть на такую чатиковую систему как Slack, то там у каждой сообщеньки однозначный ID = «timestamp.timestamp_microsec» и дропание сообщений где-то в начале треда никак не затрагивает ID остальных сообщенек в этом треде. Я даже могу подумать, что у них в базе вообще все сообщеньки всех тредов лежат в одной таблице с этим адским primary_key (timestamp.timestamp_microsec) и это там ничему не противоречит, но я так не хочу чё-то пока.