2016-08-05 1 views
1

Я использую феникс-фреймворк для своего приложения Elixir с соединением WebSocket. У меня две разные темы: одна для пользователей и другая для администраторов. Администратор должен видеть, какие пользователи присутствуют. Я решил использовать модуль Presence от Phoenix. К сожалению, вы можете отправить текущее состояние Presence только в сокет, который начинает отслеживать.Можно ли отслеживать присутствие пользователей из разных тем?

Пример код:

def join("users", params, socket) do 
    socket |> assign(:user_id, params[:user_id]) 

    send(self, :after_join) 
    {:ok, socket} 
end 

def join("admins", _params, socket) do 
    {:ok, socket} 
end 

def handle_info(:after_join, socket) do 
    push(socket, "presence_state", Presence.list(socket)) 

    {:ok, _} = Presence.track(socket, socket.assigns[:user_id], %{ 
    online_at: inspect(System.system_time(:seconds)) 
    }) 

    {:noreply, socket} 
end 

Я хочу слушать событие в фронтальном применении админы для изменения присутствия. Можно ли это сделать с Phoenix.Presence?

ответ

3

Вы можете использовать YourApp.Endpoint.broadcast/3:

def handle_info(:after_join, socket) do 

    {:ok, _} = Presence.track(socket, socket.assigns[:user_id], %{ 
    online_at: inspect(System.system_time(:seconds)) 
    }) 
    YourApp.Endpoint.broadcast "admins", "presence_state", Presence.list(socket) 

    {:noreply, socket} 
end 

и слушать presence_state от вашего adminChannel:

adminChannel.on("presence_state", state => { 
    presences = Presence.syncState(state) 
    // doSomethingWithPresences 
} 

Вы должны отделить YourApp.AdminChannel и YourApp.UserChannel

Когда ваш клиент получит presence_diff event.You может нажать его к пользовательскому каналу и снова использовать Endpoint.broadcast/3:

userChannel.on("presence_diff", diff => { 
    userChannel.push("presence_diff", diff) 
} 

в YourApp.UserChannel:

def handle_in("presence_diff", diff, socket) do 
    YourApp.Endpoint.broadcast "admins", "presence_diff", diff 
    {:noreply, socket} 
end 

И теперь вы можете слушать presence_diff событие:

adminChannel.on("presence_diff", diff => { 
    presences = Presence.syncDiff(diff) 
    render(presences) 
} 
+0

Это было полезно. У вас есть идея, как обрабатывать событие «presence_diff»? Я получаю присутствие, когда пользователь подключается к каналу, но когда администратор будет регистрировать позже этого пользователя, он получит пустое состояние присутствия. – mirox

+0

Я отредактировал ответ. Упование, которое помогает – TheAnh

+0

Я пробовал вашу идею, и она не работает должным образом. Когда пользователь выходит из режима присутствия, что часы администратора не обновляются. Это происходит, когда это один пользователь онлайн. Просто нет другого пользователя, который уведомляет канал администратора о различии присутствия. Я выкопаю его, я увидел, что если у вас есть канал, то его кабриолет будет присутствовать, см. Https://hexdocs.pm/phoenix/Phoenix.Presence.html#c:track/4. Так что теперь мне нужно получить каналы pid. – mirox

1

Если вы настраиваете наличие отслеживания в одном из обработчиков обратного вызова телеканала (как handle_info/2), вы можете добавить отслеживание по произвольной теме:

Presence.track(self(), "admins", socket.assigns[:user_id], %{some_metadata: "whatever"})

Затем, в другом месте в другом процессе вы можете подписаться на admins тему, как:

YourApp.Endpoint.subscribe("admins"), в этот момент, что процесс начнет получать presence_diff сообщения.

Смежные вопросы