feat(cloud-scheduler): renew active leases

This commit is contained in:
2026-07-12 17:23:07 +08:00
parent b0a5b1426f
commit 1b15a8a218
4 changed files with 225 additions and 2 deletions
+172
View File
@@ -577,3 +577,175 @@ def test_expired_assignment_cannot_be_claimed(database_url: str) -> None:
assert task.status == "assigned"
finally:
database.close()
def test_active_lease_renews_for_owning_host(database_url: str) -> None:
database = CloudDatabase(database_url)
host_id = _unique_id("renew-host")
device_id = _unique_id("renew-device")
task_id = _unique_id("renew-task")
now = datetime(2026, 7, 12, 8, 0, tzinfo=UTC)
initial_expiry = now + timedelta(minutes=1)
renewed_expiry = now + timedelta(minutes=2)
try:
database.repository.upsert_host(host_id, address=None, last_seen_at=now)
database.repository.replace_host_devices(
host_id,
[_device(device_id, host_id)],
)
database.repository.enqueue_task(
ScheduledTask(
id=task_id,
goal="renew me",
workflow_definition_id=None,
constraints=TaskConstraints(),
created_at=now,
)
)
database.repository.assign_task(
task_id=task_id,
host_id=host_id,
device_id=device_id,
lease_id="renew-lease",
lease_expires_at=initial_expiry,
now=now,
)
database.repository.claim_assignment(host_id=host_id, now=now)
status = database.repository.renew_lease(
task_id=task_id,
attempt=1,
lease_id="renew-lease",
host_id=host_id,
lease_expires_at=renewed_expiry,
now=now + timedelta(seconds=30),
)
assert status == "renewed"
task = database.repository.get_task(task_id)
assert task is not None
assert task.lease_expires_at == renewed_expiry
attempts = database.repository.list_task_attempts(task_id)
assert attempts[0].lease_expires_at == renewed_expiry
finally:
database.close()
@pytest.mark.parametrize(
("attempt", "lease_id", "host_id"),
[
(2, "lease-current", "owner"),
(1, "lease-stale", "owner"),
(1, "lease-current", "foreign"),
],
)
def test_stale_or_foreign_lease_renewal_conflicts(
database_url: str,
attempt: int,
lease_id: str,
host_id: str,
) -> None:
database = CloudDatabase(database_url)
owner_id = _unique_id("renew-owner")
device_id = _unique_id("renew-conflict-device")
task_id = _unique_id("renew-conflict-task")
now = datetime(2026, 7, 12, 9, 0, tzinfo=UTC)
initial_expiry = now + timedelta(minutes=1)
try:
database.repository.upsert_host(owner_id, address=None, last_seen_at=now)
database.repository.replace_host_devices(
owner_id,
[_device(device_id, owner_id)],
)
database.repository.enqueue_task(
ScheduledTask(
id=task_id,
goal="do not renew",
workflow_definition_id=None,
constraints=TaskConstraints(),
created_at=now,
)
)
database.repository.assign_task(
task_id=task_id,
host_id=owner_id,
device_id=device_id,
lease_id="lease-current",
lease_expires_at=initial_expiry,
now=now,
)
status = database.repository.renew_lease(
task_id=task_id,
attempt=attempt,
lease_id=lease_id,
host_id=owner_id if host_id == "owner" else _unique_id("foreign"),
lease_expires_at=now + timedelta(minutes=2),
now=now + timedelta(seconds=30),
)
assert status == "conflict"
task = database.repository.get_task(task_id)
assert task is not None
assert task.lease_expires_at == initial_expiry
finally:
database.close()
def test_expired_or_missing_lease_cannot_be_renewed(database_url: str) -> None:
database = CloudDatabase(database_url)
host_id = _unique_id("expired-renew-host")
device_id = _unique_id("expired-renew-device")
task_id = _unique_id("expired-renew-task")
now = datetime(2026, 7, 12, 10, 0, tzinfo=UTC)
try:
database.repository.upsert_host(host_id, address=None, last_seen_at=now)
database.repository.replace_host_devices(
host_id,
[_device(device_id, host_id)],
)
database.repository.enqueue_task(
ScheduledTask(
id=task_id,
goal="expired renewal",
workflow_definition_id=None,
constraints=TaskConstraints(),
created_at=now,
)
)
database.repository.assign_task(
task_id=task_id,
host_id=host_id,
device_id=device_id,
lease_id="expired-renew-lease",
lease_expires_at=now + timedelta(seconds=1),
now=now,
)
assert (
database.repository.renew_lease(
task_id=task_id,
attempt=1,
lease_id="expired-renew-lease",
host_id=host_id,
lease_expires_at=now + timedelta(minutes=2),
now=now + timedelta(seconds=2),
)
== "expired"
)
assert (
database.repository.renew_lease(
task_id=_unique_id("missing-task"),
attempt=1,
lease_id="missing-lease",
host_id=host_id,
lease_expires_at=now + timedelta(minutes=2),
now=now,
)
== "not_found"
)
finally:
database.close()