2017-02-16 2 views
0

Часть требований Apple к видеочату заключается в том, что обе стороны должны явно нажать «принять», прежде чем они смогут войти в видеочат.Phoenix + Channels: Как обеспечить, чтобы обе стороны «приняли»?

У меня есть кнопка, которая вызывает эту функцию при нажатии "принять":

Мое мнение:

channel.on("match_accepted", payload => { 
    if (payload.matched_client_email == matchedClientEmail) { 
     this.setState({ clientQueued: true }); 
    } 
    }); 

    acceptMatch() { 
    ... 
    if (this.state.clientQueued) { 
     // start video session 
    } else { 
     // notify the other person that you have accepted 
     channel.push("accept_match", { 
     "matched_client_email": matchedClientEmail, 
     }); 
    } 
    } 

Вызов канала:

def handle_in("accept_match", %{ "matched_client_email" => matched_client_email }, socket) do 
    # broadcast to the other person that you have accepted 
    VideoChat.Endpoint.broadcast(
     "user_pool:#{matched_client_email}", 
     "match_accepted", 
     %{ matched_client_email: socket.assigns[:email] } 
    ) 

    {:noreply, socket} 
    end 

Это очень хрупким, так как у меня нет способ гарантировать, что state (это реактивная вещь) будет обновляться к тому времени, когда человек нажмет кнопку. Поэтому они могли бы одновременно одновременно принять и просто висеть в подвешенном состоянии.

Есть ли лучший способ гарантировать, что оба человека нажали, принять? Я думал о том, чтобы сделать это через библиотеку Presence Phoenix и сохранить свойство в ключе metas, но с его нынешним способом у меня все клиенты находятся в своих собственных каналах/комнатах, поэтому каждый список присутствия будет иметь только одну запись (.. .правильно?).

ответ

1

На высоком уровне кажется, что сервер чата должен быть тем, который определяет, что оба пользователя приняли. Итак:

user1 presses accept -> sends "accept_match" to chat server 
user2 presses accept -> sends "accept_match" to chat server 

chat server sees both has accepted 
    -> broadcasts "start_session" 

Вот краткий пример использования Agent за сеанс и вещания как если бы они были приняты. Существует наиболее определенно более простой/более эффективный способ сделать это.

Вид:

channel.on("session_started", payload => { 
    if (payload.matched_client_email == matchedClientEmail) { 
     this.setState({ sessionStarted: true }); 
     // start video session 
    } 
}); 

acceptMatch() { 
    channel.push("accept_match", { 
     "matched_client_email": matchedClientEmail, 
    }); 
} 

вызов Канал:

def handle_in("accept_match", %{ "matched_client_email" => matched_client_email }, socket) do 
    Agent.update agent_session_pid, fn state -> 
    Map.put(state, socket.assigns[:email], true) 
    end 
    # check to see if we should broadcast acceptance 
    matched_accepted = Agent.get(agent_session_pid, &(Map.get(&1, matched_client_email))) 
    case matched_accepted do 
    true -> 
     # broadcast to each user 
     VideoChat.Endpoint.broadcast(
     "user_pool:#{matched_client_email}", 
     "session_started", 
     %{ matched_client_email: socket.assigns[:email] } 
     ) 

     VideoChat.Endpoint.broadcast(
     "user_pool:#{socket.assigns[:email]}", 
     "session_started", 
     %{ matched_client_email: } 
     ) 

     {:noreply, socket} 
    _ -> 
     {:noreply, socket} 
    end 
end 
+0

Wow это является удивительным. Спасибо! Что такое агент? И откуда происходит «agent_session_pid»? – Edmund

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