Skip to content

Commit cc5274f

Browse files
committed
Split processing of docs uploads and search index updating
1 parent 6b63145 commit cc5274f

File tree

11 files changed

+287
-178
lines changed

11 files changed

+287
-178
lines changed

lib/hexdocs.ex

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11
defmodule Hexdocs do
22
@key_regex ~r"docs/(.*)-(.*).tar.gz$"
33

4-
def process_object(key) do
5-
key
6-
|> build_message()
7-
|> send_message()
4+
def process_object(type, key) when type in [:upload, :search] do
5+
publish_message(type, key)
86
end
97

10-
def process_all_objects() do
8+
def process_all_objects(type) when type in [:upload, :search] do
119
(Hexdocs.Store.list(:repo_bucket, "docs/") ++ Hexdocs.Store.list(:repo_bucket, "repos/"))
1210
|> Enum.shuffle()
13-
|> batched_send()
14-
end
15-
16-
defp build_message(key) do
17-
%{
18-
"Records" => [%{"eventName" => "ObjectCreated:Put", "s3" => %{"object" => %{"key" => key}}}]
19-
}
11+
|> batched_send(type)
2012
end
2113

22-
def batched_send(keys) do
14+
def batched_send(keys, type) when type in [:upload, :search] do
2315
keys
2416
|> Stream.filter(&Regex.match?(@key_regex, &1))
25-
|> Stream.map(&build_message/1)
17+
|> Stream.map(&build_message(type, &1))
2618
|> Task.async_stream(&send_message/1, max_concurrency: 10, ordered: false, timeout: 60_000)
2719
|> Stream.run()
2820
end
2921

22+
defp build_message(:upload, key) do
23+
%{"hexdocs:upload" => key}
24+
end
25+
26+
defp build_message(:search, key) do
27+
%{"hexdocs:search" => key}
28+
end
29+
3030
defp send_message(map) do
3131
queue = Application.fetch_env!(:hexdocs, :queue_id)
3232
message = Jason.encode!(map)
@@ -41,4 +41,22 @@ defmodule Hexdocs do
4141
|> Task.async_stream(&send_message/1, max_concurrency: 10, ordered: false, timeout: 60_000)
4242
|> Stream.run()
4343
end
44+
45+
def publish_upload_message(key) do
46+
publish_message(:upload, key)
47+
end
48+
49+
def publish_search_message(key) do
50+
publish_message(:search, key)
51+
end
52+
53+
def publish_message(:upload, key) do
54+
%{"hexdocs:upload" => key}
55+
|> send_message()
56+
end
57+
58+
def publish_message(:search, key) do
59+
%{"hexdocs:search" => key}
60+
|> send_message()
61+
end
4462
end

lib/hexdocs/bucket.ex

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,6 @@ defmodule Hexdocs.Bucket do
305305
|> purge()
306306
end
307307

308-
defp purge_hexdocs_cache("hexpm", package, _versions, :unversioned) do
309-
purge([docspage_unversioned_cdn_key("hexpm", package)])
310-
end
311-
312308
defp purge_hexdocs_cache(_repository, _package, _version, _publish_unversioned?) do
313309
:ok
314310
end

lib/hexdocs/hex_repo.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
defmodule Hexdocs.HexRepo do
22
@callback get_names() :: {:ok, [binary()]} | {:error, term()}
33

4-
@module Application.fetch_env!(:hexdocs, :hex_repo_impl)
4+
@module Application.compile_env(:hexdocs, :hex_repo_impl)
55

6+
@compile {:no_warn_undefined, [{@module, :get_names, 0}]}
67
defdelegate get_names(), to: @module
78
end
89

lib/hexdocs/queue.ex

Lines changed: 115 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -77,76 +77,136 @@ defmodule Hexdocs.Queue do
7777
message
7878
end
7979

80-
@impl true
81-
def handle_batch(_batcher, messages, _batch_info, _context) do
82-
messages
80+
def handle_message(%{data: %{"hexdocs:upload" => key}} = message) do
81+
process_docs(key, :upload)
82+
message
8383
end
8484

85-
defp handle_record(%{"eventName" => "ObjectCreated:" <> _, "s3" => s3}) do
85+
def handle_message(%{data: %{"hexdocs:search" => key}} = message) do
86+
process_docs(key, :search)
87+
message
88+
end
89+
90+
defp process_docs(key, type) do
8691
start = System.os_time(:millisecond)
87-
key = s3["object"]["key"]
88-
Logger.info("OBJECT CREATED #{key}")
92+
event_name = if type == :upload, do: "hexdocs:upload", else: "hexdocs:search"
93+
log_prefix = if type == :upload, do: "UPLOAD", else: "SEARCH INDEX"
94+
95+
Sentry.Context.set_extra_context(%{queue_event: event_name})
96+
Logger.info("#{log_prefix} #{key}")
8997

9098
case key_components(key) do
9199
{:ok, repository, package, version} ->
92100
Sentry.Context.set_extra_context(%{
93-
queue_event: "ObjectCreated",
101+
queue_event: event_name,
94102
repository: repository,
95103
package: package,
96104
version: version
97105
})
98106

99107
body = Hexdocs.Store.get(:repo_bucket, key)
100108

101-
{version, all_versions} =
102-
if package in @special_package_names do
103-
version =
104-
case Version.parse(version) do
105-
{:ok, version} ->
106-
version
107-
108-
# main or MAJOR.MINOR
109-
:error ->
110-
version
111-
end
112-
113-
all_versions = Hexdocs.SourceRepo.versions!(Map.fetch!(@special_packages, package))
114-
{version, all_versions}
115-
else
116-
version = Version.parse!(version)
117-
all_versions = all_versions(repository, package)
118-
{version, all_versions}
109+
case type do
110+
:upload ->
111+
process_upload(key, repository, package, version, body, start)
112+
113+
:search ->
114+
process_search(key, package, version, body, start)
115+
end
116+
117+
:error ->
118+
Logger.info("#{key}: skip")
119+
end
120+
end
121+
122+
defp process_upload(key, repository, package, version, body, start) do
123+
{version, all_versions} =
124+
if package in @special_package_names do
125+
version =
126+
case Version.parse(version) do
127+
{:ok, version} ->
128+
version
129+
130+
# main or MAJOR.MINOR
131+
:error ->
132+
version
119133
end
120134

121-
case Hexdocs.Tar.unpack(body, repository: repository, package: package, version: version) do
122-
{:ok, files} ->
123-
files = rewrite_files(files)
135+
all_versions = Hexdocs.SourceRepo.versions!(Map.fetch!(@special_packages, package))
136+
{version, all_versions}
137+
else
138+
version = Version.parse!(version)
139+
all_versions = all_versions(repository, package)
140+
{version, all_versions}
141+
end
142+
143+
case Hexdocs.Tar.unpack(body, repository: repository, package: package, version: version) do
144+
{:ok, files} ->
145+
files = rewrite_files(files)
146+
147+
Hexdocs.Bucket.upload(
148+
repository,
149+
package,
150+
version,
151+
all_versions,
152+
files
153+
)
154+
155+
if Hexdocs.Utils.latest_version?(package, version, all_versions) do
156+
update_index_sitemap(repository, key)
157+
update_package_sitemap(repository, key, package, files)
158+
update_package_names_csv(repository)
159+
end
124160

125-
Hexdocs.Bucket.upload(
126-
repository,
127-
package,
128-
version,
129-
all_versions,
130-
files
131-
)
161+
elapsed = System.os_time(:millisecond) - start
162+
Logger.info("FINISHED UPLOADING DOCS #{key} #{elapsed}ms")
132163

133-
if Hexdocs.Utils.latest_version?(package, version, all_versions) do
134-
update_index_sitemap(repository, key)
135-
update_package_sitemap(repository, key, package, files)
136-
update_package_names_csv(repository)
137-
end
164+
{:error, reason} ->
165+
Logger.error("Failed unpack #{repository}/#{package} #{version}: #{reason}")
166+
end
167+
end
138168

139-
if repository == "hexpm" do
140-
update_search_index(key, package, version, files)
141-
end
169+
defp process_search(key, package, version, body, start) do
170+
version = Version.parse!(version)
142171

143-
elapsed = System.os_time(:millisecond) - start
144-
Logger.info("FINISHED UPLOADING AND INDEXING DOCS #{key} #{elapsed}ms")
172+
case Hexdocs.Tar.unpack(body, package: package, version: version) do
173+
{:ok, files} ->
174+
update_search_index(key, package, version, files)
145175

146-
{:error, reason} ->
147-
Logger.error("Failed unpack #{repository}/#{package} #{version}: #{reason}")
176+
elapsed = System.os_time(:millisecond) - start
177+
Logger.info("FINISHED INDEXING DOCS #{key} #{elapsed}ms")
178+
179+
{:error, reason} ->
180+
Logger.error("Failed unpack #{package} #{version}: #{reason}")
181+
end
182+
end
183+
184+
@impl true
185+
def handle_batch(_batcher, messages, _batch_info, _context) do
186+
messages
187+
end
188+
189+
defp handle_record(%{"eventName" => "ObjectCreated:" <> _, "s3" => s3}) do
190+
key = s3["object"]["key"]
191+
Logger.info("OBJECT CREATED #{key}")
192+
193+
case key_components(key) do
194+
{:ok, repository, _package, _version} ->
195+
Sentry.Context.set_extra_context(%{
196+
queue_event: "ObjectCreated",
197+
repository: repository
198+
})
199+
200+
# Publish upload message
201+
publish_message(%{"hexdocs:upload" => key})
202+
203+
# Publish search message for hexpm repository
204+
if repository == "hexpm" do
205+
publish_message(%{"hexdocs:search" => key})
148206
end
149207

208+
Logger.info("PUBLISHED MESSAGES FOR #{key}")
209+
150210
:error ->
151211
:skip
152212
end
@@ -281,6 +341,14 @@ defmodule Hexdocs.Queue do
281341
end
282342
end
283343

344+
defp publish_message(map) do
345+
queue = Application.fetch_env!(:hexdocs, :queue_id)
346+
message = Jason.encode!(map)
347+
348+
ExAws.SQS.send_message(queue, message)
349+
|> ExAws.request!()
350+
end
351+
284352
@doc false
285353
def paths_for_sitemaps() do
286354
key_regex = ~r"docs/(.*)-(.*).tar.gz$"

lib/hexdocs/search/search.ex

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ defmodule Hexdocs.Search do
4242
json
4343

4444
_ when is_binary(search_data_js) ->
45-
Logger.error("Unexpected search_data format for #{package} #{version}")
46-
nil
45+
raise "Unexpected search_data format for #{package} #{version}"
4746

4847
nil ->
4948
nil
@@ -55,12 +54,7 @@ defmodule Hexdocs.Search do
5554
:json.decode(search_data_json)
5655
catch
5756
_kind, reason ->
58-
Logger.error(
59-
"Failed to decode search data json for #{package} #{version}: " <>
60-
inspect(reason)
61-
)
62-
63-
nil
57+
raise "Failed to decode search data json for #{package} #{version}: #{inspect(reason)}"
6458
end
6559
end
6660

@@ -73,11 +67,7 @@ defmodule Hexdocs.Search do
7367
nil
7468

7569
_ ->
76-
Logger.error(
77-
"Failed to extract search items and proglang from search data for #{package} #{version}"
78-
)
79-
80-
nil
70+
raise "Failed to extract search items and proglang from search data for #{package} #{version}"
8171
end
8272
end
8373

lib/hexdocs/search/typesense.ex

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,15 @@ defmodule Hexdocs.Search.Typesense do
3333
:ok
3434

3535
%{"success" => false, "error" => error, "document" => document} ->
36-
Logger.error(
37-
"Failed to index search item for #{package} #{version} for document #{inspect(document)}: #{inspect(error)}"
38-
)
36+
raise "Failed to index search item for #{package} #{version} for document #{inspect(document)}: #{inspect(error)}"
3937
end
4038
end)
4139

4240
{:ok, status, _resp_headers, _body} ->
43-
Logger.error("Failed to index search items for #{package} #{version}: status=#{status}")
41+
raise "Failed to index search items for #{package} #{version}: status=#{status}"
4442

4543
{:error, reason} ->
46-
Logger.error("Failed to index search items #{package} #{version}: #{inspect(reason)}")
44+
raise "Failed to index search items #{package} #{version}: #{inspect(reason)}"
4745
end
4846
end
4947

@@ -60,12 +58,10 @@ defmodule Hexdocs.Search.Typesense do
6058
:ok
6159

6260
{:ok, status, _resp_headers, _body} ->
63-
Logger.error("Failed to delete search items for #{package} #{version}: status=#{status}")
61+
raise "Failed to delete search items for #{package} #{version}: status=#{status}"
6462

6563
{:error, reason} ->
66-
Logger.error(
67-
"Failed to delete search items for #{package} #{version}: #{inspect(reason)}"
68-
)
64+
raise "Failed to delete search items for #{package} #{version}: #{inspect(reason)}"
6965
end
7066
end
7167

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ defmodule Hexdocs.MixProject do
4646
{:jason, "~> 1.1"},
4747
{:logster, "~> 1.0"},
4848
{:plug_cowboy, "~> 2.0"},
49-
{:sentry, "~> 10.8"},
49+
{:sentry, "~> 11.0"},
5050
{:ssl_verify_fun, "~> 1.1", manager: :rebar3, override: true},
5151
{:sweet_xml, "~> 0.7.0"},
5252
{:hex_core, "~> 0.11.0"},

0 commit comments

Comments
 (0)