Packages
pigeon
2.0.1
2.0.1
2.0.0
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.1.0-rc.1
1.1.0-rc.0
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.13.1
0.13.0
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.8.0
0.7.0
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
iOS (APNS), Android (FCM), and Amazon Android (ADM) push notifications for Elixir.
Current section
Files
Jump to
Current section
Files
lib/pigeon.ex
defmodule Pigeon do
@moduledoc """
iOS (APNS), Android (FCM), and Amazon Android (ADM) push notifications for Elixir.
## Getting Started
Check the module documentation for your push notification service.
- `Pigeon.ADM` - Amazon Android.
- `Pigeon.APNS` - Apple iOS.
- `Pigeon.FCM` - Firebase Cloud Messaging v1 API.
## Creating Dynamic Runtime Dispatchers
Pigeon can spin up dynamic dispatchers for a variety of advanced use-cases, such as
supporting dozens of dispatcher configurations or custom connection pools.
See `Pigeon.Dispatcher` for instructions.
## Writing a Custom Dispatcher Adapter
Want to write a Pigeon adapter for an unsupported push notification service?
See `Pigeon.Adapter` for instructions.
"""
alias Pigeon.Tasks
@default_timeout 5_000
@typedoc ~S"""
Async callback for push notifications response.
## Examples
handler = fn(%Pigeon.ADM.Notification{response: response}) ->
case response do
:success ->
Logger.debug "Push successful!"
:unregistered ->
Logger.error "Bad device token!"
_error ->
Logger.error "Some other error happened."
end
end
n = Pigeon.ADM.Notification.new("token", %{"message" => "test"})
Pigeon.ADM.push(n, on_response: handler)
"""
@type on_response ::
(notification -> no_return)
| {module, atom}
| {module, atom, [any]}
@type notification :: %{
:__struct__ => atom(),
:__meta__ => Pigeon.Metadata.t(),
optional(atom()) => any()
}
@typedoc ~S"""
Options for sending push notifications.
- `:on_response` - Optional async callback triggered on receipt of push.
See `t:on_response/0`
- `:timeout` - Push timeout. Defaults to 5000ms.
"""
@type push_opts :: [
on_response: on_response | nil,
timeout: non_neg_integer
]
@doc """
Returns the configured default pool size for Pigeon dispatchers.
To customize this value, include the following in your config/config.exs:
config :pigeon, :default_pool_size, 5
"""
@spec default_pool_size :: pos_integer
def default_pool_size() do
Application.get_env(:pigeon, :default_pool_size, 5)
end
@doc """
Returns the configured JSON encoding library for Pigeon.
To customize the JSON library, include the following in your config/config.exs:
config :pigeon, :json_library, Jason
"""
@spec json_library :: module
def json_library do
Application.get_env(:pigeon, :json_library, Jason)
end
@spec push(pid | atom, notification :: notification, push_opts) ::
notification :: struct | no_return
@spec push(pid | atom, notifications :: [notification, ...], push_opts) ::
notifications :: [struct, ...] | no_return
@doc """
Sends a push notification with given options.
"""
def push(pid, notifications, opts \\ [])
def push(pid, notifications, opts) when is_list(notifications) do
for n <- notifications, do: push(pid, n, opts)
end
def push(pid, notification, opts) do
if Keyword.has_key?(opts, :on_response) do
on_response = Keyword.get(opts, :on_response)
notification = put_on_response(notification, on_response)
push_async(pid, notification)
else
timeout = Keyword.get(opts, :timeout, @default_timeout)
push_sync(pid, notification, timeout)
end
end
defp push_sync(pid, notification, timeout) do
myself = self()
ref = :erlang.make_ref()
on_response = fn x -> send(myself, {:"$push", ref, x}) end
notification = put_on_response(notification, on_response)
push_async(pid, notification)
receive do
{:"$push", ^ref, x} -> x
after
timeout -> %{notification | response: :timeout}
end
end
defp push_async(pid, notification) do
case Pigeon.Registry.next(pid) do
nil ->
Tasks.process_on_response(%{notification | response: :not_started})
pid ->
send(pid, {:"$push", notification})
:ok
end
end
defp put_on_response(notification, on_response) do
meta = %{notification.__meta__ | on_response: on_response}
%{notification | __meta__: meta}
end
end