Size: a a a

2019 October 13

VI

Victor Ivanov in pro.elixir
ur welcome!
по сути, это вариант из ссылки http://derkobe.github.io/2016/01/11/get-notified-when-an-user-leaves-a-phoenix-channel.html
но переписанный с использованием Presence
источник

VI

Victor Ivanov in pro.elixir
второй вариант из того, что Крис вот здесь предлагает делать https://elixirforum.com/t/how-to-create-a-process-subscribed-to-a-channel-topic-to-watch-the-handle-diff-events/2869/2?u=victorivanov
источник

AM

Alexander Malaev in pro.elixir
Victor Ivanov
интересно будет посмотреть
Требования к презенсам у нас были следующие:
- когда клиент открывает экран с чатом на клиенте, то получает эвент со списком статусов всех юзеров этого чата, чтобы отобразить актуальный статус + время последней смены статуса, для каждого из них, включая то, когда он стал offline;
- если пользователь не на экране чата, ему презенсы не нужны;
- можно подписаться на презенсы конкретных юзеров и на других экранах в приложения, например в профиле конкретного пользователя.

Изначально сделали так, что подписывались вообще на все презенсы всех юзеров, с которыми есть общий чат, но это приводило к огромному количеству user_status'ов летящих в клиентов. Это било по количеству трафа, поэтому в дальнейшем сделали отправку статусов только по подписке с клиента.

Посмотрел как трэкаем сокет - при джойне в системный канал system, делаем Phoenix.Tracker.track(tracker_name(server_id), socket.channel_pid, "system", user_id, %{udid: device_id, server_id: server_id})

Как детектим изменение online -> offline и наоборот:
- в handle_diff достаём текущий список трекаемых pid'ов по ключу user_id Phoenix.Tracker.get_by_key("system", user_id)
 - если дифф joins и длина списка стала > 0, то шлем online
 - если дифф leaves и длина списка стала [], то шлем offline

- каждое измнение статуса с таймстемпом пишем в ets и периодически скидываем в dets, чтобы при рестарте сервиса была инфа о сменах статусов.

Грабли на которые наступили по пути:
- списки пидов по юзеру складывали в GS, по ключу с user_id, но под нагрузкой он стал боттлнэком, трэкер стал падать.  
- переделали его на ets, начали появляться зомби - у юзера не было живых pid'ов, но GS видел его как живого, по какой-то причине коллбэки от феникс-трекера доходили дважды, либо доходили не в том порядке, причину так и не поняли.

В итоге выкинули GS и стали брать актуальную инфу из самого Phoenix.Tracker'а, оставив запись таймстемпов в ets.
источник

VI

Victor Ivanov in pro.elixir
> по какой-то причине коллбэки от феникс-трекера доходили дважды, либо доходили не в том порядке, причину так и не поняли.

Вот у меня что-то похожее, надо логгирование воткнуть и попробовать отловить
источник

ML

Maksim Lapshin in pro.elixir
А людей много в одном чате?
источник

VI

Victor Ivanov in pro.elixir
Не знаю, как у Саши, у меня где-то 1.5К пока было максимум
источник

ML

Maksim Lapshin in pro.elixir
Это похоже на нашу проблематику: показать список видеостримов на сервере

Постраничная листалка страдает тем, что пока листаешь, список меняется
источник

ML

Maksim Lapshin in pro.elixir
Но надо стараться: нет смысла отдавать весь список юзеров. Можно например отдавать последние 50-100 говоривших
источник

ML

Maksim Lapshin in pro.elixir
Остальных показывать отдельным апи
источник

ML

Maksim Lapshin in pro.elixir
Но главное: нельзя показывать список из 1500 элементов, это дорога вникуда
источник

VI

Victor Ivanov in pro.elixir
не не не, у меня другая задача – для стрима считать сколько времени человек его смотрел. так что все остается внутри сервера, на клиента только для модераторов (2-3 максимум) уходят presence_diff

А подсчет ведется немного не elixir way – создаются записи в БД на каждый коннект/дисконнект. Почему так – феникс здесь маленькая пристройка рядом с рельсами, причем без шанса, что феникс будет сильно расти (я контрактор, основная комманда только на руби пишет)
источник

VI

Victor Ivanov in pro.elixir
то есть мне по сути нужна очень простая вещь – стабильное отслеживание когда человек присоединился, и когда ушел, с учетом таких штук, как long poll fallback и несколько табов (дисконнект только когда последний таб закрылся, коннект – только если уже нет открытого таба)
источник

VI

Victor Ivanov in pro.elixir
в целом презенс хорошо работает, но вот с presence_diff происходит то же самое, что Саша описал в своем посте – в какой-то момент остаются зомби, то есть сам Presence.list(topic) вернет %{}, а мой процесс, который слушал presence_diff и вел внутренний учет – он по прежнему считает что есть один зритель
источник

VI

Victor Ivanov in pro.elixir
вот сейчас на проде сделал
ap.keys(state.topics) |> Enum.map(&(AppWeb.Presence.list(&1))) |> Enum.filter(&(is_map(&1) && Enum.empty?(&1))) |> length
12
источник

VI

Victor Ivanov in pro.elixir
Причем сейчас вот начал копать,

deploy@app:log# grep hRW erlang.log.17 | tail -n5
05:48:53.741 [warn]  Removing broadcast:hRW, with 0 keys
06:47:25.863 [warn]  Removing broadcast:hRW, with 0 keys
06:52:31.115 [warn]  Removing broadcast:hRW, with 0 keys
06:57:36.373 [warn]  Removing broadcast:hRW, with 0 keys
07:03:01.241 [warn]  Removing broadcast:hRW, with 0 keys


ro
ot@app:log# grep "6M1" /var/log/nginx/access.log.1 | tail -n5
83.84.3.178 - - [11/Oct/2019:23:39:02 +0000] "GET /phoenix/socket/websocket?broadcast=hRW&subs_secret_key=6M1&subs_id=1375931&vsn=2.0.0 HTTP/1.1" 101 184 "-" "Safari/605.1.15"
83.84.3.178 - - [12/Oct/2019:01:27:15 +0000] "GET /phoenix/socket/websocket?broadcast=hRW&subs_secret_key=6M1&subs_id=1375931&vsn=2.0.0 HTTP/1.1" 101 184 "-" "Safari/605.1.15"
83.84.3.178 - - [12/Oct/2019:03:15:29 +0000] "GET /phoenix/socket/websocket?broadcast=hRW&subs_secret_key=6M1&subs_id=1375931&vsn=2.0.0 HTTP/1.1" 101 184 "-" "Safari/605.1.15"
83.84.3.178 - - [12/Oct/2019:05:03:45 +0000] "GET /phoenix/socket/websocket?broadcast=hRW&subs_secret_key=6M1&subs_id=1375931&vsn=2.0.0 HTTP/1.1" 101 184 "-" "Safari/605.1.15"
83.84.3.178 - - [12/Oct/2019:06:57:31 +0000] "GET /phoenix/socket/websocket?broadcast=hRW&subs_secret_key=6M1&subs_id=1375931&vsn=2.0.0 HTTP/1.1" 101 184 "-" "Safari/605.1.15"

то есть последний дисконнект случился 07:03:01, после этого в логах энжинэкса нет подключений

То есть я не понимаю, откуда вообще эта запись сейчас в стейте процесса взялась 😕
источник

VI

Victor Ivanov in pro.elixir
Учитывая, что Removing broadcast:hRW, with 0 keys пишет в лог вот эта функция
defp drop_topic(state, topic) do
 :ok = AppWeb.Endpoint.unsubscribe(topic)
 Logger.warn("Removing #{topic}, with #{state.topics[topic]} keys")
 %{state | topics: Map.delete(state.topics, topic)}
end

в которой я отписываюсь от presence_diff, непонятно, как там что-то новое могло появиться
источник

ML

Maksim Lapshin in pro.elixir
Значит где-то рейс. Надо сырцы читать
источник

VI

Victor Ivanov in pro.elixir
я бы понял рейс в пределах пары секунд. но тут 5 минут прошло как-никак
источник

ⰿⱄ

ⰿⰰⰾⱏ ⱄⰽⱃⰹⰾⰵⰲⱏ in pro.elixir
Юрий Корушев
#Вакансия

Ростов. Центр
⁃ Ищем Хорошего специалиста в команду.
⁃ Офис, но можно и удаленка.
⁃ FullTime
⁃ Зарплата от 120тыс. До 150
⁃ Разрабатываем мобильное приложение.
Нужно будет Дорабатывать уже существующий продукт. Не переписывать заново, а улучшать то что есть.
Стек: react-native, react, phoenix elixir, postgresql
⁃ Юрий. 89085038168 - пишите мне
великий или папа?
источник

ML

Maksim Lapshin in pro.elixir
Victor Ivanov
я бы понял рейс в пределах пары секунд. но тут 5 минут прошло как-никак
Так у тебя осталось что-то недочищенное и все
источник