117 lines
3.2 KiB
Elixir
117 lines
3.2 KiB
Elixir
defmodule Symbiont.QueueTest do
|
|
use ExUnit.Case, async: false
|
|
import Symbiont.TestHelpers
|
|
|
|
@moduletag :capture_log
|
|
|
|
setup do
|
|
tmp_dir = Path.join(System.tmp_dir!(), "symbiont_queue_test_#{:rand.uniform(999_999)}")
|
|
File.mkdir_p!(tmp_dir)
|
|
|
|
safe_stop(Symbiont.Queue)
|
|
{:ok, _pid} = Symbiont.Queue.start_link(data_dir: tmp_dir)
|
|
|
|
on_exit(fn ->
|
|
safe_stop(Symbiont.Queue)
|
|
File.rm_rf!(tmp_dir)
|
|
end)
|
|
|
|
%{tmp_dir: tmp_dir}
|
|
end
|
|
|
|
test "starts with empty queue" do
|
|
assert Symbiont.Queue.size() == 0
|
|
assert Symbiont.Queue.list() == []
|
|
end
|
|
|
|
test "enqueue adds tasks and returns IDs" do
|
|
{:ok, id1} = Symbiont.Queue.enqueue("Task one")
|
|
{:ok, id2} = Symbiont.Queue.enqueue("Task two", "high")
|
|
|
|
assert is_binary(id1)
|
|
assert is_binary(id2)
|
|
assert id1 != id2
|
|
assert Symbiont.Queue.size() == 2
|
|
end
|
|
|
|
test "take returns pending tasks and marks them as processing" do
|
|
{:ok, _} = Symbiont.Queue.enqueue("Task A")
|
|
{:ok, _} = Symbiont.Queue.enqueue("Task B")
|
|
{:ok, _} = Symbiont.Queue.enqueue("Task C")
|
|
|
|
taken = Symbiont.Queue.take(2)
|
|
assert length(taken) == 2
|
|
assert Enum.all?(taken, &(&1["status"] == "processing"))
|
|
|
|
# Only 1 pending remains
|
|
assert Symbiont.Queue.size() == 1
|
|
end
|
|
|
|
test "complete marks a task as done" do
|
|
{:ok, id} = Symbiont.Queue.enqueue("Complete me")
|
|
[task] = Symbiont.Queue.take(1)
|
|
assert task["id"] == id
|
|
|
|
Symbiont.Queue.complete(id, "All done!")
|
|
Process.sleep(50)
|
|
|
|
tasks = Symbiont.Queue.list()
|
|
done = Enum.find(tasks, &(&1["id"] == id))
|
|
assert done["status"] == "done"
|
|
assert done["result"] == "All done!"
|
|
end
|
|
|
|
test "fail marks a task as failed" do
|
|
{:ok, id} = Symbiont.Queue.enqueue("Fail me")
|
|
_taken = Symbiont.Queue.take(1)
|
|
|
|
Symbiont.Queue.fail(id, "something broke")
|
|
Process.sleep(50)
|
|
|
|
tasks = Symbiont.Queue.list()
|
|
failed = Enum.find(tasks, &(&1["id"] == id))
|
|
assert failed["status"] == "failed"
|
|
assert failed["result"] == "something broke"
|
|
end
|
|
|
|
test "list filters by status" do
|
|
{:ok, _} = Symbiont.Queue.enqueue("Pending 1")
|
|
{:ok, _} = Symbiont.Queue.enqueue("To complete")
|
|
|
|
# Take one task (first pending)
|
|
[taken] = Symbiont.Queue.take(1)
|
|
# Complete the taken task
|
|
Symbiont.Queue.complete(taken["id"], "done")
|
|
Process.sleep(50)
|
|
|
|
pending = Symbiont.Queue.list("pending")
|
|
assert length(pending) == 1
|
|
|
|
done = Symbiont.Queue.list("done")
|
|
assert length(done) == 1
|
|
end
|
|
|
|
test "queue persists to JSONL file", %{tmp_dir: tmp_dir} do
|
|
{:ok, _} = Symbiont.Queue.enqueue("Persistent task")
|
|
|
|
path = Path.join(tmp_dir, "queue.jsonl")
|
|
content = File.read!(path)
|
|
assert String.contains?(content, "Persistent task")
|
|
assert String.contains?(content, "pending")
|
|
end
|
|
|
|
test "queue loads tasks from file on restart", %{tmp_dir: tmp_dir} do
|
|
{:ok, _} = Symbiont.Queue.enqueue("Survivor task")
|
|
assert Symbiont.Queue.size() == 1
|
|
|
|
# Stop and restart
|
|
GenServer.stop(Symbiont.Queue)
|
|
{:ok, _} = Symbiont.Queue.start_link(data_dir: tmp_dir)
|
|
|
|
assert Symbiont.Queue.size() == 1
|
|
[task] = Symbiont.Queue.list("pending")
|
|
assert task["task"] == "Survivor task"
|
|
end
|
|
|
|
end
|