Close TD-13 publishing GenServer call surface

This commit is contained in:
2026-06-12 13:13:00 +02:00
parent 4859c9708a
commit 741979fc39
5 changed files with 233 additions and 96 deletions

View File

@@ -76,18 +76,18 @@ defmodule BDS.CSM020NestedCaseTest do
end
end
describe "Publishing.handle_call :update_job uses with" do
describe "Publishing.update_job/2 uses with" do
test "source code uses with instead of case" do
source = File.read!("lib/bds/publishing.ex")
[func_source] =
Regex.scan(~r/def handle_call\(\{:update_job.*?(?=\n def |\n @impl)/s, source)
Regex.scan(~r/defp update_job\(job_id, attrs\).*?(?=\n defp |\nend)/s, source)
assert func_source |> List.first() |> String.contains?("with"),
"update_job handler should use with"
"update_job should use with"
refute func_source |> List.first() |> String.contains?("case Repo.get"),
"update_job handler should not use case Repo.get"
"update_job should not use case Repo.get"
end
end
end

View File

@@ -14,7 +14,7 @@ defmodule BDS.CSM036ImplTrueTest do
String.contains?(line, "def handle_call(")
end)
assert length(handle_call_lines) >= 5, "expected at least 5 handle_call clauses"
assert length(handle_call_lines) >= 2, "expected at least 2 handle_call clauses"
for {_line, idx} <- handle_call_lines do
preceding = Enum.at(lines, idx - 2)

View File

@@ -280,6 +280,46 @@ defmodule BDS.PublishingTest do
assert elem(html_upload, 1) == ["-q", html_index, "deploy@example.com:/srv/blog/index.html"]
end
test "upload_site batches scp mtime bookkeeping instead of calling the publishing server per file",
%{project: project, temp_dir: temp_dir} do
test_pid = self()
File.mkdir_p!(Path.join([temp_dir, "html", "posts"]))
for index <- 1..5 do
File.write!(Path.join([temp_dir, "html", "posts", "entry-#{index}.html"]), "<html />")
end
credentials = %{
ssh_host: "example.com",
ssh_user: "deploy",
ssh_remote_path: "/srv/blog",
ssh_mode: :scp
}
publishing_pid = Process.whereis(BDS.Publishing)
:erlang.trace(publishing_pid, true, [:receive])
runner = fn command, args, opts ->
send(test_pid, {:command_run, command, args, opts})
{"", 0}
end
assert {:ok, job} =
BDS.Publishing.upload_site(project.id, credentials,
command_runner: runner,
ssh_auth_sock: "/tmp/test-agent.sock"
)
assert wait_for_publish_job(job.id, &(&1.status == :completed)).status == :completed
:erlang.trace(publishing_pid, false, [:receive])
bookkeeping_calls = collect_publishing_bookkeeping_calls(publishing_pid)
assert length(bookkeeping_calls) <= 6
end
test "publish jobs survive a publishing server restart because they are persisted", %{
project: project,
temp_dir: temp_dir
@@ -325,6 +365,25 @@ defmodule BDS.PublishingTest do
end
end
defp collect_publishing_bookkeeping_calls(publishing_pid, acc \\ []) do
receive do
{:trace, ^publishing_pid, :receive, {:"$gen_call", _from, message}}
when is_tuple(message) and tuple_size(message) > 0 and
elem(message, 0) in [
:should_upload_scp_file,
:mark_uploaded_scp_file,
:filter_scp_uploads,
:record_uploaded_scp_files
] ->
collect_publishing_bookkeeping_calls(publishing_pid, [message | acc])
{:trace, ^publishing_pid, :receive, _message} ->
collect_publishing_bookkeeping_calls(publishing_pid, acc)
after
50 -> Enum.reverse(acc)
end
end
defp wait_for_publish_job(job_id, predicate, attempts \\ 100)
defp wait_for_publish_job(job_id, predicate, attempts) when attempts > 0 do