neiam
/apollos_crib
It's Apollo's Crib
public · Issues · Pulls 1 · Labels · Forks · Compare · Actions failure · Badges · Packages
⭐
Log in to mark this repository.
GitLab: a host it can't reach skips the poll, not the worker
eeea624 · Gabe Morell · 2026-11-05 16:25
Files changed
modified
apps/room_gitlab/lib/room_gitlab/gitlab_worker.ex
+23
−21
@@ -172,7 +172,22 @@ defmodule RoomGitlab.Worker do
| 172 | 172 | defp gitlab_path(:commits, id), do: {"/api/v4/projects/#{id}/repository/commits/master", %{}} |
| 173 | 173 | defp gitlab_path(:jobs, id), do: {"/api/v4/projects/#{id}/jobs", %{}} |
| 174 | 174 | |
| 175 | − defp do_gitlab_reqa(uri, token, lookup, id \\ nil) do | |
| 175 | + # Starts a request and files `entry` under its id. One that can't start | |
| 176 | + # (the host unreachable, say) is logged and left out; the next poll tries | |
| 177 | + # again. | |
| 178 | + defp start_req(refs, state, url, pat, {lookup, id}, entry) do | |
| 179 | + case do_gitlab_reqa(url, pat, lookup, id) do | |
| 180 | + {:ok, ref} -> | |
| 181 | + {:ok, fd} = StringIO.open("") | |
| 182 | + Map.put(refs, ref.id, Map.put(entry, :fd, fd)) | |
| 183 | + | |
| 184 | + {:error, %HTTPoison.Error{reason: reason}} -> | |
| 185 | + Logger.warning("GLab::#{state.inst.id} #{lookup} request failed: #{inspect(reason)}") | |
| 186 | + refs | |
| 187 | + end | |
| 188 | + end | |
| 189 | + | |
| 190 | + defp do_gitlab_reqa(uri, token, lookup, id) do | |
| 176 | 191 | {path, params} = gitlab_path(lookup, id) |
| 177 | 192 | |
| 178 | 193 | HTTPoison.get( |
@@ -204,10 +219,7 @@ defmodule RoomGitlab.Worker do
| 204 | 219 | |
| 205 | 220 | with true <- state |> Map.get(:inst, %{}) |> Map.get(:enabled), |
| 206 | 221 | {url, pat} when is_binary(url) and is_binary(pat) <- gitlab_creds(state.inst) do |
| 207 | − {:ok, ref} = do_gitlab_reqa(url, pat, :projects) | |
| 208 | − {:ok, fd} = StringIO.open("") | |
| 209 | − refs = state |> Map.get(:refs) | |
| 210 | − refs = refs |> Map.put(ref.id, %{fd: fd, type: :projects}) | |
| 222 | + refs = start_req(state.refs, state, url, pat, {:projects, nil}, %{type: :projects}) | |
| 211 | 223 | |
| 212 | 224 | {:noreply, state |> Map.put(:refs, refs)} |
| 213 | 225 | else |
@@ -240,17 +252,12 @@ defmodule RoomGitlab.Worker do
| 240 | 252 | def handle_cast(:query_commits, state) do |
| 241 | 253 | with true <- state |> Map.get(:inst, %{}) |> Map.get(:enabled), |
| 242 | 254 | {url, pat} when is_binary(url) and is_binary(pat) <- gitlab_creds(state.inst) do |
| 243 | − all = | |
| 244 | − state.projects | |
| 245 | − |> Enum.map(fn p -> | |
| 255 | + refs = | |
| 256 | + Enum.reduce(state.projects, state.refs, fn p, acc -> | |
| 246 | 257 | Logger.info("GLab::#{state.inst.id} Querying Commits for #{p["name"]}") |
| 247 | − {:ok, ref} = do_gitlab_reqa(url, pat, :commits, p["id"]) | |
| 248 | − {:ok, fd} = StringIO.open("") | |
| 249 | − {ref.id, %{fd: fd, type: :commits, id: p["id"]}} | |
| 258 | + start_req(acc, state, url, pat, {:commits, p["id"]}, %{type: :commits, id: p["id"]}) | |
| 250 | 259 | end) |
| 251 | − |> Map.new() | |
| 252 | 260 | |
| 253 | − refs = state |> Map.get(:refs) |> Map.merge(all) | |
| 254 | 261 | {:noreply, state |> Map.put(:refs, refs)} |
| 255 | 262 | else |
| 256 | 263 | _ -> {:noreply, state} |
@@ -268,18 +275,13 @@ defmodule RoomGitlab.Worker do
| 268 | 275 | "GLab::#{state.inst.id} Querying Jobs for #{length(state.projects)} watched projects" |
| 269 | 276 | ) |
| 270 | 277 | |
| 271 | − all = | |
| 272 | − state.projects | |
| 273 | − |> Enum.map(fn p -> | |
| 278 | + refs = | |
| 279 | + Enum.reduce(state.projects, state.refs, fn p, acc -> | |
| 274 | 280 | id = p["id"] |
| 275 | 281 | Logger.debug("GLab::#{state.inst.id} Querying Jobs for #{id}") |
| 276 | − {:ok, ref} = do_gitlab_reqa(url, pat, :jobs, id) | |
| 277 | − {:ok, fd} = StringIO.open("") | |
| 278 | − {ref.id, %{fd: fd, type: :jobs, id: id}} | |
| 282 | + start_req(acc, state, url, pat, {:jobs, id}, %{type: :jobs, id: id}) | |
| 279 | 283 | end) |
| 280 | − |> Map.new() | |
| 281 | 284 | |
| 282 | − refs = state |> Map.get(:refs) |> Map.merge(all) | |
| 283 | 285 | {:noreply, state |> Map.put(:refs, refs)} |
| 284 | 286 | else |
| 285 | 287 | _ -> |
modified
apps/room_gitlab/test/gitlab_worker_test.exs
+11
−0
@@ -84,6 +84,17 @@ defmodule RoomGitlab.WorkerTest do
| 84 | 84 | end |
| 85 | 85 | end |
| 86 | 86 | |
| 87 | + test "a GitLab it can't reach skips the poll instead of crashing", %{state: state} do | |
| 88 | + # A port nothing listens on: the request fails before it starts. | |
| 89 | + {:ok, sock} = :gen_tcp.listen(0, []) | |
| 90 | + {:ok, port} = :inet.port(sock) | |
| 91 | + :ok = :gen_tcp.close(sock) | |
| 92 | + state = put_in(state.inst.config.url, "http://127.0.0.1:#{port}") | |
| 93 | + | |
| 94 | + assert {:noreply, state} = query_jobs(state, [11, 22]) | |
| 95 | + assert state.refs == %{} | |
| 96 | + end | |
| 97 | + | |
| 87 | 98 | test "what still arrives for a request after its end is dropped", %{state: state} do |
| 88 | 99 | # Its connection, already gone. |
| 89 | 100 | conn = spawn(fn -> :ok end) |
Parents: 328b281