/// Concurrent ownership of one home conflicts with the one-daemon E2E harness.
import albedo/daemon/server
import gleam/erlang/process
import gleam/result
import gleeunit/should
@external(erlang, "albedo_skills_test_support", "fixture")
fn fixture() -> #(String, String, String)
@external(erlang, "albedo_skills_test_support", "cleanup")
fn cleanup(root: String) -> Nil
pub fn second_daemon_cannot_claim_a_held_home_test() -> Nil {
let #(root, _, home) = fixture()
let claimed = process.new_subject()
// A subject only delivers to the process that created it, so the owner makes
// its own release subject and hands it back.
process.spawn(fn() {
let release = process.new_subject()
process.send(claimed, #(server.claim_home(home), release))
process.receive_forever(release)
})
let assert Ok(#(first, release)) = process.receive(claimed, 5000)
first |> should.equal(Ok(Nil))
server.claim_home(home)
|> result.map_error(fn(_) { Nil })
|> should.equal(Error(Nil))
// The connection closes when the owner's resources are freed, which can land
// just after its exit is observable, so a fresh claimant retries briefly.
process.send(release, Nil)
claim_eventually(home, 50) |> should.equal(Ok(Nil))
cleanup(root)
}
fn claim_eventually(home: String, attempts: Int) -> Result(Nil, Nil) {
let reply = process.new_subject()
process.spawn(fn() { process.send(reply, server.claim_home(home)) })
case process.receive(reply, 5000) {
Ok(Ok(Nil)) -> Ok(Nil)
_ if attempts > 1 -> {
process.sleep(20)
claim_eventually(home, attempts - 1)
}
_ -> Error(Nil)
}
}