Я пытаюсь расширить пример Phoenix.Channel.reply/2 из документации Phoenix до полностью рабочего примера асинхронного ответа на push-события канала/сокета Phoenix:
Взято с сайта https://hexdocs.pm/phoenix/Phoenix.Channel.html#reply /2а>:
def handle_in("work", payload, socket) do Worker.perform(payload, socket_ref(socket)) {:noreply, socket} end def handle_info({:work_complete, result, ref}, socket) do reply ref, {:ok, result} {:noreply, socket} end
Я переработал пример следующим образом:
room_channels.ex
...
def handle_in("work", job, socket) do
send worker_pid, {self, job}
{:noreply, socket}
end
def handle_info({:work_complete, result}, socket) do
broadcast socket, "work_complete", %{result: result}
{:noreply, socket}
end
...
рабочий.ex
...
receive do
{pid, job} ->
result = perform(job) # stub
send pid, {:work_complete, result}
end
...
Это решение работает, но оно не основано на создании и передаче socket_ref с socket_ref(socket)
и на Phoenix.Channel.reply/2. Вместо этого он использует Phoenix.Channel.broadcast/3.
В документации подразумевается, что reply/2 специально используется для этого сценария асинхронного ответа на события push сокета:
ответить(arg1, arg2)
Асинхронно отвечает на нажатие сокета.
Полезно, когда вам нужно ответить на push-уведомление, которое иначе нельзя обработать, используя возврат {:reply, {status, payload}, socket} из ваших обратных вызовов handle_in. answer/3 будет использоваться в тех редких случаях, когда вам нужно выполнить работу в другом процессе и ответить, когда закончите, сгенерировав ссылку на отправку с помощью socket_ref/1.
Когда я генерирую и передаю socket_ref и полагаюсь на Phoenix.Channel.reply/2 для асинхронных ответов на push сокета, я вообще не заставляю его работать:
room_channels.ex
...
def handle_in("work", job, socket) do
send worker_pid, {self, job, socket_ref(socket)}
{:noreply, socket}
end
def handle_info({:work_complete, result, ref}, socket) do
reply ref, {:ok, result}
{:noreply, socket}
end
...
рабочий.ex
...
receive do
{pid, job, ref} ->
result = perform(job) # stub
send pid, {:work_complete, result, ref}
end
...
Моя функция room_channels.ex handle_info
вызывается, но reply/2, похоже, не отправляет сообщение по сокету. Я не вижу ни трассировки стека на stderr, ни вывода на stdout, указывающего на ошибку. Более того, отслеживание socket_ref просто увеличивает нагрузку на мой код.
В чем преимущество использования socket_ref и reply/2 по сравнению с моим решением с broadcast/3 и как я могу получить решение с reply/2 > работать?