Skip to content

Commit cd3e1d3

Browse files
committed
Ensure all autoretries dont happen within the genserver's process so that the genserver is available to answer other genservers
1 parent 411c4f2 commit cd3e1d3

File tree

5 files changed

+53
-22
lines changed

5 files changed

+53
-22
lines changed

config/config.exs

+5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ config :slack_coder, SlackCoder.Guardian,
4747
serializer: SlackCoder.Guardian,
4848
secret_key: "nUzHV60AayAhzalp8iRhB5FokH7tcVv67ozi6PTjO0PZcUtyO4uoQRfcrVk5bc54"
4949

50+
config :httpoison_retry,
51+
wait: 15_000,
52+
max_attempts: 5,
53+
include_404s: true
54+
5055
config :scrivener_html,
5156
routes_helper: SlackCoder.Router.Helpers
5257

config/dev.exs

+5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ config :logger,
4242
# and calculating stacktraces is usually expensive.
4343
config :phoenix, :stacktrace_depth, 20
4444

45+
# Make dev mode more likely to fail but with still a little bit of error protection
46+
config :httpoison_retry,
47+
wait: 1_000,
48+
max_attempts: 2
49+
4550
database = if(System.get_env("DATA_DB_USER") == "nanobox", do: "gonano", else: "slack_coder_dev")
4651
# Configure your database
4752
config :slack_coder, SlackCoder.Repo,

lib/services/pr_service.ex

+8-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@ defmodule SlackCoder.Services.PRService do
2626
|> Repo.insert_or_update()
2727
|> case do
2828
{:ok, pr} ->
29-
{:ok, pr |> check_failed() |> notifications() |> broadcast(Map.to_list(changeset.changes), changeset.data.id == nil)}
29+
pr_worker = self()
30+
pr = pr |> notifications() |> broadcast(Map.to_list(changeset.changes), changeset.data.id == nil)
31+
# This could take some time with the autoretry, so don't hold up the PR worker or others tryig to
32+
# contact the worker will time out since the PR worker can be sleeping
33+
Task.Supervisor.start_child SlackCoder.TaskSupervisor, fn ->
34+
GenServer.cast(pr_worker, {:save, pr |> check_failed()})
35+
end
36+
{:ok, pr}
3037
errored_changeset ->
3138
Logger.error "Unable to save PR: #{inspect errored_changeset}\n#{inspect changeset.data}"
3239
errored_changeset

lib/slack_coder/github/watchers/merge_conflict.ex

+31-21
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ defmodule SlackCoder.Github.Watchers.MergeConflict do
1616
GenServer.start_link(__MODULE__, %{prs: []}, name: __MODULE__)
1717
end
1818

19-
@normal_wait_time 60 * 5 * 1_000
19+
@normal_wait_time 60 * 1 * 1_000
2020
def init(state) do
2121
Process.send_after(self(), :check_conflicts, @normal_wait_time)
2222
{:ok, state}
@@ -95,28 +95,38 @@ defmodule SlackCoder.Github.Watchers.MergeConflict do
9595
{:noreply, state}
9696
end
9797
def handle_info(:check_conflicts, %{prs: prs} = state) do
98-
remaining_prs =
99-
case SlackCoder.Github.query(@mergeable_query, variable_params(prs)) do
100-
{:ok, %{"data" => data}} when is_map(data) ->
101-
response_prs = Map.values(data) |> Enum.map(&(&1["pullRequest"])) |> Enum.filter(&(&1))
98+
# This could take some time with the autoretry, so don't hold up the genserver or others tryig to
99+
# contact the genserver will time out since the genserver can be sleeping
100+
s = self()
101+
Task.Supervisor.start_child SlackCoder.TaskSupervisor, fn ->
102+
remaining_prs =
103+
case SlackCoder.Github.query(@mergeable_query, variable_params(prs)) do
104+
{:ok, %{"data" => data}} when is_map(data) ->
105+
response_prs = Map.values(data) |> Enum.map(&(&1["pullRequest"])) |> Enum.filter(&(&1))
102106

103-
Enum.reject(prs, fn(pr) ->
104-
response = Enum.find(response_prs, &(&1["number"] == pr.number && &1["repository"]["name"] == pr.repo && &1["repository"]["owner"]["login"] == pr.owner))
105-
if response && response["mergeable"] != @unknown do
106-
Logger.debug [IO.ANSI.green, IO.ANSI.bright, "[MergeConflict] ", IO.ANSI.normal, IO.ANSI.default_color, "Status of PR-", to_string(pr.number), " ", response["mergeable"]]
107-
pr
108-
|> Github.find_watcher()
109-
|> PullRequest.update_sync(%{"mergeable_state" => response["mergeable"] |> convert_mergeable()})
110-
end
111-
end)
112-
%HTTPoison.Error{reason: :timeout} ->
113-
# Ignore (Rate limiting)
114-
prs
115-
error ->
116-
Logger.warn "Received unexpected response from Github: #{inspect error}"
117-
prs
118-
end
107+
Enum.reject(prs, fn(pr) ->
108+
response = Enum.find(response_prs, &(&1["number"] == pr.number && &1["repository"]["name"] == pr.repo && &1["repository"]["owner"]["login"] == pr.owner))
109+
if response && response["mergeable"] != @unknown do
110+
Logger.debug [IO.ANSI.green, IO.ANSI.bright, "[MergeConflict] ", IO.ANSI.normal, IO.ANSI.default_color, "Status of PR-", to_string(pr.number), " ", response["mergeable"]]
111+
pr
112+
|> Github.find_watcher()
113+
|> PullRequest.update_sync(%{"mergeable_state" => response["mergeable"] |> convert_mergeable()})
114+
end
115+
end)
116+
%HTTPoison.Error{reason: :timeout} ->
117+
# Ignore (Rate limiting)
118+
prs
119+
error ->
120+
Logger.warn "Received unexpected response from Github: #{inspect error}"
121+
prs
122+
end
123+
send(s, {:check_conflict_complete, remaining_prs})
124+
end
119125

126+
{:noreply, state}
127+
end
128+
129+
def handle_info({:check_conflict_complete, remaining_prs}, state) do
120130
Process.send_after(self(), :check_conflicts, check_conflict_timeout(remaining_prs))
121131
{:noreply, Map.put(state, :prs, remaining_prs)}
122132
end

lib/slack_coder/github/watchers/pull_request.ex

+4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ defmodule SlackCoder.Github.Watchers.PullRequest do
5959
{:noreply, {pr |> PRService.check_failed(), callouts}}
6060
end
6161

62+
def handle_cast({:save, pr}, {_pr, callouts}) do
63+
{:noreply, {pr, callouts}}
64+
end
65+
6266
def handle_cast({:build, sha, url, state}, {%PR{sha: sha} = pr, callouts}) do
6367
{:ok, pr} = pr |> PR.reg_changeset(%{build_status: state, build_url: url}) |> PRService.save
6468
{:noreply, {pr, callouts}}

0 commit comments

Comments
 (0)