fix: refactorings to remove anti-patterns

This commit is contained in:
2026-06-25 15:42:32 +02:00
parent d78cb5c07b
commit e3e94ac2d9
28 changed files with 1028 additions and 604 deletions

View File

@@ -310,14 +310,26 @@ defmodule BDS.Scripting.ApiTest do
assert {:ok, _published_template} = BDS.Templates.publish_template(template.id)
assert {:ok, running_task} =
BDS.Tasks.register_external_task("preview build", %{
group_id: "generation",
group_name: "Generation"
})
runner = self()
assert {:ok, _running_task} =
BDS.Tasks.submit_task(
"preview build",
fn report ->
report.(0.5, "halfway")
send(runner, {:task_started, self()})
receive do
:release_task -> {:ok, :done}
end
end,
%{group_id: "generation", group_name: "Generation"}
)
assert_receive {:task_started, task_pid}, 1_000
on_exit(fn ->
_ = BDS.Tasks.complete_task(running_task.id)
send(task_pid, :release_task)
end)
source =

View File

@@ -2,11 +2,14 @@ defmodule BDS.TasksTest do
use ExUnit.Case, async: false
setup do
cleanup_task_server()
original = Application.get_env(:bds, :tasks, [])
Application.put_env(:bds, :tasks, max_concurrent: 3, progress_throttle_ms: 250)
:ok = BDS.Tasks.clear_finished()
on_exit(fn ->
cleanup_task_server()
Application.put_env(:bds, :tasks, original)
_ = BDS.Tasks.clear_finished()
end)
@@ -131,74 +134,129 @@ defmodule BDS.TasksTest do
end
test "progress reports within 250ms throttle window are silently dropped" do
assert {:ok, task} = BDS.Tasks.register_external_task("fast progress")
runner = self()
assert {:ok, task} =
BDS.Tasks.submit_task("fast progress", fn report ->
send(runner, {:started, "fast progress", self()})
report.(0.25, "quarter")
report.(0.5, "half")
receive do
:release -> {:ok, :done}
end
end)
{"fast progress", worker_pid} = receive_started()
assert :ok = BDS.Tasks.report_progress(task.id, 0.25, "quarter")
assert wait_for_task(task.id, &(&1.progress == 0.25)).progress == 0.25
assert :ok = BDS.Tasks.report_progress(task.id, 0.5, "half")
assert task_id = task.id
# The 250ms throttle has not elapsed, so progress stays at 0.25.
assert wait_for_task(task_id, & &1.progress == 0.25).progress == 0.25
assert wait_for_task(task.id, &(&1.progress == 0.25)).progress == 0.25
on_exit(fn -> BDS.Tasks.complete_task(task.id) end)
send(worker_pid, :release)
assert wait_for_task(task.id, &(&1.status == :completed)).status == :completed
end
test "progress report with value 1.0 bypasses the throttle" do
assert {:ok, task} = BDS.Tasks.register_external_task("completion progress")
runner = self()
assert :ok = BDS.Tasks.report_progress(task.id, 0.25, "quarter")
assert {:ok, task} =
BDS.Tasks.submit_task("completion progress", fn report ->
send(runner, {:started, "completion progress", self()})
report.(0.25, "quarter")
report.(1.0, "done")
receive do
:release -> {:ok, :done}
end
end)
{"completion progress", worker_pid} = receive_started()
# A completion report (1.0) must go through even if throttled.
assert :ok = BDS.Tasks.report_progress(task.id, 1.0, "done")
assert wait_for_task(task.id, &(&1.progress == 1.0)).progress == 1.0
assert wait_for_task(task.id, &(&1.message == "done")).message == "done"
on_exit(fn -> BDS.Tasks.complete_task(task.id) end)
send(worker_pid, :release)
assert wait_for_task(task.id, &(&1.status == :completed)).status == :completed
end
test "external tasks are registered as running and can report progress and complete" do
test "submitted tasks are registered as running and can report progress and complete" do
assert {:ok, task} =
BDS.Tasks.register_external_task("preview build", %{
BDS.Tasks.submit_task(
"preview build",
fn report ->
report.(0.5, "halfway")
receive do
:release -> {:ok, :done}
end
end,
%{
group_id: "generation",
group_name: "Generation"
})
}
)
assert task.status == :running
assert task.status == :pending
assert task.group_id == "generation"
assert task.group_name == "Generation"
assert :ok = BDS.Tasks.report_progress(task.id, 0.5, "halfway")
progressed = wait_for_task(task.id, &(&1.progress == 0.5 and &1.message == "halfway"))
assert progressed.status == :running
assert :ok = BDS.Tasks.complete_task(task.id)
task_state = :sys.get_state(BDS.Tasks)
%{pid: worker_pid} = task_state.running[task.id]
send(worker_pid, :release)
assert wait_for_task(task.id, &(&1.status == :completed and &1.progress == 1.0)).status ==
:completed
end
test "status_snapshot exposes active task details for the desktop shell" do
runner = self()
assert {:ok, first} =
BDS.Tasks.register_external_task("preview build", %{
group_id: "generation",
group_name: "Generation"
})
BDS.Tasks.submit_task(
"preview build",
fn report ->
send(runner, {:started, "preview build", self()})
report.(0.5, "halfway")
receive do
:release -> {:ok, :done}
end
end,
%{group_id: "generation", group_name: "Generation"}
)
assert {:ok, second} =
BDS.Tasks.register_external_task("reindex text", %{
group_id: "search",
group_name: "Search"
})
BDS.Tasks.submit_task(
"reindex text",
fn _report ->
send(runner, {:started, "reindex text", self()})
receive do
:release -> {:ok, :done}
end
end,
%{group_id: "search", group_name: "Search"}
)
on_exit(fn ->
_ = BDS.Tasks.complete_task(first.id)
_ = BDS.Tasks.complete_task(second.id)
task_state = :sys.get_state(BDS.Tasks)
Enum.each([first.id, second.id], fn task_id ->
case task_state.running[task_id] do
%{pid: pid} -> send(pid, :release)
nil -> :ok
end
end)
end)
assert :ok = BDS.Tasks.report_progress(first.id, 0.5, "halfway")
_ = receive_started()
_ = receive_started()
snapshot = BDS.Tasks.status_snapshot()
@@ -250,12 +308,23 @@ defmodule BDS.TasksTest do
finished_task_ttl_ms: 1
)
assert {:ok, task} = BDS.Tasks.register_external_task("short lived")
assert {:ok, running} = BDS.Tasks.register_external_task("still running")
runner = self()
on_exit(fn -> _ = BDS.Tasks.complete_task(running.id) end)
assert {:ok, task} = BDS.Tasks.submit_task("short lived", fn _report -> {:ok, :done} end)
assert {:ok, running} =
BDS.Tasks.submit_task("still running", fn _report ->
send(runner, {:started, "still running", self()})
receive do
:release -> {:ok, :done}
end
end)
{"still running", worker_pid} = receive_started()
on_exit(fn -> send(worker_pid, :release) end)
assert :ok = BDS.Tasks.complete_task(task.id)
assert wait_for_task(task.id, &(&1.status == :completed)).status == :completed
Process.sleep(20)
@@ -273,15 +342,15 @@ defmodule BDS.TasksTest do
finished_task_ttl_ms: 50
)
assert {:ok, first} = BDS.Tasks.register_external_task("first finished")
assert {:ok, second} = BDS.Tasks.register_external_task("second finished")
assert {:ok, first} = BDS.Tasks.submit_task("first finished", fn _report -> {:ok, :done} end)
assert {:ok, second} = BDS.Tasks.submit_task("second finished", fn _report -> {:ok, :done} end)
assert :ok = BDS.Tasks.complete_task(first.id)
assert wait_for_task(first.id, &(&1.status == :completed)).status == :completed
first_timer = :sys.get_state(BDS.Tasks).finished_task_eviction_timer
assert is_reference(first_timer)
assert is_integer(Process.read_timer(first_timer))
assert :ok = BDS.Tasks.complete_task(second.id)
assert wait_for_task(second.id, &(&1.status == :completed)).status == :completed
second_timer = :sys.get_state(BDS.Tasks).finished_task_eviction_timer
assert second_timer == first_timer
@@ -336,4 +405,34 @@ defmodule BDS.TasksTest do
flunk("task did not reach expected state")
end
defp cleanup_task_server do
BDS.Tasks.list_tasks()
|> Enum.filter(&(&1.status in [:pending, :running]))
|> Enum.each(fn task ->
_ = BDS.Tasks.cancel_task(task.id)
end)
wait_until(fn ->
BDS.Tasks.list_tasks()
|> Enum.all?(&(&1.status not in [:pending, :running]))
end)
:ok = BDS.Tasks.clear_finished()
end
defp wait_until(predicate, attempts \\ 100)
defp wait_until(predicate, attempts) when attempts > 0 do
if predicate.() do
:ok
else
Process.sleep(20)
wait_until(predicate, attempts - 1)
end
end
defp wait_until(_predicate, 0) do
flunk("condition was not met")
end
end