Skip to content

Commit 2913b54

Browse files
committed
Don't keep patches in memory
1 parent 31ac7b5 commit 2913b54

File tree

1 file changed

+18
-89
lines changed

1 file changed

+18
-89
lines changed

lib/diff_web/live/diff_live_view.ex

Lines changed: 18 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,12 @@ defmodule DiffWeb.DiffLiveView do
4545
</div>
4646
<% end %>
4747
48-
<%= if @search_query != "" do %>
49-
<div class="search-form">
50-
<input
51-
class="search-input"
52-
type="text"
53-
placeholder="Search files..."
54-
phx-keyup="search"
55-
phx-debounce="300"
56-
value={@search_query}
57-
/>
58-
</div>
59-
<% end %>
48+
6049
6150
<div class="ghd-container" id="patch-list">
6251
<%= for patch_id <- @loaded_patches do %>
6352
<div id={"patch-#{patch_id}"}>
64-
<%= raw(Map.get(@patch_contents, patch_id, "")) %>
53+
<%= raw(load_patch_content(@package, @from, @to, patch_id)) %>
6554
</div>
6655
<% end %>
6756
@@ -152,10 +141,8 @@ defmodule DiffWeb.DiffLiveView do
152141
all_patch_ids: patch_ids,
153142
loaded_patches: initial_patches,
154143
remaining_patches: remaining,
155-
patch_contents: %{},
156144
loading: true,
157145
generating: false,
158-
search_query: "",
159146
has_more_patches: length(remaining) > 0
160147
)
161148

@@ -175,10 +162,8 @@ defmodule DiffWeb.DiffLiveView do
175162
all_patch_ids: [],
176163
loaded_patches: [],
177164
remaining_patches: [],
178-
patch_contents: %{},
179165
loading: false,
180166
generating: true,
181-
search_query: "",
182167
has_more_patches: false
183168
)
184169

@@ -221,30 +206,6 @@ defmodule DiffWeb.DiffLiveView do
221206
{:noreply, socket}
222207
end
223208

224-
def handle_event("search", %{"value" => query}, socket) do
225-
filtered_patches =
226-
if query == "" do
227-
socket.assigns.all_patch_ids
228-
else
229-
Enum.filter(socket.assigns.all_patch_ids, fn patch_id ->
230-
case Map.get(socket.assigns.patch_contents, patch_id) do
231-
nil -> false
232-
content -> String.contains?(String.downcase(content), String.downcase(query))
233-
end
234-
end)
235-
end
236-
237-
socket =
238-
assign(socket,
239-
search_query: query,
240-
loaded_patches: Enum.take(filtered_patches, 10),
241-
remaining_patches: Enum.drop(filtered_patches, 10),
242-
has_more_patches: length(filtered_patches) > 10
243-
)
244-
245-
{:noreply, socket}
246-
end
247-
248209
def handle_info({:generate_diff, package, from, to}, socket) do
249210
case Diff.Hex.diff(package, from, to) do
250211
{:ok, stream} ->
@@ -283,66 +244,24 @@ defmodule DiffWeb.DiffLiveView do
283244
end
284245

285246
def handle_info({:load_patches_and_update, patch_ids}, socket) do
286-
%{package: package, from: from, to: to} = socket.assigns
287-
288-
loaded_contents =
289-
patch_ids
290-
|> Enum.reduce(%{}, fn patch_id, acc ->
291-
case Diff.Storage.get_patch(package, from, to, patch_id) do
292-
{:ok, content} ->
293-
sanitized_content = sanitize_utf8(content)
294-
Map.put(acc, patch_id, sanitized_content)
295-
296-
{:error, reason} ->
297-
Logger.error("Failed to load patch #{patch_id}: #{inspect(reason)}")
298-
Map.put(acc, patch_id, "<div class='patch-error'>Failed to load patch</div>")
299-
end
300-
end)
301-
302-
# Update BOTH loaded_patches AND patch_contents in ONE DOM update
247+
# Simply add new patches to loaded_patches - no server memory management needed
248+
# Patches are loaded on-demand during rendering from storage
303249
new_loaded_patches = socket.assigns.loaded_patches ++ patch_ids
304250

305251
socket =
306252
socket
307253
|> assign(
308254
loaded_patches: new_loaded_patches,
309-
patch_contents: Map.merge(socket.assigns.patch_contents, loaded_contents),
310255
loading: false
311256
)
312257

313258
{:noreply, socket}
314259
end
315260

316-
def handle_info({:load_patches, patch_ids}, socket) do
317-
%{package: package, from: from, to: to} = socket.assigns
318-
319-
Logger.info("📦 Actually loading patch content for: #{inspect(patch_ids)}")
320-
321-
loaded_contents =
322-
patch_ids
323-
|> Enum.reduce(%{}, fn patch_id, acc ->
324-
case Diff.Storage.get_patch(package, from, to, patch_id) do
325-
{:ok, content} ->
326-
# Ensure content is valid UTF-8 to prevent JSON encoding errors
327-
sanitized_content = sanitize_utf8(content)
328-
Logger.info("✅ Successfully loaded patch #{patch_id} (#{byte_size(content)} bytes)")
329-
Map.put(acc, patch_id, sanitized_content)
330-
331-
{:error, reason} ->
332-
Logger.error("❌ Failed to load patch #{patch_id}: #{inspect(reason)}")
333-
Map.put(acc, patch_id, "<div class='patch-error'>Failed to load patch</div>")
334-
end
335-
end)
336-
337-
Logger.info("🎯 Loaded #{map_size(loaded_contents)} patches, updating socket assigns")
338-
339-
socket =
340-
socket
341-
|> assign(
342-
patch_contents: Map.merge(socket.assigns.patch_contents, loaded_contents),
343-
loading: false
344-
)
345-
261+
def handle_info({:load_patches, _patch_ids}, socket) do
262+
# With on-demand loading, we just need to mark loading as complete
263+
# Patch content will be loaded during rendering
264+
socket = assign(socket, loading: false)
346265
{:noreply, socket}
347266
end
348267

@@ -496,6 +415,16 @@ defmodule DiffWeb.DiffLiveView do
496415

497416
defp sanitize_utf8(content), do: content
498417

418+
defp load_patch_content(package, from, to, patch_id) do
419+
case Diff.Storage.get_patch(package, from, to, patch_id) do
420+
{:ok, content} ->
421+
sanitize_utf8(content)
422+
423+
{:error, _reason} ->
424+
"<div class='patch-error'>Failed to load patch</div>"
425+
end
426+
end
427+
499428
defp parse_diff(diff) do
500429
case String.split(diff, ":", trim: true) do
501430
[app, from, to] -> {app, from, to, build_url(app, from, to)}

0 commit comments

Comments
 (0)