-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathevents.ex
88 lines (74 loc) · 1.71 KB
/
events.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
defmodule WebSocket.Events do
@moduledoc """
"""
use GenEvent
@type event :: {:add_client | :remove_client, pid}
| {:send, tuple, pid}
@type state :: [pid]
## Public API
@doc """
"""
@spec start_link(atom) :: {:ok, pid}
def start_link(ref) do
case GenEvent.start_link(name: ref) do
{:ok, pid} ->
GenEvent.add_handler(ref, __MODULE__, [])
{:ok, pid}
{:error, {:already_started, pid}} ->
{:ok, pid}
end
end
@doc """
"""
@spec subscribe(atom, pid) :: :ok
def subscribe(ref, pid) do
GenEvent.notify(ref, {:add_client, pid})
end
@doc """
"""
@spec unsubscribe(atom, pid) :: :ok
def unsubscribe(ref, pid) do
GenEvent.notify(ref, {:remove_client, pid})
end
@doc """
"""
@spec broadcast(atom, tuple, pid | nil) :: :ok
def broadcast(ref, event, originator) do
GenEvent.notify(ref, {:send, event, originator})
end
@doc """
"""
@spec broadcast!(atom, tuple) :: :ok
def broadcast!(ref, event) do
broadcast(ref, event, nil)
end
@doc """
"""
@spec stop(atom) :: :ok
def stop(ref) do
GenEvent.stop(ref)
end
## Callbacks
@doc """
"""
@spec handle_event(event, state) :: {:ok, state}
def handle_event({:add_client, pid}, clients) do
{:ok, [pid|clients]}
end
def handle_event({:remove_client, pid}, clients) do
{:ok, clients |> Enum.filter(&(&1 != pid))}
end
def handle_event({:send, event, originator}, clients) do
spawn fn ->
_ =
clients
|> Enum.map(&(maybe_send(&1, originator, event)))
end
{:ok, clients}
end
defp maybe_send(client, originator, event) do
unless client == originator do
send client, event
end
end
end