Current section

Files

Jump to
pixie lib transports long_polling.ex
Raw

lib/transports/long_polling.ex

defmodule Pixie.Transport.LongPolling do
use GenServer
def start_link do
GenServer.start_link __MODULE__, []
end
def init [] do
{:ok, {nil, []}}
end
def terminate _, state do
dequeue_messages state
:ok
end
# Long polling doesn't stray from the default advice
def handle_call {:advice, advice}, _from, state do
{:reply, advice, state}
end
# Await messages to send back to the adapter, unless there's already
# an adapter process waiting for it.
def handle_call {:await, messages}, from, {nil, queued_messages} do
case enqueue_messages(messages, {from, queued_messages}) do
{nil, _}=state ->
{:noreply, state}
state ->
{:noreply, state, Pixie.timeout}
end
end
# If a second adapter connects while we're still waiting for an old one
# to timeout it will kill the timeout, so we send an empty reply to the
# old adapter to get it to close it's connection then we run the usual
# enqueuing logic.
def handle_call {:await, messages}, from, {old, queued_messages} do
GenServer.reply old, []
case enqueue_messages(messages, {from, queued_messages}) do
{nil, _}=state ->
{:noreply, state}
state ->
{:noreply, state, Pixie.timeout}
end
end
def handle_cast {:enqueue, messages}, state do
{:noreply, enqueue_messages(messages, state)}
end
def handle_info :timeout, state do
{:noreply, dequeue_messages state}
end
defp enqueue_messages messages, {nil, queued_messages} do
{nil, queued_messages ++ messages}
end
defp enqueue_messages messages, {waiting_adapter, queued_messages} do
messages = queued_messages ++ messages
if Pixie.Protocol.respond_immediately? messages do
dequeue_messages {waiting_adapter, messages}
else
{waiting_adapter, messages}
end
end
def dequeue_messages {nil, queued_messages} do
{nil, queued_messages}
end
def dequeue_messages {waiting_adapter, queued_messages} do
GenServer.reply(waiting_adapter, queued_messages)
{nil, []}
end
end