Skip to content

Commit 2bc2011

Browse files
committed
Optimize pager
1 parent 7428de2 commit 2bc2011

7 files changed

Lines changed: 54 additions & 38 deletions

File tree

config/config.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ config :bob,
3131
],
3232
[
3333
module: Bob.Job.DockerChecker,
34-
period: {15, :min}
34+
period: {15, :min},
35+
queue: true
3536
]
3637
],
3738
agent_schedule: [

lib/bob/docker_hub.ex

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,24 @@ defmodule Bob.DockerHub do
99

1010
{:ok, 200, _headers, body} =
1111
Bob.HTTP.retry("DockerHub #{url}", fn ->
12-
:hackney.request(:post, url, headers, Jason.encode!(body), opts)
12+
:hackney.request(:post, url, headers, :json.encode(body), opts)
1313
end)
1414

15-
result = Jason.decode!(body)
15+
{result, _, _} = :json.decode(body)
1616
Application.put_env(:bob, :dockerhub_token, result["token"])
1717
end
1818

1919
def fetch_repo_tags(repo) do
20-
(@dockerhub_url <> "v2/repositories/#{repo}/tags?page=${page}&page_size=100")
21-
|> dockerhub_request()
20+
url = @dockerhub_url <> "v2/repositories/#{repo}/tags?page=${page}&page_size=100"
21+
{:ok, server} = Bob.DockerHub.Pager.start_link(url)
22+
Bob.DockerHub.Pager.wait(server)
2223
end
2324

2425
def fetch_repo_tags_from_cache(repo) do
25-
Bob.DockerHub.Cache.lookup(repo, fn ->
26-
(@dockerhub_url <> "v2/repositories/#{repo}/tags?page=${page}&page_size=100")
27-
|> dockerhub_request()
26+
Bob.DockerHub.Cache.lookup(repo, fn on_result ->
27+
url = @dockerhub_url <> "v2/repositories/#{repo}/tags?page=${page}&page_size=100"
28+
{:ok, server} = Bob.DockerHub.Pager.start_link(url, on_result)
29+
Bob.DockerHub.Pager.wait(server)
2830
end)
2931
end
3032

@@ -40,9 +42,8 @@ defmodule Bob.DockerHub do
4042

4143
case result do
4244
{:ok, 200, _headers, body} ->
43-
body
44-
|> Jason.decode!()
45-
|> parse()
45+
{decoded, _, _} = :json.decode(body)
46+
parse(decoded)
4647

4748
{:ok, 404, _headers, _body} ->
4849
nil
@@ -82,12 +83,8 @@ defmodule Bob.DockerHub do
8283
else
8384
# DockerHub returns dupes sometimes?
8485
archs = result["images"] |> Enum.map(&:binary.copy(&1["architecture"])) |> Enum.uniq()
85-
{result["name"], archs}
86+
{:binary.copy(result["name"]), archs}
8687
end
8788
end
8889

89-
defp dockerhub_request(url) do
90-
{:ok, server} = Bob.DockerHub.Pager.start_link(url)
91-
Bob.DockerHub.Pager.wait(server)
92-
end
9390
end

lib/bob/docker_hub/cache.ex

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,15 @@ defmodule Bob.DockerHub.Cache do
9494
try do
9595
case GenServer.call(__MODULE__, {:lock, repo}, @timeout + @timeout_grace_time) do
9696
:aquired ->
97-
result = fun.()
98-
99-
:ets.insert(
100-
__MODULE__,
101-
Enum.map(result, fn {tag, archs} -> {{:data, repo, tag}, archs} end)
102-
)
97+
on_result = fn results ->
98+
Enum.each(results, fn {tag, archs} ->
99+
:ets.insert(__MODULE__, {{:data, repo, tag}, archs})
100+
end)
101+
end
103102

103+
:ok = fun.(on_result)
104104
:ets.insert(__MODULE__, {{:status, repo}, true})
105-
106-
result
105+
read_from_ets(repo)
107106

108107
:done ->
109108
lookup(repo, fun)
@@ -113,8 +112,12 @@ defmodule Bob.DockerHub.Cache do
113112
end
114113

115114
[{_, true}] ->
116-
:ets.select(__MODULE__, [{{{:data, repo, :"$1"}, :"$2"}, [], [:"$$"]}])
117-
|> Enum.map(&List.to_tuple/1)
115+
read_from_ets(repo)
118116
end
119117
end
118+
119+
defp read_from_ets(repo) do
120+
:ets.select(__MODULE__, [{{{:data, repo, :"$1"}, :"$2"}, [], [:"$$"]}])
121+
|> Enum.map(&List.to_tuple/1)
122+
end
120123
end

lib/bob/docker_hub/pager.ex

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,50 @@ defmodule Bob.DockerHub.Pager do
55
@timeout 60 * 60 * 1000
66

77
def start_link(url) do
8-
GenServer.start_link(__MODULE__, url)
8+
GenServer.start_link(__MODULE__, {url, nil})
9+
end
10+
11+
def start_link(url, on_result) do
12+
GenServer.start_link(__MODULE__, {url, on_result})
913
end
1014

1115
def wait(server) do
1216
GenServer.call(server, :wait, @timeout)
1317
end
1418

15-
def init(url) do
16-
{:ok, next_request(%{url: url, page: 1, tasks: MapSet.new(), results: [], reply: nil})}
19+
def init({url, on_result}) do
20+
{:ok, next_request(%{url: url, on_result: on_result, page: 1, tasks: MapSet.new(), results: [], reply: nil})}
1721
end
1822

1923
def handle_call(:wait, from, state) do
2024
if MapSet.size(state.tasks) == 0 do
21-
{:stop, :normal, Enum.concat(state.results), state}
25+
result = if state.on_result, do: :ok, else: Enum.concat(state.results)
26+
{:stop, :normal, result, state}
2227
else
2328
state = %{state | reply: from}
2429
{:noreply, state}
2530
end
2631
end
2732

2833
def handle_info({ref, {:ok, result}}, state) do
29-
state = %{state | tasks: MapSet.delete(state.tasks, ref), results: [result | state.results]}
34+
state =
35+
if state.on_result do
36+
state.on_result.(result)
37+
state
38+
else
39+
%{state | results: [result | state.results]}
40+
end
41+
42+
state = %{state | tasks: MapSet.delete(state.tasks, ref)}
3043
{:noreply, next_request(state)}
3144
end
3245

3346
def handle_info({ref, :done}, state) do
3447
state = %{state | tasks: MapSet.delete(state.tasks, ref)}
3548

3649
if MapSet.size(state.tasks) == 0 do
37-
GenServer.reply(state.reply, Enum.concat(state.results))
50+
result = if state.on_result, do: :ok, else: Enum.concat(state.results)
51+
GenServer.reply(state.reply, result)
3852
{:stop, :normal, state}
3953
else
4054
{:noreply, state}
@@ -60,8 +74,8 @@ defmodule Bob.DockerHub.Pager do
6074

6175
case result do
6276
{:ok, 200, _headers, body} ->
63-
body = Jason.decode!(body)
64-
{:ok, Enum.flat_map(body["results"], &List.wrap(Bob.DockerHub.parse(&1)))}
77+
{decoded, _, _} = :json.decode(body)
78+
{:ok, Enum.flat_map(decoded["results"], &List.wrap(Bob.DockerHub.parse(&1)))}
6579

6680
{:ok, 404, _headers, _body} ->
6781
:done

lib/bob/github.ex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ defmodule Bob.GitHub do
2727
end
2828

2929
defp response_to_refs(response) do
30-
Enum.map(response, &{&1["name"], &1["commit"]["sha"]})
30+
Enum.map(response, fn item ->
31+
{:binary.copy(item["name"]), :binary.copy(item["commit"]["sha"])}
32+
end)
3133
end
3234

3335
defp github_request(url) do
@@ -39,7 +41,7 @@ defmodule Bob.GitHub do
3941
{:ok, 200, headers, body} =
4042
Bob.HTTP.retry("GitHub #{url}", fn -> :hackney.request(:get, url, [], "", opts) end)
4143

42-
body = Jason.decode!(body)
44+
{body, _, _} = :json.decode(body)
4345

4446
if url = next_link(headers) do
4547
body ++ github_request(url)

lib/bob/router.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ defmodule Bob.Router do
1616
plug(Plug.Parsers,
1717
pass: ["application/json", "application/vnd.bob+erlang"],
1818
parsers: [:json, Bob.Plug.Parser],
19-
json_decoder: Jason
19+
json_decoder: JSON
2020
)
2121

2222
plug(Sentry.PlugContext)

mix.exs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ defmodule Bob.Mixfile do
2323
[
2424
{:ex_aws_s3, "~> 2.0"},
2525
{:hackney, "~> 1.11"},
26-
{:jason, "~> 1.1"},
2726
{:plug_cowboy, "~> 2.0"},
2827
{:porcelain, "~> 2.0"},
2928
{:sentry, "~> 10.2"},

0 commit comments

Comments
 (0)