Skip to content

Instantly share code, notes, and snippets.

@romul
Created June 24, 2015 09:22
Show Gist options
  • Save romul/97d1b6f05b0937a9c4eb to your computer and use it in GitHub Desktop.
Save romul/97d1b6f05b0937a9c4eb to your computer and use it in GitHub Desktop.
Draft implementation of Faye Client in Elixir
defmodule MyApp.Faye do
@name __MODULE__
@unconnected 1
@connecting 2
@connected 3
@disconnected 4
@handshake_params %{
channel: "/meta/handshake",
version: "1.0",
supportedConnectionTypes: ["long-polling"]
}
@request_headers [{"Content-Type", "application/json"}]
use HTTPoison.Base
defmodule State do
defstruct url: nil, state: @unconnected, client_id: nil
end
def start_link do
faye_state = %State{url: Application.get_env(:faye, :url)}
Agent.start_link(fn -> faye_state end, name: @name)
handshake
{:ok, self}
end
def publish(channel, params) do
spawn fn ->
if Agent.get(@name, fn faye -> faye.url end) != @connected do
handshake
end
send %{
"channel" => channel,
"data" => params,
"clientId" => Agent.get(@name, fn faye -> faye.client_id end)
}
end
end
defp handshake do
Agent.update(@name, &(%{&1 | :state => @connecting}))
case send(@handshake_params) do
{:ok, %HTTPoison.Response{body: body}} ->
[data|_] = Poison.decode!(body)
Agent.update(@name, &(%{&1 | :client_id => Dict.get(data, "clientId")}))
Agent.update(@name, &(%{&1 | :state => @connected}))
{:error, _} ->
IO.puts("Handshake failed. Retry in 10 seconds")
Agent.update(@name, &(%{&1 | :state => @unconnected}))
:timer.sleep(10000)
handshake
end
end
defp send(params) do
post(Agent.get(@name, fn faye -> faye.url end),
params |> to_json,
@request_headers)
end
defp to_json(payload) do
Poison.encode!(payload)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment