More error handling, retry automatically on disconnected

This commit is contained in:
Shadowfacts 2024-04-07 10:37:46 -04:00
parent 257ea3e47e
commit fdf59f660a
3 changed files with 39 additions and 7 deletions

View File

@ -8,8 +8,20 @@ defmodule TuskerPush.Apns do
with {:ok, body} <- Jason.encode(payload, pretty_print: false), with {:ok, body} <- Jason.encode(payload, pretty_print: false),
req <- make_request(registration, body), req <- make_request(registration, body),
{:ok, resp} <- Finch.request(req, TuskerPush.Finch) do {:ok, resp} <- Finch.request(req, TuskerPush.Finch) do
handle_response(resp, registration.apns_environment) handle_response(resp, registration, payload)
else else
{:error, %Finch.Error{reason: :connection_closed}} ->
Logger.warning("Apns Finch connection_closed, retrying")
__MODULE__.send(registration, payload)
{:error, %Finch.Error{reason: :disconnected}} ->
Logger.warning("Apns Finch disconnected, retrying")
__MODULE__.send(registration, payload)
{:error, %Mint.TransportError{reason: :closed}} ->
Logger.warning("Apns Mint transport closed, retrying")
__MODULE__.send(registration, payload)
{:error, reason} -> {:error, reason} ->
{:error, reason} {:error, reason}
end end
@ -36,10 +48,10 @@ defmodule TuskerPush.Apns do
) )
end end
@spec handle_response(Finch.Response.t(), :development | :production) :: :ok | {:error, term()} @spec handle_response(Finch.Response.t(), Registration.t(), Map.t()) :: :ok | {:error, term()}
defp handle_response(resp, env) do defp handle_response(resp, registration, payload) do
maybe_log_unique_id(resp, env) maybe_log_unique_id(resp, registration.apns_environment)
if resp.status in 200..299 do if resp.status in 200..299 do
:ok :ok
@ -53,11 +65,22 @@ defmodule TuskerPush.Apns do
resp.body resp.body
end end
Logger.error("Received #{resp.status} with #{info}") case {resp.status, info} do
{403, %{reason: "ExpiredProviderToken"}} ->
Logger.warning("Expired provider token, retrying")
__MODULE__.send(registration, payload)
{410, %{reason: "Unregistered"}} ->
Logger.warning("Device token unregistered")
{:error, :device_token_unregistered}
_ ->
Logger.error("Received #{resp.status} with #{inspect(info)}")
{:error, "unexpected status #{resp.status}"} {:error, "unexpected status #{resp.status}"}
end end
end end
end
@spec maybe_log_unique_id(Finch.Response.t(), :development | :production) :: :ok @spec maybe_log_unique_id(Finch.Response.t(), :development | :production) :: :ok

View File

@ -2,6 +2,8 @@ defmodule TuskerPush.Forwarder do
alias TuskerPush.Apns alias TuskerPush.Apns
alias TuskerPush.Registration alias TuskerPush.Registration
require Logger
@spec forward(Registration.t(), binary(), String.t(), String.t()) :: :ok | {:error, term()} @spec forward(Registration.t(), binary(), String.t(), String.t()) :: :ok | {:error, term()}
def forward(%Registration{push_version: 1} = registration, body, salt, key) do def forward(%Registration{push_version: 1} = registration, body, salt, key) do
payload = %{ payload = %{
@ -18,6 +20,8 @@ defmodule TuskerPush.Forwarder do
"v" => 1 "v" => 1
} }
Logger.debug("Sending #{inspect(payload)}")
Apns.send(registration, payload) Apns.send(registration, payload)
end end
end end

View File

@ -20,7 +20,7 @@ defmodule TuskerPushWeb.PushController do
{:expired, registration} -> {:expired, registration} ->
TuskerPush.unregister(registration) TuskerPush.unregister(registration)
send_resp(conn, 400, "unregistered") send_resp(conn, 400, "expired")
{:encoding, encoding} -> {:encoding, encoding} ->
Logger.warning("Unexpected encoding: #{inspect(encoding)}") Logger.warning("Unexpected encoding: #{inspect(encoding)}")
@ -42,6 +42,11 @@ defmodule TuskerPushWeb.PushController do
Logger.warning("Missing key") Logger.warning("Missing key")
send_resp(conn, 400, "missing key") send_resp(conn, 400, "missing key")
{:forward, {:error, :device_token_unregistered}} ->
Logger.debug("APNS device token unregistered, removing registration")
TuskerPush.unregister(id)
send_resp(conn, 400, "apns unregistered")
{:forward, {:error, reason}} -> {:forward, {:error, reason}} ->
Logger.error("Sending notification: #{inspect(reason)}") Logger.error("Sending notification: #{inspect(reason)}")
send_resp(conn, 500, "failed to send") send_resp(conn, 500, "failed to send")